```
In [1]:
```using Symata # load Symata and enter Symata mode

There are (more or less) three ways to define functions in Symata.

- via rules
- via the host language (Julia)
- via the pure function expression head
`Function`

```
In [2]:
```f(x_) := x^2
f(2)

```
Out[2]:
```

Note the trailing underscore in `x_`

. This function is implemented via a *rule* for rewriting expressions.

The argument to `f`

can be any expression:

```
In [3]:
```[f(x+y), f("dog"), f(2.0)]

```
Out[3]:
```

```
In [4]:
```ClearAll(f) # remove the definition for `f`

This computes the `n`

th Fibonacci number.

```
In [5]:
```fib(1) := 1
fib(2) := 1
fib(n_) := fib(n-1) + fib(n-2)
fib(10)

```
Out[5]:
```

A compound statement can be written like this.

```
In [6]:
```addone(x_) := (a = 1, x + a)
addone(y)

```
Out[6]:
```

But, the variable `a`

is not local to the function. The global value of a is set.

```
In [7]:
``````
a
```

```
Out[7]:
```

To make variables local to a function, use `Module`

```
In [8]:
```g(x_) := Module([c,d],(c=1,d=3,a+d+x)) # local variables are lexically scoped.

```
In [9]:
```g(z)

```
Out[9]:
```

The global values of `c`

and `d`

are not affected.

```
In [10]:
```[c,d]

```
Out[10]:
```

`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`

.

```
In [11]:
```gt5(x_) := x > 5
g(x_Float`gt5`) := 1

```
In [12]:
```g(10.0) # The conditions in the new definition are satisfied by 10.0

```
Out[12]:
```

```
In [13]:
```[g(4.0), g(10), g(q + r)] # The definition using `Module` applies here

```
Out[13]:
```

You can do structural matching on the argument. This matches anything that has the form of a square.

```
In [14]:
```h(x_^2) := x

```
In [15]:
```[h(r^2), h(r^3), h((r+q)^2), h(Expand((r+q)^2)), 4 , 2]

```
Out[15]:
```

`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`

.

```
In [16]:
```FullForm(r^2)

```
Out[16]:
```

```
In [17]:
```ClearAll(f,h,a)

Use two trailing underscores to match one or more elements

```
In [18]:
```g(x_Symbol, p__Integer) := Apply(Plus, x^[p])

```
In [19]:
```g(y,1,4,7,10)

```
Out[19]:
```

```
In [20]:
```Apply(ClearAll, UserSyms())

```
In [21]:
```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)]

```
Out[21]:
```

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`

.

```
In [22]:
```Map(DownValues, [f,g,h,j])

```
Out[22]:
```

```
In [23]:
```ClearAll(f,g,h,j,x) # clear the symbols used in this example

```
In [24]:
```1;

```
In [25]:
```ClearAll(g,h,a,b)
# J(expr) interprets expr as Julia code
f = J((x) -> x^2 ) ;

```
In [26]:
```f(3)

```
Out[26]:
```

```
In [27]:
```f("dog") # This calls the Julia function, so we get what "dog"^2 means in Julia

```
Out[27]:
```

`:=`

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.

```
In [28]:
```f(a+b)

```
Out[28]:
```

`^`

has been "overloaded" in Julia to operate on Symata expressions. (Symata expressions are objects of type `Symata.Mxpr`

in Julia.)

Anonymous or pure functions are used like this:

```
In [29]:
```Function(x, x^2)(a)

```
Out[29]:
```

The infix operator `->`

is equivalent to `Function`

. Note that this is *not* a Julia function.

```
In [30]:
```(x -> x^2)(a)

```
Out[30]:
```

A function of two variables is defined like this:

```
In [31]:
```([x,y] -> x^2 + y^2)(3,4)

```
Out[31]:
```

```
In [32]:
```VersionInfo()

```
```

```
In [33]:
```InputForm(Now())

```
Out[33]:
```