How do I map a macro across a list in Scheme? - macros

I have a Scheme macro and a long list, and I'd like to map the macro across the list, just as if it were a function. How can I do that using R5RS?
The macro accepts several arguments:
(mac a b c d)
The list has
(define my-list ((a1 b1 c1 d1)
(a2 b2 c2 d2)
...
(an bn cn dn)))
And I'd like to have this:
(begin
(mac a1 b1 c1 d2)
(mac a2 b2 c2 d2)
...
(mac an bn cn dn))
(By the way, as you can see I'd like to splice the list of arguments too)

Expanding on z5h's answer of using eval, the methods below show how a map-macro macro can be written if interaction-environment in implemented in the version of R5RS in use:
(define test-list '((1 2 3 4)
(5 6 7 8)))
;Or if your version of scheme implments interaction-environment then:
(define-syntax trade
(syntax-rules ()
((_ a b c d) (display (list b a d c)))))
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;Careful this is not really mapping. More like combined map and apply.
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(define-syntax map-macro
(syntax-rules ()
((_ mac ls) (let ((mac-list (map (lambda (lst) (cons 'trade lst)) ls)))
(eval
`(begin
,#mac-list)
(interaction-environment))))
))
(map-macro trade test-list)
;outputs: (2 1 4 3)(6 5 8 7)
So that last map-macro call evaluates the following:
What ends up getting evaluated from (map-macro trade test-list) is:
(begin
(trade 1 2 3 4)
(trade 5 6 7 8))
Which is not quite a map, but I believe it does answers your question.

Syntactic extensions are expanded into
core forms at the start of evaluation
(before compilation or interpretation)
by a syntax expander. -Dybvig, "The
Scheme Programming Language:
A macro operates on syntax. This happens before compilation or execution. It gives you another way of writing the same code.
A function operates on variables and values (which might be lists, atoms, numbers, etc) who's value is known when the function is invoked.
So mapping a macro doesn't make sense. You're asking to invoke something (macro expansion) that already happened long ago.
If you need something to write code for you and evaluate it at runtime, then might be one of those cases where you need eval.

Would something like
(map (lambda (l) (mac (car l) (caar l) (caaar l) (caaaar l))) mylist)
work?

Related

Difference between an implementation of 'when' as a function vs. as a macro

What exactly is different between these implementations of 'when'?
(define-syntax when
(syntax-rules ()
((_ pred b1 ...)
(if pred (begin b1 ...)))))
vs.
(define (my-when pred b1 ...)
(if pred (begin b1 ...)))
For example, when 'my-when' is used in this for loop macro:
(define-syntax for
(syntax-rules ()
((_ (i from to) b1 ...)
(let loop((i from))
(my-when (< i to)
b1 ...
(loop (+ i 1)))))))
an error occurs:
(for (i 0 10) (display i))
; Aborting!: maximum recursion depth exceeded
I do not think 'when' can be implemented as a function, but I do not know why...
Scheme has strict semantics.
This means that all of a function's parameters are evaluated before the function is applied to them.
Macros take source code and produce source code - they don't evaluate any of their parameters.
(Or, well, I suppose they do, but their parameters are syntax - language elements - rather than what you normally think of as values, such as numbers or strings. Macro programming is meta-programming. It's important to be aware of which level you're programming at.)
In your example this means that when my-when is a function, (loop (+ i 1)) must be evaluated before my-when can be applied to it.
This leads to an infinite recursion.
When it's a macro, the my-when form is first replaced with the equivalent if-form
(if (< i to)
(begin
b1 ...
(loop (+ i 1))))
and then the whole thing is evaluated, which means that (loop (+ i 1)) only gets evaluated when the condition is true.
If you implement when as a procedure like you did, then all arguments are evaluated. In your for implementation, the evaluation would be processed like this:
evaluate (< i to)
evaluate expansion result of b1 ...
evaluate (loop (+ i 1)) <- here goes into infinite loop!
evaluate my-when
Item 1-3 can be reverse or undefined order depending on your implementation but the point is nr. 4. If my-when is implemented as a macro, then the macro is the first one to be evaluated.
If you really need to implement with a procedure, then you need to use sort of delaying trick such as thunk. For example:
(define (my-when pred body) (if (pred) (body)))
(my-when (lambda () (< i 10)) (lambda () (display i) (loop (+ i 1))))

Define function for evaluating infix expressions in Lisp

I am not very good in Lisp and I need to do a function which allows evaluating of infix expressions. For example: (+ 2 3) -> (infixFunc 2 + 3). I tried some variants, but none of them was successful.
One of them:
(defun calcPrefInf (a b c)
(funcall b a c))
OK, let's do it just for fun. First, let's define order of precedence for operations, since when one deals with infix notation, it's necessary.
(defvar *infix-precedence* '(* / - +))
Very good. Now imagine that we have a function to-prefix that will convert infix notation to polish prefix notation so Lisp can deal with it and calculate something after all.
Let's write simple reader-macro to wrap our calls of to-prefix, for aesthetic reasons:
(set-dispatch-macro-character
#\# #\i (lambda (stream subchar arg)
(declare (ignore sub-char arg))
(car (reduce #'to-prefix
*infix-precedence*
:initial-value (read stream t nil t)))))
Now, let's write a very simple function to-prefix that will convert infix notation to prefix notation in given list for given symbol.
(defun to-prefix (lst symb)
(let ((pos (position symb lst)))
(if pos
(let ((e (subseq lst (1- pos) (+ pos 2))))
(to-prefix (rsubseq `((,(cadr e) ,(car e) ,(caddr e)))
e
lst)
symb))
lst)))
Good, good. Function rsubseq may be defined as:
(defun rsubseq (new old where &key key (test #'eql))
(labels ((r-list (rest)
(let ((it (search old rest :key key :test test)))
(if it
(append (remove-if (constantly t)
rest
:start it)
new
(r-list (nthcdr (+ it (length old))
rest)))
rest))))
(r-list where)))
Now it's time to try it!
CL-USER> #i(2 + 3 * 5)
17
CL-USER> #i(15 * 3 / 5 + 10)
19
CL-USER> #i(2 * 4 + 7 / 3)
31/3
CL-USER> #i(#i(15 + 2) * #i(1 + 1))
34
etc.
If you want it to work for composite expressions like (2 + 3 * 5 / 2.4), it's better to convert it into proper prefix expression, then evaluate it. You can find some good example of code to do such convetion here: http://www.cs.berkeley.edu/~russell/code/logic/algorithms/infix.lisp or in Piter Norvigs "Paradigs of Artificial Intelligence Programming" book. Code examples here: http://www.norvig.com/paip/macsyma.lisp
It's reall too long, to be posted in the aswer.
A different approach for "evaluating infix expressions" would be to enable infix reading directly in the Common Lisp reader using the "readable" library, and then have users use the notation. Then implement a traditional Lisp evaluator (or just evaluate directly, if you trust the user).
Assuming you have QuickLisp enabled, use:
(ql:quickload "readable")
(readable:enable-basic-curly)
Now users can enter any infix expression as {a op b op c ...}, which readable automatically maps to "(op a b c ...)". For example, if users enter:
{2 + 3}
the reader will return (+ 2 3). Now you can use:
(eval (read))
Obviously, don't use "eval" if the user might be malicious. In that case, implement a function that evaluates the values the way you want them to.
Tutorial here:
https://sourceforge.net/p/readable/wiki/Common-lisp-tutorial/
Assuming that you're using a lisp2 dialect, you need to make sure you're looking up the function you want to use in the function namespace (by using #'f of (function f). Otherwise it's being looked up in the variable namespace and cannot be used in funcall.
So having the definition:
(defun calcPrefInf (a b c)
(funcall b a c))
You can use it as:
(calcPrefInf 2 #'+ 3)
You can try http://www.cliki.net/infix.
(nfx 1 + (- x 100)) ;it's valid!
(nfx 1 + (- x (3 * 3))) ;it's ALSO valid!
(nfx 1 + (- x 3 * 3)) ;err... this can give you unexpected behavior

Recursive function in Lisp

I have to build a function which determines if I have a conjunction of well-formed formulas built in this way :
cong ::= '(' and wff wff ...')'
Let's suppose I have the code which determines if a formula is wff. The function must first check if the first element of the list is 'and and then check recursively the rest of the sublists if they are wff. Note that p is also a wff so it doesn't neccessarily have to be a sublist.
Example : (and (or a b v) (and a b d) m n)
Here's what I tried which doesn't work for me :
(defun cong (fbf)
(and (eq (first fbf) 'and )
(reduce (lambda (x y) (and x y))
(mapcar #'wff (rest fbf)))))
Assuming a working wff predicate, your code will work. For example, using numberp as the predicate:
(defun cong (fbf)
(and (eq (first fbf) 'and)
(reduce (lambda (x y) (and x y))
(mapcar #'numberp (rest fbf)))))
Works fine:
CL-USER> (cong '(and 1 2 3 4 5))
T
CL-USER> (cong '(and 1 2 3 4 foo))
NIL
CL-USER> (cong '(1 2 3 4))
NIL
Note, that this can be done more easily:
(defun cong (fbf)
(and (eq (first fbf) 'and)
(every #'wff (cdr fbf))))
Also, note that in CL, by convention, predicates usually should end in p.
So, your, given your comment above, your problem is the wff predicate, which doesn't seem to work for atoms. Since you mentioned that p satisfies wff, that predicate is plain wrong, but if you have to use it (assuming this is some kind of homework), just check if the element at hand is a cons:
(defun cong (fbf)
(and (eq (first fbf) 'and)
(every #'wff (remove-if-not #'consp (cdr fbf)))))
This assumes that every atom satisfies wff. Thus, they won't change the outcome of a conjunction and can be dropped. Otherwise, you'd have to write another predicate to check for atoms satisfying wff or, which would be the right thing to do, fix wff in the first place.
Also, note that none of this really involves recursion, since you're only asking how to apply a predicate to a list and take the conjunction of the results.

Lisp IF-THEN-ELSE Lambda Calc Implementation

I made this IF-THEN-ELSE Lambda Calculus code
(defvar IF-THEN-ELSE
#'(lambda(con)
#'(lambda(x)
#'(lambda(y)
#'(lambda(acc1)
#'(lambda (acc2)
(funcall (funcall (funcall (funcall con x) y) acc1) acc2))))))
)
(defun IF-THEN-ELSEOP(c x y a1 a2)
(funcall (funcall (funcall (funcall (funcall IF-THEN-ELSE c) x) y) a1) a2)
)
And this Greater or Equal operator
(defvar GEQ
#'(lambda(p)
#'(lambda(q)
(funcall #'LEQOP q p)))
)
LEQOP is a function for "Less or Equal" and it works OK. So when I call IF-THEN-ELSE like this ("six" and "two" are church numbers)
(if-then-elseop GEQ six two (print "THIS") (print "THAT"))
as output I've got
"THIS"
"THAT"
"THIS"
Both functions that I'm passing are being called. How can I avoid it in order to get only as output "THIS"?
This happens with every function I use, and this is a trouble because I want to use IF-THEN-ELSE in a recursive call, so just one function must be called dependign on the IF-THEN-ELSE eval.
Any help would be appreciated
Thanks.
Passing your print statements by wrapping them in lambdas should work, but maybe it's worth an explanation as to why this is necessary.
You're implementing a lambda calculus. By definition, all 'things' in the calculus are higher order functions. Your six and two and any other church numerals you may have defined are also higher order functions.
IF-THEN-ELSE is a lambda abstraction (also a higher-order function because it's 'arguments' are also functions). So this would have been valid:
(if-then-elseop GEQ six two one two)
Where one and two are church numbers. By doing that, you're expressing in lambda calculus what you would in plain lisp as:
(if (>= 6 2)
1
2)
But I'm guessing what you were aiming for was:
(if (>= 6 2)
(print "this")
(print "that"))
(more later about why messing with print might be a distraction to your exercise)
So the 'real' 1 has a church encoding one, which I'me assuming you've defined. That way, it can be applied to the lambda abstraction IF-THEN-ELSE - In the same way that
(>= 6 2)
evaluates to TRUE in the lisp world, your lambda calculus implementation of the same,
((GEQ six) two)
will evaluate to the lambda encoding of TRUE, which is again, encoded as a higher-order function.
(defvar TRUE #'(lambda (x) #'(lambda (y) x)))
(defvar FALSE #'(lambda (x) #'(lambda (y) y)))
So the rule to remember is that everything you are passing around and getting back in the lambda calculus are functions:
0 := λf.λx.x
1 := λf.λx.f x
2 := λf.λx.f (f x)
3 := λf.λx.f (f (f x))
... and so on
Which is why, if you did:
(if-then-elseop GEQ six two
#'(lambda () (print "THIS"))
#'(lambda () (print "THAT")))
should work. (sort of, read ahead)
(I'd stick to the faithful interpretation of IF-THEN-ELSE though:
(defvar IFTHENELSE
#'(lambda (p)
#'(lambda (a)
#'(lambda (b) (funcall (funcall p a) b)))))
Where p is your condition... )
As a side note, it's worth pointing out that it might not be too helpful to bring in print and other code that 'does stuff' within lambda calculus - the calculus does not define IO, and is restricted to evaluation of lambda expressions. The church encodings are a way of encoding numbers as lambda terms; There's no simple and meaningful way to represent
a statement with side-effects such a (print "hello") as a lambda term; #'(lambda () (print "THIS")) works but as an academic exercise it's best to stick to only evaluating things and getting back results.
What about lisp itself? if in lisp is not a function so (if cond then-expr else-expr) works the way you expect (that is, only one of then-expr or else-expr will actually be evaluated) because it is a special form. If you were to define your own, you would need a macro (as #wvxvw rightly suggests). But that's another topic.

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.