Functions

Functions use defn and fn, just like Clojure, however in Nujel we can freely choose whether we want to use brackets or parentheses.

1. Defining functions

Defining a function is best done with the (defn) macro if it is named, or (fn) for anonymous functions.

(defn double (a) (* 2 a))
(double 2)
4

(def double (fn (b) (* 2 b)))
(double 2)
4

2. Defining functions with a rest argument

In order to define a function that has a certain number of named arguments, and then a final catch-all argument you can use the dotted pair notation, just like in Scheme.

(defn multiply-vals (val . l)
      (map l (fn (v) (* v val))))
(multiply-vals 2 1 2 3)
(2 4 6)

3. Defining a functions with any amount of arguments

If you want to define a function that can take an arbitrary amount of arguments, you can just omit the brackets surrounding the argument list, this is just like you may be used from Scheme.

(defn my-list l l)
(my-list 1 2 3 4)
(1 2 3 4)

4. Documenting functions

You can document your functions behaviour by having your functions start with a string literal (don't worry it will be optimized out of the final bytecode).

Adding multiple string literals to the beginning results in the docstring being all strings joined by a linebreak, this makes it easier to add multi-line docstrings.

In order to look up the docstring for any given function (even built-in ones) you can use the (describe) function

(defn double (a)
      "Return a multiplied by 2"
      (* 2 a))
(double 2)
4

5. Function decorators

In order to tell the compiler some additional information about the function you are declaring, you can add keywords to the beginning of your function body.

Right now we only support :export and :export-as, :inline also exists but is still very buggy. More are very likely to follow though.

(defn double (a)
      :inline
      "Return α multiplied by 2"
      (* 2 a))
(double 2)
4
;; Doesn't really make much difference here, but helps especially with some simple predicates like (zero?)