using Symata; isymata() # load Symata and enter Symata mode
This is how you define a function.
f(x_) := x^2
f(2)
Note the trailing underscore in x_
. In Symata, In(2)
is actually not a function, but a rule. For the moment, we will gloss over this distinction.
The argument to f
can be any expression:
[f(x+y), f("dog"), f(2.0)]
ClearAll(f) # remove the definition for `f`
This computes the n
th Fibonacci number.
fib(1) := 1
fib(2) := 1
fib(n_) := fib(n-1) + fib(n-2)
fib(10)
A compound statement can be written like this.
addone(x_) := (a = 1, x + a)
addone(y)
But, the variable a
is not local to the function. The global value of a is set.
a
To make variables local to a function, use Module
g(x_) := Module([c,d],(c=1,d=3,a+d+x)) # local variables are lexically scoped.
g(z)
The global values of c
and d
are not affected.
[c,d]
The argument to the function f
in In(2)
can be any expression. You can also make multiple definitions that apply only when the argument satisfies some requirements. For example, the following makes a definition for g
that only applies for floating point arguments greater than 5
.
(
gt5(x_) := x > 5 ,
g(x_Float:?(gt5)) := 1
)
g(10.0) # The conditions in the new definition are satisfied by 10.0
[g(4.0), g(10), g(q + r)] # The definition in In(13) applies here
You can do structural matching on the argument. This matches anything that has the form of a square.
h(x_^2) := x
[h(r^2), h(r^3), h((r+q)^2), h(Expand((r+q)^2)), 4 , 2]
Although 4
is the square of 2
, 2
is the square of Sqrt(2)
, and q^2 +2*q*r + r^2
is the square of r+q
, none of these match. Only expressions of the form Power(expr,2)
match. We see why h(r^2)
matches by looking at the full form of r^2
.
FullForm(r^2)
Power(r,2)
ClearAll(f,h,a)
Currying is supported. By default, arguments are appended to the list of arguments. (Some builtin functions insert the arguents in different positions.)
f(a,z)(b)(c)(d)
Why did we use :=
rather than =
above ? One reason is that it is safer. The following example shows why.
(
ClearAll(f,g,h,a,b,x),
f(x_) := x^2,
g(x_) = x^2,
x = 3,
h(x_) = x^2,
j(x_) := x^2,
[f(a), g(a), h(a), j(a)]
)
In the definition of h
, x
is not a dummy variable. If you are beginning with Symata it is enough to know that :=
should be preferred and you can skip the following.
What does f(x_) := x^2
do ? When Symata evaluates this expression, it does not evaluate the right hand side, but rather holds it in its unevaluated form. When the rule is applied, say by evaluating f(a+b)
, the value that matches x_
, in this case a+b
, is substituted for x
in the right hand side and the result is evaluated with the result (a+b)^2
. Note that the value of x
at the time the definition is first evaluated has no affect on this result: The right hand side is never evaluated before subsituting for x
.
The definition g(x_) = x^2
differs in that the right hand side is evaluated when the definition is made. After this, everything is the same as for :=
. The value that matches x_
is substituted in the right hand side and the result is evaluated. If x
was unbound when the definition was made, the results are identical, because the substituion will be made before evaluating the right hand side again, so assignments to x
in the mean time will have no effect. However if x
is bound at the time of the definition, then the value of x^2
at the time of defnition is stored and the match of x_
is substituted into this expression. If x
had a value of 3
, then a+b
is substituted into 3
, which just results in 3
.
These "function" definitions actually define DownValues
. We can see that the definitions of f
,g
, and j
are the same, no matter what the future values of x
.
Map(DownValues, [f,g,h,j])
ClearAll(f,g,h,j,x) # clear the symbols used in this example
We mentioned above that these defintions are actually Rule
s, not functions. Implementing true functions in Symata has not been done yet. But, in many situations, rules are more common than true functions. However, you can use compiled functions in Symata. One way is to code such a function directly in the host language, Julia.
(
ClearAll(g,h,a,b),
f = :( (x) -> x^2 ) # :( expr ) interprets expr as Julia code
);
f(3)
f("dog") # This calls the Julia function, so we get what "dog"^2 means in Julia
Note that we did not use :=
in the definition of f
. That is, f := :((x) -> x^2 )
. This would create a new anonymous function everytime f
is called, which would be very slow.
f(a+b)
The last example works because ^
has been overloaded in Julia to operate on Symata expressions. (Symata expressions are objects of type Symata.Mxpr
in Julia.)