Skip to content

Commit

Permalink
Add section on macro arguments and evaluation.
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminion committed Jul 17, 2017
1 parent 4128223 commit 192c84a
Showing 1 changed file with 34 additions and 0 deletions.
34 changes: 34 additions & 0 deletions lll_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,40 @@ expanded in place at each invocation. If you have 10 invocations in different
places, the same code will be duplicated ten times.


Macro arguments
^^^^^^^^^^^^^^^

Note that evaluation of macro arguments is done *after* they have been
substituted. This can be very significant if the arguments are complex
expressions. It can lead to surprise explosions in gas usage, and potentially
to unexpected side-effects from evaluating the same expressions multiple times.

Consider the following::

(seq
(def 'round (a b) (* (/ a b) b))
(round 35 (exp 2 5)))

This looks innocent enough. However, since the parameter ``b`` appears twice
in the macro body, the ``exp`` expression will be evaluated twice. If the
parameter expressions are more complex, this can quickly become expensive.

One way to deal with this is for the macro to store its arguments in memory
temporarily if they appear more than once in the body::

(seq
(def 'round (a b) (seq [0]:b (* (/ a @b) @b)))
(round 35 (exp 2 5)))

As for side-effects, the following evaluates to 6 rather than 3 (which is what
you would expect were expressions evaluated before substitution)::
(seq
(def 'inc (m) {[m]:(+ @m 1) @m})
(def 'thrice (a) (+ a a a))
(return (thrice (inc 0))))


Macro example
^^^^^^^^^^^^^

Expand Down

0 comments on commit 192c84a

Please sign in to comment.