Macro-defining macro in Racket? - macros

In Common Lisp it is relatively easy to create a macro-defining macro. For example, the following macro
(defmacro abbrev (short long)
`(defmacro ,short (&rest args)
`(,',long ,#args)))
is a macro-defining macro, because it expands to another macro.
If we now put
(abbrev def defun)
in our program, we can write def instead of defun whenever we define a new function.
Of course, abbrev can be used for other things, too. For example, after
(abbrev /. lambda)
we can write (/. (x) (+ x 1)) instead of (lambda (x) (+ x 1)). Nice. (For detailed explanation of abbrev, see http://dunsmor.com/lisp/onlisp/onlisp_20.html)
Now, my questions are:
Can I write the macro-defining macros in Racket?
If I can, how to do that? (for example, how to write something similar to
abbrev macro in Racket?)

According to this part of the Racket Guide:
(define-syntax-rule (abbrev short long)
(define-syntax-rule (short body (... ...))
(long body (... ...))))
Quoting the above link:
The only non-obvious part of its definition is the (... ...), which
“quotes” ... so that it takes its usual role in the generated macro,
instead of the generating macro.
Now
(abbrev def define)
(abbrev /. lambda)
(def f (/. (x) (+ x 1)))
(f 3)
yields
4
FWIW, it works on Guile as well, so it's no Racket-specific thing.

ad 1. Yes.
ad 2. Your example can most easily be written
#lang racket
(define-syntax (abbrev stx)
(syntax-case stx ()
[(_ short long)
#'(define-syntax short (make-rename-transformer #'long))]))
(abbrev def define)
(def x 42)
x
The example above evaluates to 42.

I find that renaming can be done simply with define or let statements:
(define =? =)
(define lr list-ref)
or:
(let ((=? =)
(lr list-ref))
(println (lr '(1 2 3) 2))
(println (=? 1 2))
(println (=? 1 1)))
Output:
3
#f
#t
There seem to be no need for any macro for this purpose.

Related

Use variable from outside (lexical) environment in a macro

How do I get this piece of macro to function as intended? -- I'd like to capture p from the lexical environment without having to send it to the macro as an argument.
(define-syntax-rule (fi a b)
(if p a b)) ;--->capture `p` from lexical env
(let ((p #t))
(fi 1 2))
Bonus thanks -- How would I do the same in CL?
In Common Lisp a macro is simply a function that takes as input the list structure of the code and returns a list structure representing the new code.
(defmacro fi (a b)
`(if p ,a ,b))
So if you were to use fi like this:
(let ((p t)) ; Common Lisp uses 't' for truth.
(fi 1 2))
It is as if you had typed:
(let ((p t))
(if p 1 2))
To see how you would get this expansion, imagine fi was a function and you gave it the arguments of 1 and 2.
(fi 1 2) => (if p 1 2)
Then took the list structure it returned and substituted it with the call to fi.
The example you give is simple because the arguments evaluate to themselves. If you had something more complicated like the expressions (* 1 1) and (+ 1 1), the actual list structure is passed in (the value of a is the list (* 1 1), and the value of b is the list (+ 1 1))
(fi (* 1 1) (+ 1 1)) => (if p (* 1 1) (+ 1 1))
You can't capture local bindings with syntax-rules. You can use syntax-case for that, though:
(define-syntax fi
(lambda (stx)
(syntax-case stx ()
((_ a b)
(with-syntax ((p (datum->syntax stx #'p)))
#'(if p a b))))))
However, using datum->syntax to capture identifiers of a fixed name like this is not ideal. If you're using Racket, it's better to use syntax parameters for this.
For Scheme implementations that don't have syntax-case but have explicit renaming, you might write the macro this way:
(define-syntax fi
(er-macro-transformer
(lambda (exp rename compare)
`(,(rename 'if) p ,(cadr exp) ,(caddr exp)))))
Some people find it simpler, but the onus is on you to rename everything that you're not intentionally capturing. In this case, we're explicitly renaming if; for most other macros that use lambda, let, etc., those all must be renamed.

Tacit programming in Lisp

Is it possible to use/implement tacit programming (also known as point-free programming) in Lisp? And in case the answer is yes, has it been done?
This style of programming is possible in CL in principle, but, being a Lisp-2, one has to add several #'s and funcalls. Also, in contrast to Haskell for example, functions are not curried in CL, and there is no implicit partial application. In general, I think that such a style would not be very idiomatic CL.
For example, you could define partial application and composition like this:
(defun partial (function &rest args)
(lambda (&rest args2) (apply function (append args args2))))
(defun comp (&rest functions)
(flet ((step (f g) (lambda (x) (funcall f (funcall g x)))))
(reduce #'step functions :initial-value #'identity)))
(Those are just quick examples I whipped up – they are not really tested or well thought-through for different use-cases.)
With those, something like map ((*2) . (+1)) xs in Haskell becomes:
CL-USER> (mapcar (comp (partial #'* 2) #'1+) '(1 2 3))
(4 6 8)
The sum example:
CL-USER> (defparameter *sum* (partial #'reduce #'+))
*SUM*
CL-USER> (funcall *sum* '(1 2 3))
6
(In this example, you could also set the function cell of a symbol instead of storing the function in the value cell, in order to get around the funcall.)
In Emacs Lisp, by the way, partial application is built-in as apply-partially.
In Qi/Shen, functions are curried, and implicit partial application (when functions are called with one argument) is supported:
(41-) (define comp F G -> (/. X (F (G X))))
comp
(42-) ((comp (* 2) (+ 1)) 1)
4
(43-) (map (comp (* 2) (+ 1)) [1 2 3])
[4 6 8]
There is also syntactic threading sugar in Clojure that gives a similar feeling of "pipelining":
user=> (-> 0 inc (* 2))
2
You could use something like (this is does a little more than -> in
Clojure):
(defmacro -> (obj &rest forms)
"Similar to the -> macro from clojure, but with a tweak: if there is
a $ symbol somewhere in the form, the object is not added as the
first argument to the form, but instead replaces the $ symbol."
(if forms
(if (consp (car forms))
(let* ((first-form (first forms))
(other-forms (rest forms))
(pos (position '$ first-form)))
(if pos
`(-> ,(append (subseq first-form 0 pos)
(list obj)
(subseq first-form (1+ pos)))
,#other-forms)
`(-> ,(list* (first first-form) obj (rest first-form))
,#other-forms)))
`(-> ,(list (car forms) obj)
,#(cdr forms)))
obj))
(you must be careful to also export the symbol $ from the package in
which you place -> - let's call that package tacit - and put
tacit in the use clause of any package where you plan to use ->, so -> and $ are inherited)
Examples of usage:
(-> "TEST"
string-downcase
reverse)
(-> "TEST"
reverse
(elt $ 1))
This is more like F#'s |> (and the shell pipe) than Haskell's ., but they
are pretty much the same thing (I prefer |>, but this is a matter of personal taste).
To see what -> is doing, just macroexpand the last example three times (in SLIME, this is accomplished by putting the cursor on the first ( in the example and typing C-c RET three times).
YES, it's possible and #danlei already explained very well. I am going to add up some examples from the book ANSI Common Lisp by Paul Graham, chapter 6.6 on function builders:
you can define a function builder like this:
(defun compose (&rest fns)
(destructuring-bind (fn1 . rest) (reverse fns)
#'(lambda (&rest args)
(reduce #'(lambda (v f) (funcall f v))
rest
:initial-value (apply fn1 args)))))
(defun curry (fn &rest args)
#'(lambda (&rest args2)
(apply fn (append args args2))))
and use it like this
(mapcar (compose #'list #'round #'sqrt)
'(4 9 16 25))
returns
((2) (3) (4) (5))
The compose function call:
(compose #'a #'b #'c)
is equlvalent to
#'(lambda (&rest args) (a (b (apply #'c args))))
This means compose can take any number of arguments, yeah.
Make a function which add 3 to argument:
(curry #'+ 3)
See more in the book.
Yes, this is possible in general with the right functions. For example, here is an example in Racket implementing sum from the Wikipedia page:
#lang racket
(define sum (curry foldr + 0))
Since procedures are not curried by default, it helps to use curry or write your functions in an explicitly curried style. You could abstract over this with a new define macro that uses currying.

scheme macro produces unexpected result

Does someone know why the following produces the expected result - (2 4 6)
(defmacro mult2 (lst)
(define (itter x)
(list '* 2 x))
`(list ,#(map itter lst)))
(mult2 (1 2 3))
while I expected that this one would (with the list identifier)
(defmacro mult2 (lst)
(define (itter x)
(list '* 2 x))
`(list ,#(map itter lst)))
(mult2 '(1 2 3))
Macro "arguments" are not evaluated. So, when you pass in '(1 2 3), i.e., (quote (1 2 3)), that is exactly what the macro sees.
P.S. You are much better off using hygienic macros in Scheme. Here's an example using syntax-case:
(define-syntax mult2
(lambda (stx)
(define (double x)
#`(* 2 #,x))
(syntax-case stx ()
((_ lst)
#`(list #,#(map double (syntax-e #'lst)))))))
(That's still not how such a macro is idiomatically written, but I tried to mirror your version as closely as possible.)
That's because the '(1 2 3) is expanded by the reader into (quote (1 2 3)). Since you only destructure one list in your macro, it won't work as expected.
Some general advice: if you're working in Racket you probably want to avoid using defmacro. That is definitely not the idiomatic way to write macros. Take a look at syntax-rules and, if you want to define more complicated macros, syntax-parse. Eli also wrote an article explaining syntax-case for people used to defmacro.

Renaming lambda in Common Lisp

I started learning Common Lisp recently, and (just for fun) decided to rename the lambda macro.
My attempt was this:
> (defmacro λ (args &body body) `(lambda ,args ,#body))
It seems to expand correctly when by itself:
> (macroexpand-1 '(λ (x) (* x x)))
(LAMBDA (X) (* X X))
But when it's nested inside an expression, execution fails:
> ((λ (x) (* x x)) 2)
(Λ (X) (* X X)) is not a function name; try using a symbol instead
I am probably missing something obvious about macro expansion, but couldn't find out what it is.
Maybe you can help me out?
edit:
It does work with lambda:
> ((lambda (x) (* x x)) 2)
4
edit 2:
One way to make it work (as suggested by Rainer):
> (set-macro-character #\λ (lambda (stream char) (quote lambda)))
(tested in Clozure CL)
In Common Lisp LAMBDA is two different things: a macro and a symbol which can be used in a LAMBDA expression.
The LAMBDA expression:
(function (lambda (x) (foo x)))
shorter written as
#'(lambda (x) (foo x))
An applied lambda expression is also valid:
((lambda (x) (+ x x)) 4)
Above both forms are part of the core syntax of Common Lisp.
Late in the definition of Common Lisp a macro called LAMBDA has been added. Confusingly enough, but with good intentions. ;-) It is documented as Macro LAMBDA.
(lambda (x) (+ x x))
expands into
(function (lambda (x) (+ x x))
It makes Common Lisp code look slightly more like Scheme code and then it is not necessary to write
(mapcar #'(lambda (x) (+ x x)) some-list)
With the LAMBDA macro we can write
(mapcar (lambda (x) (+ x x)) some-list)
Your example fails because
((my-lambda (x) (* x x)) 2)
is not valid Common Lisp syntax.
Common Lisp expects either
a data object
a variable
a function call in the form (function args...)
a function call in the form ((lambda (arglist ...) body) args...)
a macro form like (macro-name forms...)
a special form using one of the built-in special operators like FUNCTION, LET, ...
defined in the list of special operators in Common Lisp
As you can see a syntax of
((macro-name forms...) forms...)
is not a part of Common Lisp.
It is possible to read the character λ as LAMBDA:
(defun λ-reader (stream char)
(declare (ignore char stream))
'LAMBDA)
(set-macro-character #\λ #'λ-reader)
Example:
CL-USER 1 > ((λ (x) (* x x)) 3)
9
CL-USER 2 > '(λ (x) (* x x))
(LAMBDA (X) (* X X))
You might also think of LAMBDA as an operator which, given a term and a list of free variables, returns a function. This p.o.v. takes LAMBDA out of the family of basic functions and elementary macros -- at least as far as the interpreter is concerned.
(defun lambda-char (stream char)
"A lambda with only ONE arg _"
(declare (ignore char))
(let ((codes (read stream nil)))
`(lambda (_) ,codes)))
(set-macro-character #\λ #'lambda-char t)
λ(+ 1 2 _) ; => (lambda (_) (+ 1 2 _))
Maybe this is more concise, with ONLY ONE arg of _

How do you write an MIT Scheme macro to return a lambda form?

I'm baffled by trying to create the equivalent of this trivial (in Common Lisp) macro in MIT Scheme:
(defmacro funcify (exp)
`(lambda (x) ,exp))
This is for a simple personal project, a numerical equation solver based on the functions built in the second SICP lecture. I don't care that this macro is not "safe" or "hygienic" or will capture a variable if the exp references any symbols other than 'x. I'd like to be able to write
(solv '(* 60 x) '(* 90 (- x 1)))
where solv is:
(define (solv lh-exp rh-exp)
(solve (funcify lh-exp) (funcify rh-exp)))
instead of having to type
(solve (lambda (x) (* 60 x)) (lambda (x) (* 90 (- x 1))))
But can't figure out how to do this using MIT Scheme syntax-rules.
I've tried this but it doesn't work:
(define-syntax funcify
(syntax-rules ()
((funcify y) (lambda (x) y))))
;Value: funcify
(funcify x)
;Value 17: #[compound-procedure 17]
((funcify x) 10)
;Unbound variable: x
I've tried other things probably not worth mentioning involving eval but to no avail.
Also, references to good tutorials (not references) on Scheme's macro system that start with small simple examples and build up, with ample commentary, and in particular show how to convert backquote-comma style LISP macros (which to me are highly intuitive) to Scheme's syntax macro system would be great.
It cannot be done in syntax-rules. End of story.
Injecting an arbitrary identifier (x, in your case) into the output expression requires breaking hygiene, and syntax-rules does not provide any means to break hygiene. You will need to use a lower-level macro system to do this. MIT Scheme uses explicit renaming (see Matthias Benkard's answer), but for other Scheme implementations that use syntax-case, you can do it thus:
(define-syntax funcify
(lambda (stx)
(syntax-case stx ()
((_ body)
(with-syntax ((x (datum->syntax stx 'x)))
#'(lambda (x)
body))))))
The key is the (datum->syntax stx 'x) bit, which injects the symbol x as if it were in the syntactic context of the funcify invocation.
By the way, your solv must also be a macro, not a procedure, but at least it can be a syntax-rules macro:
(define-syntax solv
(syntax-rules ()
((_ lhs rhs) (solve (funcify lhs) (funcify rhs)))))
You can do basically the same thing as with defmacro by using explicit-renaming macros. The only significant difference is that you will have to destructure the input form yourself:
(define-syntax funcify
(er-macro-transformer
(lambda (form rename cmp)
(let ((exp (cadr form)))
`(,(rename 'lambda) (x) ,exp)))))