How to use macro inside a function? - macros

I created a for loop macro for clojure (based on this answer), which is as follows:
(defmacro for-loop [[sym init check change :as params] & steps]
`(loop [~sym ~init value# nil]
(if ~check
(let [new-value# (do ~#steps)]
(recur ~change new-value#))
value#)))
Now, I want to use this for-loop inside some function, but I can't figure out how to use it inside a function. Could somebody guide me on this, or give me an example with a simple usage of this inside a function?

If you turn it into a function by changing defmacro to defn, then, for example,
(for-loop '[i 0 (< i 10) (inc i)] '(* 2 i))
... produces (stripping the namespace qualifiers)
(loop [i 0 value__11639__auto__ nil]
(if (< i 10)
(let [new-value__11640__auto__ (do (* 2 i))]
(recur (inc i) new-value__11640__auto__))
value__11639__auto__))
Study this to see what it does.

Related

creating a macro for iterate in Common Lisp

I am trying to practise creating macros in Common Lisp by creating a simple += macro and an iterate macro. I have managed to create the += macro easily enough and I am using it within my iterate macro, which I am having a couple of issues with. When I try to run my macro with for example
(iterate i 1 5 1 (print (list 'one i)))
(where i is the control variable, 1 is the start value, 5 is the end value, and 1 is the increment value). I receive SETQ: variable X has no value
(defmacro += (x y)
(list 'setf x '(+ x y)))
(defmacro iterate (control beginExp endExp incExp &rest body)
(let ( (end (gensym)) (inc (gensym)))
`(do ( (,control ,beginExp (+= ,control ,inc)) (,end ,endExp) (,inc ,incExp) )
( (> ,control ,end) T)
,# body
)
)
)
I have tried multiple different things to fix it by messing with the , and this error makes me unsure as to whether the problem is with iterate or +=. From what I can tell += works properly.
Check the += expansion to find the error
You need to check the expansion:
CL-USER 3 > (defmacro += (x y)
(list 'setf x '(+ x y)))
+=
CL-USER 4 > (macroexpand-1 '(+= a 1))
(SETF A (+ X Y))
T
The macro expansion above shows that x and y are used, which is the error.
We need to evaluate them inside the macro function:
CL-USER 5 > (defmacro += (x y)
(list 'setf x (list '+ x y)))
+=
CL-USER 6 > (macroexpand-1 '(+= a 1))
(SETF A (+ A 1))
T
Above looks better. Note btw. that the macro already exists in standard Common Lisp. It is called incf.
Note also that you don't need it, because the side-effect is not needed in your iterate code. We can just use the + function without setting any variable.
Style
You might want to adjust a bit more to Lisp style:
no camelCase -> default reader is case insensitive anyway
speaking variable names -> improves readability
documentation string in the macro/function - improves readability
GENSYM takes an argument string -> improves readability of generated code
no dangling parentheses and no space between parentheses -> makes code more compact
better and automatic indentation -> improves readability
the body is marked with &body and not with &rest -> improves automatic indentation of the macro forms using iterate
do does not need the += macro to update the iteration variable, since do updates the variable itself -> no side-effects needed, we only need to compute the next value
generally writing a good macro takes a bit more time than writing a normal function, because we are programming on the meta-level with code generation and there is more to think about and a few basic pitfalls. So, take your time, reread the code, check the expansions, write some documentation, ...
Applied to your code, it now looks like this:
(defmacro iterate (variable start end step &body body)
"Iterates VARIABLE from START to END by STEP.
For each step the BODY gets executed."
(let ((end-variable (gensym "END"))
(step-variable (gensym "STEP")))
`(do ((,variable ,start (+ ,variable ,step-variable))
(,end-variable ,end)
(,step-variable ,step))
((> ,variable ,end-variable) t)
,#body)))
In Lisp the first part - variable, start, end, step - usually is written in a list. See for example DOTIMES. This makes it for example possible to make step optional and to give it a default value:
(defmacro iterate ((variable start end &optional (step 1)) &body body)
"Iterates VARIABLE from START to END by STEP.
For each step the BODY gets executed."
(let ((end-variable (gensym "END"))
(step-variable (gensym "STEP")))
`(do ((,variable ,start (+ ,variable ,step-variable))
(,end-variable ,end)
(,step-variable ,step))
((> ,variable ,end-variable) t)
,#body)))
Let's see the expansion, formatted for readability. We use the function macroexpand-1, which does the macro expansion only one time - not macro expanding the generated code.
CL-USER 10 > (macroexpand-1 '(iterate (i 1 10 2)
(print i)
(print (* i 2))))
(DO ((I 1 (+ I #:STEP2864))
(#:END2863 10)
(#:STEP2864 2))
((> I #:END2863) T)
(PRINT I)
(PRINT (* I 2)))
T
You can see that the symbols created by gensym are also identifiable by their name.
We can also let Lisp format the generated code, using the function pprint and giving a right margin.
CL-USER 18 > (let ((*print-right-margin* 40))
(pprint
(macroexpand-1
'(iterate (i 1 10 2)
(print i)
(print (* i 2))))))
(DO ((I 1 (+ I #:STEP2905))
(#:END2904 10)
(#:STEP2905 2))
((> I #:END2904) T)
(PRINT I)
(PRINT (* I 2)))
I figured it out. Turns out I had a problem in my += macro and a couple of other places in my iterate macro. This is the final working result. I forgot about the , while i was writing the += macro. The other macro declerations where out of order.
(defmacro += (x y)
`(setf ,x (+ ,x ,y)))
(defmacro iterate2 (control beginExpr endExpr incrExpr &rest bodyExpr)
(let ((incr(gensym))(end(gensym)) )
`(do ((,incr ,incrExpr)(,end ,endExpr)(,control ,beginExpr(+= ,control ,incr)))
((> ,control ,end) T)
,# bodyExpr
)
)
)

Rewrite loop as a mapcar

Looking at Practical Common Lisp, we're looking at a simple automated unit test framework. We're trying to write a macro to be used as such:
(check (= (+ 1 2) 3) (= (- 1 4) 9))
This should expand to something using a previously defined function report-result. The suggested implementation is:
(defmacro check (&body forms)
`(progn
,#(loop for f in forms collect `(report-result ,f ',f))))
However, that expansion seems rather procedural to me. I wanted to replace the loop with a mapcar to expand to something like this:
(mapcar #'(lambda (form) (report-result form 'form)) (list form-1 ... form-n))
However, I'm clearly lacking the macro-writing skills to do so. Can someone come up with one such macro?
In case it's relevant, this is the definition of report-result:
(defun report-result (result form)
(format t "~:[FAIL~;pass~] ... ~a~%" result form))
It's indeed fairly simple: you just place the collect expression into the body of your mapcar:
(defmacro check (&body forms)
`(progn
,#(mapcar #'(lambda (form)
`(report-result ,form ',form))
forms)))
You don't really need to know anything about the "macro-y" stuff that's going on, in order to do the replacement you want, which is simply replacing a loop with some other equivalent expression: it will work just as well in a macro context as it would outside.
If you want to expand to a mapcar you can, but there's no real reason to do so, since the list's size is known at compile time. Here's what that would look like:
(defmacro check (&body forms)
`(let ((results (list ,#(mapcar #'(lambda (form)
`(list ,form ',form))
forms))))
(mapcar #'(lambda (result)
(report-result (car result) (cadr result)))
results)))
Which expands like so
> (macroexpand-1 '(check (+ 1 2) (* 2 3)))
(let ((results (list (list (+ 1 2) '(+ 1 2))
(list (* 2 3) '(* 2 3)))))
(mapcar #'(lambda (result) (report-result (car result) (cadr result)))
results))
Which as you can see is rather awkward: the macro already has the forms like (+ 1 2) available to it, but in order to preserve them to runtime for the mapcar lambda to see, you have to emit the input form twice. And you have to produce the whole list to map over, rather than just producing a list that's "finished" to begin with. Additionally, this produces a list as output, and requires having all the inputs and outputs in memory at once: the original macro with progn produced the inputs and outputs one at a time, and discarded them when finished.

How to find sum of n number using clojure for loop macro?

I'm using a for-loop macro in clojure:
(defmacro for-loop [[sym initial check-exp post-exp] & steps]
`(loop [~sym ~initial]
(if ~check-exp
(do
~#steps
(recur ~post-exp)))))
I want to write a simple function to find the sum of n numbers like:
for(int i=1; i<n; i++)
sum=sum+i;
How can I do this in clojure using the for-loop macro?
First of all, there is no need to use a macro here. Second, your use of do with the final call to recur will prevent the macro from ever returning a value other than nil as discussed in Lee's answer. That you should use when instead of if when you're not really providing an else case is only a slight matter, but hints at a possible better solution: Use the else case to return the result. For this to work you need to introduce an accumulator into the equation.
(defmacro for-loop [[sym initial result initial-result check-exp post-exp] & steps]
`(loop [~sym ~initial
~result ~initial-result]
(if ~check-exp
(do
~#steps
(recur ~#post-exp))
~result)))
This is still pretty ugly, but allows you to solve your summing task like this, actually not requiring any intermediate steps:
(for-loop [i 0 r 0 (< i n) ((inc i) (+ r i))] nil)
If you macro-expand this, it's easier to see that is going on:
(pprint (macroexpand-1 '(for-loop [i 0 r 0 (< i n) ((inc i) (+ r i))] nil)))
==> (clojure.core/loop [i 0 r 0]
(if (< i n)
(do nil
(recur (inc i) (+ r i)))
r))
It would be nice if one would not have to explicitly name and use the accumulator but just use the results from the steps, but as the steps will likely need to refer to any intermediate values build up so far as in this example, there is no way around it.
(def sum (atom 0))
(def n 100)
(for-loop [i 0 (< i n) (inc i)] (swap! sum #(+ % i)))

Clojure Nested Macro

Is it possible to macro returned macro? I would like to simplify the code maximum, and I can do this using a macro that returns the function. However, it is too much overhead and it is too slow. To keep the code more readable, I did not use type hints, but even with them my code is ~ 5x slower.
My English is not very precise, so I write what I have and what I wanted to have.
I have this...
(defmacro series [java-array]
`(fn
([i#]
(aget ~java-array i#))
([start# stop#]
(let [limit# (unchecked-subtract-int stop# start#)
result# (double-array limit#)]
(loop [i# 0]
(if (< i# limit#)
(let [r# (double (aget ~java-array i#))]
(aset result# i# r#)
(recur (inc i#)))
result#))))))
I want something like this...
(defmacro series [java-array]
`(defmacro blabla
([i#]
`(aget ~~java-array i#))
([start# stop#]
`(let [limit# (unchecked-subtract-int stop# start#)
result# (double-array limit#)]
(loop [i# 0]
(if (< i# limit#)
(let [r# (double (aget ~~java-array i#))]
(aset result# i# r#)
(recur (inc i#)))
result#))))))
But when I call this...
Wrong number of args (1) passed to: blabla
A simpler example.
I have a lot of java arrays. I do not want to use aget. I want macro to expand to (aget array-name i). I write a macro that expand to (fn [n] (aget array-name i)), but this is unnecessary overhead.
(defmacro series [arr]
`(fn [i#]
(aget (longs ~arr) (int i#))))
I now declare the series, such as "date", and call it in this way (date i), which will return me "i" element of the array.
I think what you're looking for is a way to declare local macros within functions. The clojure.tools.macro package has a macrolet form, which I think you should be able to wrangle into creating a macro for local array lookups.
Here's a little example I put together:
; project.clj
(defproject testproject "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.5.0"]
[org.clojure/tools.macro "0.1.2"]])
; src/testproject/core.clj
(ns testproject.core
(:require [clojure.tools.macro :refer [macrolet]]))
(defn my-test []
(let [n 1000
arr (int-array n (range 10))]
(macrolet [(lookup [i] (list `aget 'arr i))]
(loop [i 0, acc 0]
(if (< i n)
(recur (inc i) (+ acc (lookup i)))
acc)))))
In the example I use macrolet to declare a macro called lookup that will cause (lookup 5) to expand into (lookup arr 5), which is what I think you're looking for.
Notice how you have to be careful when referencing arr from within the local macro definition. If you just declared the macro as`(aget arr ~i), then it tries to find a fully-qualified symbol arr, which doesn't exist. You could alternatively declare the macro as `(aget ~'arr ~i), but I felt that (list `aget 'arr i) looked a lot nicer.
Now you can take it one step further and use defmacro to create a macro that includes macrolet inside, which you can use to simplify the declaration of arrays with a local lookup macro. We leave this as an exercise for the reader.
Since macros are so subtle, and nesting macros in macros only makes things worse, I decided it would probably be more helpful to just give an example and let you figure out how it works:
(defmacro lookup-binding [[fn-sym value] & body]
(let [array-sym (symbol (str fn-sym "-raw"))]
`(let [~array-sym ~value]
(macrolet [(~fn-sym [i#] (list aget '~array-sym i#))]
~#body))))
(defn my-test2 []
(let [n 1000]
(lookup-binding [arr (int-array n (range 10))]
(loop [i 0, acc 0]
(if (< i n)
(recur (inc i) (+ acc (arr i)))
acc)))))
Disclaimer: I'm only trying to show that this is possible, not that it's a good idea. I personally don't think all this extra complexity is worth avoiding aget. I'd suggest just using aget since it's only a few extra characters, and it will make your code more clear/readable.

How do I memoize a recursive function in Lisp?

I'm a Lisp beginner. I'm trying to memoize a recursive function for calculating the number of terms in a Collatz sequence (for problem 14 in Project Euler). My code as of yet is:
(defun collatz-steps (n)
(if (= 1 n) 0
(if (evenp n)
(1+ (collatz-steps (/ n 2)))
(1+ (collatz-steps (1+ (* 3 n)))))))
(defun p14 ()
(defvar m-collatz-steps (memoize #'collatz-steps))
(let
((maxsteps (funcall m-collatz-steps 2))
(n 2)
(steps))
(loop for i from 1 to 1000000
do
(setq steps (funcall m-collatz-steps i))
(cond
((> steps maxsteps)
(setq maxsteps steps)
(setq n i))
(t ())))
n))
(defun memoize (fn)
(let ((cache (make-hash-table :test #'equal)))
#'(lambda (&rest args)
(multiple-value-bind
(result exists)
(gethash args cache)
(if exists
result
(setf (gethash args cache)
(apply fn args)))))))
The memoize function is the same as the one given in the On Lisp book.
This code doesn't actually give any speedup compared to the non-memoized version. I believe it's due to the recursive calls calling the non-memoized version of the function, which sort of defeats the purpose. In that case, what is the correct way to do the memoization here? Is there any way to have all calls to the original function call the memoized version itself, removing the need for the special m-collatz-steps symbol?
EDIT: Corrected the code to have
(defvar m-collatz-steps (memoize #'collatz-steps))
which is what I had in my code.
Before the edit I had erroneously put:
(defvar collatz-steps (memoize #'collatz-steps))
Seeing that error gave me another idea, and I tried using this last defvar itself and changing the recursive calls to
(1+ (funcall collatz-steps (/ n 2)))
(1+ (funcall collatz-steps (1+ (* 3 n))))
This does seem to perform the memoization (speedup from about 60 seconds to 1.5 seconds), but requires changing the original function. Is there a cleaner solution which doesn't involve changing the original function?
I assume you're using Common-Lisp, which has separate namespaces for variable and function names. In order to memoize the function named by a symbol, you need to change its function binding, through the accessor `fdefinition':
(setf (fdefinition 'collatz-steps) (memoize #'collatz-steps))
(defun p14 ()
(let ((mx 0) (my 0))
(loop for x from 1 to 1000000
for y = (collatz-steps x)
when (< my y) do (setf my y mx x))
mx))
Here is a memoize function that rebinds the symbol function:
(defun memoize-function (function-name)
(setf (symbol-function function-name)
(let ((cache (make-hash-table :test #'equal)))
#'(lambda (&rest args)
(multiple-value-bind
(result exists)
(gethash args cache)
(if exists
result
(setf (gethash args cache)
(apply fn args)))))))
You would then do something like this:
(defun collatz-steps (n)
(if (= 1 n) 0
(if (evenp n)
(1+ (collatz-steps (/ n 2)))
(1+ (collatz-steps (1+ (* 3 n)))))))
(memoize-function 'collatz-steps)
I'll leave it up to you to make an unmemoize-function.
something like this:
(setf collatz-steps (memoize lambda (n)
(if (= 1 n) 0
(if (evenp n)
(1+ (collatz-steps (/ n 2)))
(1+ (collatz-steps (1+ (* 3 n))))))))
IOW: your original (non-memoized) function is anonymous, and you only give a name to the result of memoizing it.
Note a few things:
(defun foo (bar)
... (foo 3) ...)
Above is a function that has a call to itself.
In Common Lisp the file compiler can assume that FOO does not change. It will NOT call an updated FOO later. If you change the function binding of FOO, then the call of the original function will still go to the old function.
So memoizing a self recursive function will NOT work in the general case. Especially not if you are using a good compiler.
You can work around it to go always through the symbol for example: (funcall 'foo 3)
(DEFVAR ...) is a top-level form. Don't use it inside functions. If you have declared a variable, set it with SETQ or SETF later.
For your problem, I'd just use a hash table to store the intermediate results.
Changing the "original" function is necessary, because, as you say, there's no other way for the recursive call(s) to be updated to call the memoized version.
Fortunately, the way lisp works is to find the function by name each time it needs to be called. This means that it is sufficient to replace the function binding with the memoized version of the function, so that recursive calls will automatically look up and reenter through the memoization.
huaiyuan's code shows the key step:
(setf (fdefinition 'collatz-steps) (memoize #'collatz-steps))
This trick also works in Perl. In a language like C, however, a memoized version of a function must be coded separately.
Some lisp implementations provide a system called "advice", which provides a standardized structure for replacing functions with enhanced versions of themselves. In addition to functional upgrades like memoization, this can be extremely useful in debugging by inserting debug prints (or completely stopping and giving a continuable prompt) without modifying the original code.
This function is exactly the one Peter Norvig gives as an example of a function that seems like a good candidate for memoization, but which is not.
See figure 3 (the function 'Hailstone') of his original paper on memoization ("Using Automatic Memoization as a Software Engineering Tool in Real-World AI Systems").
So I'm guessing, even if you get the mechanics of memoization working, it won't really speed it up in this case.
A while ago I wrote a little memoization routine for Scheme that used a chain of closures to keep track of the memoized state:
(define (memoize op)
(letrec ((get (lambda (key) (list #f)))
(set (lambda (key item)
(let ((old-get get))
(set! get (lambda (new-key)
(if (equal? key new-key) (cons #t item)
(old-get new-key))))))))
(lambda args
(let ((ans (get args)))
(if (car ans) (cdr ans)
(let ((new-ans (apply op args)))
(set args new-ans)
new-ans))))))
This needs to be used like so:
(define fib (memoize (lambda (x)
(if (< x 2) x
(+ (fib (- x 1)) (fib (- x 2)))))))
I'm sure that this can be ported to your favorite lexically scoped Lisp flavor with ease.
I'd probably do something like:
(let ((memo (make-hash-table :test #'equal)))
(defun collatz-steps (n)
(or (gethash n memo)
(setf (gethash n memo)
(cond ((= n 1) 0)
((oddp n) (1+ (collatz-steps (+ 1 n n n))))
(t (1+ (collatz-steps (/ n 2)))))))))
It's not Nice and Functional, but, then, it's not much hassle and it does work. Downside is that you don't get a handy unmemoized version to test with and clearing the cache is bordering on "very difficult".