I'm reading the book of Leonid Shifrin, and I love the way the book explains the core in Mathematica
. As everything is an expression, now I understand that, there are no real function or variable in Mathematica
. Function is such an indexed variable containing several rules.
Head /@ {Sin, Sin[x], x, 3}
AtomQ /@ {Sin, Sin[x], x, 3}
Attributes /@ {Symbol, String, Integer}
{Symbol, Sin, Symbol, Integer}
{True, False, True, True}
{{Locked, Protected}, {Protected}, {Protected}}
So both function Sin
and variable x
are Symbol
. Everything in Mathematica
is Symbol, String, or Number. This principle helps me a lot.
f = Sin;
g = Sin[x];
{f[x], g[x]}
{Sin[x], Sin[x][x]}
Without this principle, a beginner can think that the function g
equals to the function Sin[x]
. So g[x]
should return as Sin[x]
. And he can think that the definition f = Sin
is impossible because Sin should be expressed as a function Sin[something].
But here, we can see that Mathematica
is very flexible. If we consider Sin
as a variable, so assigning f = Sin
is totally correct. And g[x]
is not equal to Sin[x]
, but Sin[x][x]
. I think this is a very basic thing, that a beginner should remember.
So many books on Mathematica
don't explain these principles, they just teach how to use the command. But understanding the core in Mathematica for me is much more important, because it is the basic to master Mathematica
programming style. Thank you Leonid Shifrin.
As now, I see that functions and variable are Symbol
. Beside Symbol
, could we use another type as a variable?
For example, I would like to have a list of 40 variables a1=1, a2=2, a3=3,... a40=40. But I don't want to use indexed variable a[1]
, a[2]
, a[3]
, a[40]
because for me, it is just one variable a
with several index.
Of course, the natural way is typing a1 = 1
, a2 = 2
, ... a40 = 40
manually. But how to do it in automatically in a loop or table way?
My first try is to generate "a1"
, "a2"
, ... "a40"
as String
.
"a" <> # & /@ ToString /@ Table[i, {i, 3}]
{"a1", "a2", "a3"}
But String
can not be used as variable....
{"a1", "a2", "a3"} = {1, 2, 3}
Set::setraw: Cannot assign to raw object a1. >>
So how to generate a list of variable? a1, a2, a3...?
I try to use ToExpression
to convert the String to Expression, I got a list of variable a1,a2,a3.
ToExpression["a" <> # & /@ ToString /@ Table[i, {i, 3}]]
{a1, a2, a3}
I'm trying to assign the value: (*)
ToExpression["a" <> # & /@ ToString /@ Table[i, {i, 3}]]] = {1, 2, 3}
Set::write: Tag ToExpression in ToExpression[{a1,a2,a3}] is Protected.
>
What is wrong here. I try to add Evaluate on the l.h.s:
Evaluate@ToExpression[
"a" <> # & /@ ToString /@ Table[i, {i, 3}]] = {1, 2, 3}
{a1, a2, a3}
{1, 2, 3}
Finally, it works. But are there any another way than this way (too long) to generate a list of variable a1
, a2
, a40
? and why I need to Evaluate
the l.h.s at (*) before Set
to {1,2,3} ?
Edit: Thanks to @RunnyKine, now I understand why I must Evaluate
at (*) before using Set
.
"because when using Set, Mathematica evaluates the R.H.S. and leaves the L.H.S. unevaluated."