Everything should be a function. Everything. Especially in *Julia*, for
performance related reasons that are far beyond the scope of this material. So
one of the first, most significant piece of knowledge to acquire is: how do I
declare a function?

Let us start with a function that says (or rather, `print`

, as we call it)
`"Hello"`

:

```
function hello()
return print("Hello")
end
```

```
hello (generic function with 1 method)
```

This is a `generic function`

with `1 method`

, and for now we will ignore this
information (and get back to it only when discussing dispatch in the next
module). We can call our function by using its name:

```
hello()
```

```
Hello
```

Note that we use the parentheses (`()`

) to make a difference between *talking
about the function* (`hello`

) and *executing the function* (`hello()`

). There
is nothing within the parentheses (yet), but without them, this would not
work.

Let’s get something out of the way immediately. We do not need to write
`function`

and `end`

, as we can simply get the same effect with a one-liner
function:

```
hello_oneline() = print("Hello")
hello_oneline()
```

```
Hello
```

This is, at times, a little more convenient. For example, we can define the logit and logistic functions on one line (each!):

```
logistic(x) = 1.0 / (1.0 + exp(-x))
```

```
logistic (generic function with 1 method)
```

```
logit(p) = log(p / (1.0 - p))
```

```
logit (generic function with 1 method)
```

Hey there’s something new! We have added `x`

(and `p`

) in the declaration of
the function. What are these?

They are called *argument*. The arguments of a function (and their type!) are
called its *signature* (there is a second part to the signature of a function,
and we will get to it much, much later).

We can have many arguments to a function. For example, we can have a function
called `linear`

, with three arguments `x`

, `m`

, and `b`

, which would return
$mx+b$.

```
function linear(x, m, b)
return m*x+b
end
```

```
linear (generic function with 1 method)
```

We can check that it works, maybe by testing different values of `x`

, with the
equation $0.2x+1.4$:

```
for x in 0.0:0.1:0.5
@info linear(x, 0.2, 1.4)
end
```

```
[ Info: 1.4
[ Info: 1.42
[ Info: 1.44
[ Info: 1.46
[ Info: 1.48
[ Info: 1.5
```

But how do we know that `m`

is `0.2`

and `b`

is `1.4`

? Well, these arguments
are what we call *positional arguments*; they are read in the order where they
are declared in the function signature.

One thing that the function cannot do yet is deal with us giving it no arguments. We can fix this by giving default values to some arguments. Note how we also change the name of the arguments to make it far more obvious what the function will do:

```
function linear(x, slope, intercept=0.0)
return slope*x+intercept
end
```

```
linear (generic function with 2 methods)
```

*Good Thing*. Most text editors will auto-complete, but most importantly, it makes the code readable by humans.

One small (or, well, actually, gigantic) caveat with default values for
positional arguments is that you *cannot* mix and match the order: the
arguments with default values *must* come last.

There is another way to declare a function, and we will make ample use of it
in the next modules – we can declare an *anonymous* function using a notation
very close to the standard mathematical notation of declaring a function. For
example:

```
f = (x) -> x^2
```

```
#1 (generic function with 1 method)
```

This makes `f`

a function returning the square of its argument:

```
f(2.0)
```

```
4.0
```

In this module, we went through the different ways to declare a function. In
the following module, we will go in a lot of details into the dispatch
mechanism, which is central to *Julia*’s philosophy.