Racket / Scheme - Syntax-Case - macros

I'm currently working on an assigment about racket macros. In one of the questions we`re asked to define a macro my-set! which acts like this:
(define x 3)
(define y 5)
(define z 7)
(my-set! (x (+ x y)))
(my-set! (x (+ x y)) (z 6))
x
13
y
5
z
6
I found this interesting document on syntax-case http://www.cs.indiana.edu/~dyb/pubs/tr356.pdf
Currently my macro works but i'm trying to add a "fender" like on page 10 of the document to fend off errors like if one of the variables arent identifiers or anything else.
Here`s my code:
(define-syntax my-set!
(letrec ((all-ids?
(λ (ls)
(or (null? ls)
(and (identifier? (car ls))
(all-ids? (cdr ls)))))))
(lambda (x)
(syntax-case x ()
((_ (var val) (var2 val2) (var3 val3) ...)
(all-ids? (syntax (var var2 var3 ...)))
(syntax (begin (set! var val) (my-set! (var2 val2) (var3 val3) ...))))
((_ (var val))
(syntax (set! var val)))))))
If I test this exact code without the fender, it works perfectly. But when I run this:
(define a 1)
(define b 1)
(define c 1)
(my-set! (a 3) (b 4) (c 5))
I get this:
car: contract violation expected: pair?
given: syntax:C:\Users\mgiroux\Desktop\define-myset.rkt:40:26 (a b c)
Seems like all-ids? cant (car) of (a b c) cause its not a list? I tried passing it as a list but didnt work either, i seem to have copied exactly the way they do it in the pdf I linked.. What am I missing here?

#'(var var2 var3 ...) is indeed not a list. It's a syntax object that wraps a list. You should use syntax->list to extract out the items into a list, thus your guard should look like:
(all-ids? (syntax->list #'(var var2 var3 ...)))

Related

Make `define` evaluate its first argument in Racket

In some dialects of LISP, there is a distinction between SET and SETQ, the first one evaluates its first argument so that you need to use the (SET (QUOTE …) …) syntax.
Since in Racket, quoting is not needed in definitions, define behaves as SETQ.
Is there a Racket function that behaves like SET? If no, how to write one?
I tried (define (SET a b) (define (eval a) b) b) but it does not seem to work when providing it to an other language with (provide SET).
Here's my quick attempt at this problem:
;; lib.rkt
#lang racket/base
(provide (rename-out [#set set]
[##%top #%top]
[#set! set!]
[#define define]))
(require syntax/parse/define)
(define env (make-hash))
(define (set x v stx)
(unless (hash-has-key? env x)
(raise-syntax-error #f "undefined id" stx))
(hash-set! env x v))
(define-simple-macro (##%top . x)
(hash-ref
env
'x
(λ () (raise-syntax-error #f "unbound id" (quote-syntax x)))))
(define (#set x v)
(set x v x))
(define-simple-macro (#set! x:id v)
(set 'x v (quote-syntax x)))
(define-simple-macro (#define x:id v)
(begin
(when (hash-has-key? env 'x)
(raise-syntax-error #f "id already defined" (quote-syntax x)))
(hash-set! env 'x v)))
#lang racket/base
(require "lib.rkt")
(define x 1)
(set (if #t 'x 'y) 2)
(add1 x) ; 3
(set! x 3)
(add1 x) ; 4
(add1 y) ; y: unbound id in: y
Note that this differs from original Racket in several ways. For example:
unbound ids are now reported at runtime instead of compile-time.
set! now won't work with set!-transformer.
define can't be used to define functions
define can't be used to shadow an identifier.
For (2) and (3), it's possible to get the original behavior back, but I don't want the answer to be too long, so I didn't include the full functionality. For now, I don't know how to solve (4).
Also note that you can only set identifiers defined via define. If you want to set identifiers defined via lambda, let, etc., you need to redefine these constructs too.
I would do it much less verbose and much simpler.
Since all arguments are evaluated, the set or let's say define% can be defined as a function!
(define (define% x y)
(eval `(define ,x ,y)))
One can even define functions using define% when using old-style form using lambda.
(define 'ab (lambda (x y) (+ x y)))
(ab 3 5) ;; 7
It even behaves correctly in terms of scope
(define (foo x)
(define% 'bar (lambda (x) (+ 1 x)))
(bar (bar (bar x))))
foo
;; #<procedure:foo>
bar
; bar: undefined;
; cannot reference undefined identifier
; [,bt for context]
(foo 3)
6
;; after first call however, bar is available in global environment
;; as pointed out by #AlexKnauf
bar
;; #<procedure:bar>
Thus there are some scoping issues ...
(let ((x 0))
(define% 'counter (lambda () (set! x (+ x 1)) x)))
counter
;; #<procedure>
(counter)
;; 1
(counter)
;; 2
(counter)
;; 3

Racket - implementing the let* function using macro

I need to implement my_let* using defmacro which works similarly to let*, but while let* is expanded to a series of nested let calls (behind the scenes), my_let* needs to be expanded to a single let call, and use the define statement to define the arguments i get.
an example of using my_let*:
(my_let* ((a 2)
(b 3)
(c (+ a b)))
(+ a b c))
and the return value of this code should be 10. just as if it was use let*.
the code above will be expanded in my_let* to the following:
(let ()
(define a 2)
(define b 3)
(define c (+ a b))
(+ a b c))
I'm new to using macro, though i successfully written some macros, this one got me lost.
Thank you in advance.
Use syntax-parse. At the least don't even consider using defmacro in Racket.
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (my-let* stx)
(syntax-parse stx
[(_my-let* ([name:id e:expr] ...) body ...)
#'(let ()
(define name e) ...
body ...)]))
The name:id means that name must be an identifier and e:expr means
that e must an expression. These simple annotations help syntax-parse
to give you better error messages.
Example:
(my-let* ((4 2)
(b 3)
(c (+ a b)))
(+ a b c))
Here the DrRacket will color the 4 read and give the message:
my-let*: expected identifier in: 4
The Scheme way is using syntax-rules
(define-syntax my-let*
(syntax-rules ()
((_ ((binding expression) ...) body ...)
(let ()
(define binding expression) ...
body ...))))
Using defmacro is more like making a procedure.
(define (my-let-fun* bindings . body)
...)
How it should work is like this:
(my-let-fun* '((a 1) (b 2) (c (+ a b))) "test" '(list a b c))
; ==> (let () (define a 1) (define b 2) (define c (+ a b)) "test" (list a b c))
If you have not called my-let-fun* in your implementation it's just changing it to a defmacro and you're done.
(defmacro my-let* (bindings . body)
...)
It's quite simple to do either with a helper to do recursion or foldr to do the bindings. Good luck!
Your my-let* will only work in #lang racket and perhaps #!r6rs and later. In R5RS you will get an error in this case:
(my-let* ((a 1) (b 2) (c (+ a b)))
(list a b c))
; signals an error that a is undefined.
The reason is that it expands to something like this:
(let ((a 'undefined) (b 'undefined) (c 'undefined))
(let ((tmp1 1) (tmp2 2) (tmp3 (+ a b)))
(set! a tmp1)
(set! b tmp2)
(set! c tmp3))
(list a b c))
Between the error messages and some judicious use of the macro stepper I think it's hard to go too wrong here. The trouble is just making sure you've put things together right using either conses or unquote-splicing. I believe the standard practice in such macros is heavy use of quasiquote and unquote-splicing in order for the output to as closely match the intended statement as possible, otherwise the macro can become quite inscrutable. But I am not a defmacro expert.
#lang racket/base
(require (for-syntax racket/base)
compatibility/defmacro)
(defmacro my-let* (binding-pairs . body)
(define defines (map (lambda (bp) (cons 'define bp)) binding-pairs))
`(let ()
,#defines
,#body))
(my-let* ((a 2)
(b (expt a 3)))
(printf "a:~a\nb:~a\n" a b)
(+ a b))

Creating a function to return a core expression using macros

I've been working on some code using R5RS for an assignment to expand certain expressions into core forms of the expression using macros. These are put through a provided eval/apply loop later
(define expand (lambda (exp)
(letrec-syntax
((let (syntax-rules ()
((_ ((var init) ...) body ...)
(`((lambda (var ...) body ...) init ...))))) )
(exp)) ; sequence to expand
))
(expand (let ((x 2) (y 1)) (+ x y)) )
When I run the code like this I get back ;The object 3 is not applicable. but so it looks like it's actually evaluating exp, but I need to get back a uh...string representation.
If I embed the expression I want expanded into the letrec-syntax body I get back what I actually want. Like so:
(define expand (lambda (exp)
(letrec-syntax
((let (syntax-rules ()
((_ ((var init) ...) body ...)
(`((lambda (var ...) body ...) init ...))))) )
(let ((x 2) (y 1)) (+ x y))) ; sequence to expand
))
I get back ...
;The object ((lambda (x y) (+ x y)) 2 1) is not applicable Which looks like what I want to send back to be interpreted.
So my question is how can I rewrite this to take any exp given to expand like in the first example, but return its expanded form like in the second example?
I think the problem has something to do with exp defined by lambda being in the wrong scope in regards to letrec-syntax. I'm very new to Scheme, and I feel like I'm missing a simple solution here. My best leads so far involve using syntax-case somehow or something about hygienics, but I feel like I've been chasing my tail trying to research those topics so far and I'm not sure they're the right direction.
Thanks for any assistance. :)
This works:
(define-syntax expand
(syntax-rules (let)
((_ (let ((var init) ...) body ...))
'((lambda (var ...) body ...) init ...))))
then
> (expand (let ((x 2) (y 1)) (+ x y)))
((lambda (x y) (+ x y)) 2 1)

Conditional variable binding in Common Lisp

I want to execute a function with 2 local variables, but the values of these of these variables should depend on some condition. For example, let's say I have 2 variables x and y, and I want to swap them inside let if y > x. The swap should be temporary, I don't want to mutate state with rotatef. My code would look something like:
(setq x 2)
(setq y 1)
(let (if (> x y) ((x y) (y x)) ((x x) (y y)))
(cons x y)) ; should return (1 . 2)
But the expression inside let is not valid Lisp. How do I conditionally assign values to local variables? The work around is to put the body in flet and call it with different arguments, but it look clumsy:
(flet ((body (x y) (cons x y)))
(if (< x y)
(body x y)
(body y x)))
Multiple-value-bind and values
There are lots of alternatives, some of which have already been pointed out in other answers. I think that the question in the title ("Conditional variable binding in Common Lisp") is a nice case for multiple-value-bind and values. I've used different variable names in the following just to make it clear where x and y are, and where the original values are coming from. The names can be the same, though; this just shadows them inside.
(let ((a 3)
(b 2))
(multiple-value-bind (x y)
(if (< a b)
(values a b)
(values b a))
(cons x y)))
;=> (2 . 3)
Then, using a bit of macrology, we can make this a bit cleaner, much like coredump did:
(defmacro if-let (test bindings &body body)
"* Syntax:
let ({var | (var [then-form [else-form]])}*) declaration* form* => result*
* Description:
Similar to LET, but each binding instead of an init-form can have a
then-form and and else-form. Both are optional, and default to NIL.
The test is evaluated, then variables are bound to the results of the
then-forms or the else-forms, as by LET."
(let ((bindings (mapcar #'(lambda (binding)
(destructuring-bind (variable &optional then else)
(if (listp binding) binding (list binding))
(list variable then else)))
bindings)))
`(multiple-value-bind ,(mapcar 'first bindings)
(if ,test
(values ,#(mapcar 'second bindings))
(values ,#(mapcar 'third bindings)))
,#body)))
(pprint (macroexpand-1 '(if-let (< x y) ((x x y)
(y y x))
(cons x y))))
; (MULTIPLE-VALUE-BIND (X Y)
; (IF (< X Y)
; (VALUES X Y)
; (VALUES Y X))
; (CONS X Y))
(let ((a 3) (b 2))
(if-let (< a b)
((x a b)
(y b a))
(cons x y)))
;=> (2 . 3)
Comparison with progv
In terms of use, this has some similarities with sindikat's answer, but multiple-value-bind establishes bindings just like let does: lexical by default, but a global or local special declaration will make the bindings dynamic. On the other hand, progv establishes dynamic bindings. This means that if the bindings are entirely introduced by progv, you won't see much difference (except in trying to return closures), but that you can't shadow bindings. We can see this without having to do any conditional work at all. Here are two sample snippets. In the first, we see that the inner reference to x actually refers to the lexical binding, not the dynamic one established by progv. To refer to the one established by progv, you actually need to declare the inner reference to be special. progv doesn't accept declarations, but we can use locally.
(let ((x 1))
(progv '(x) '(2)
x))
;=> 1
(let ((x 1))
(progv '(x) '(2)
(locally (declare (special x))
x)))
;=> 2
multiple-value-bind actually does the binding the way we'd expect:
(let ((x 1))
(multiple-value-bind (x) (values 2)
x))
;=> 2
It's probably better to use a binding construct like multiple-value-bind that establishes lexical bindings by default, just like let does.
If you don't want to use progv, as mentioned by sindikat, you always can wtite something like that:
(defmacro let-if (if-condition then-bindings else-bindings &body body)
`(if ,if-condition
(let ,then-bindings
,#body)
(let ,else-bindings
,#body)))
So expression like
(let-if (> x y) ((x y) (y x)) ((x x) (y y))
(cons x y))
Will expand into:
(IF (> X Y)
(LET ((X Y) (Y X))
(CONS X Y))
(LET ((X X) (Y Y))
(CONS X Y)))
rotatef
How about:
CL-USER> (defvar x 2)
X
CL-USER> (defvar y 1)
Y
CL-USER> (let ((x x) ; these variables shadow previously defined
(y y)) ; X and Y in body of LET
(when (> x y)
(rotatef x y))
(cons x y))
(1 . 2)
CL-USER> x ; here the original variables are intact
2 ; ^
CL-USER> y ; ^
1 ; ^
However, I think that in every such practical case there are lispier ways to solve problem without macros. Answer by msandiford is probably the best from functional point of view.
psetf
Although rotatef is really efficient method (it probably would be compiled to about three machine instructions swapping pointers in memory), it is not general.
Rainer Joswing posted just a great solution as a comment shortly after posting of the question. To my shame, I checked macro psetf only few minutes ago, and this should be very efficient and general solution.
Macro psetf first evaluates its even arguments, then assigns evaluated values to variables at odd positions just like setf does.
So we can write:
(let ((x x)
(y y))
(when (> x y)
(psetf x y y x))
...)
And that's it, one can conditionally rebind anything to anything. I think it's way better than using macros. Because:
I don't think it's such a common situation;
Some macros in the posted answers repeat their body code, which may be really big: thus you get bigger compiled file (it's fair price for using macro, but not in this case);
Every custom macro does make code harder to understand for other people.
One solution is to use progv instead of let, its first argument is a list of symbols to bind values to, second argument is a list of values, rest is body.
(progv '(x y) (if (< x y) (list x y) (list y x))
(cons x y)) ; outputs (1 . 2)
Another alternative might be:
(let ((x (min x y))
(y (max x y)))
(cons x y))
My suggestion would be one of destructuring-bind or multiple-value-bind.
If you anticipate needing to do this a lot, I would suggest using a macro to generate the bindings. I've provided a possible macro (untested).
(defmacro cond-let (test-expr var-bindings &body body)
"Execute BODY with the VAR-BINDINGS in place, with the bound values depending on
the trueness of TEST-EXPR.
VAR-BINDINGS is a list of (<var> <true-value> <false-value>) with missing values
being replaced by NIL."
(let ((var-list (mapcar #'car var-bindings))
(then-values (mapcar #'(lambda (l)
(when (cdr l)
(nth 1 l)))
var-bindings))
(else-values (mapcar #'(lambda (l)
(when (cddr l))
(nth 2 l)))
var-bindings))
`(destructuring-bind ,var-list
(if ,test-expr
(list ,#then-values)
(list ,#else-values)))))

What is the difference between let and let* in Scheme?

I am writting a script for GIMP and using let* as it was in a sample I took. But it seems to be just a lambda sugar exactly like let. Why are they different? What is the difference between them?
They are different in the order in which variables are bound. Consider this for example:
> (let ((a 1)(b (+ a 2))) b)
This code will FAIL because b requires a, which has not been defined before. It is defined, in the same let, but Scheme will take all your let definitions as only one statement and not allow them to reference each other. In Gambit Scheme, it raises:
*** ERROR IN ##raise-unbound-global-exception -- Unbound variable: a
Conversely, let* will bind the first variable of the let, then the second, etc... so:
> (let* ((a 1)(b (+ a 2))) b)
3
Works as expected.
A third form which is of interest is letrec which lets not only variables in the let reference other variables, but also let them reference themselves (e.g. for recursion). This lets you write code like:
> (letrec ((f (lambda(n) ;; Takes the binary log2 recursively
(cond
((= n 1) 0)
(else (+ 1 (f (/ n 2))))))))
(f 256)) ;; 2^8 = 256
8
If you try to define a recursive function with let or let*, it will tell you the variable is unbound.
All of this can be achieved via clever rearranging/nesting of the let statements, but let* and letrec can be more convenient and readable in some cases like these.
They are different in the way they bind variables. All variables in one let uses the same lambda-form, so you can do this:
(let ((x 10) (y 20))
(let ((x y) (y x))
(display (list x y)))) ; prints (20 10)
While switch the inner let with a let* and you'll se that the second binds towards what was bound in the first binding and not what was before the let*
(let ((x 10) (y 20))
(let* ((x y) (y x))
(display (list x y)))) ; prints (20 20)
the reason for this is that
(let* ((x y) (y x))
...)
is the same as
(let ((x y))
(let ((y x))
...))
let and let* are used for binding variables and both are syntactic sugar (macro), but let* binds variables one after the other soon (from left to right, or from up to down). The difference is also the different scope. In let the scope of each variable is only the expression, not the bindings. In let* the scope of each variable is the expression and the before bindings.
With let* you do such a thing (b a)
...
(let* ((a 1)
(b a))
...)
...
with let you don't.
Implementation of let:
(define-syntax let
(syntax-rules ()
((_ (( variable value ) ...) body ...)
(( lambda (variable ...) body ...) value ...))))
Implementation of let*:
(define-syntax let*
(syntax-rules ()
; pattern for one binding
((_ ((variable value)) body ...)
((lambda (variable) body ...) value))
; pattern for two or more bindings
((_ ((variable value) . other) body ...)
((lambda (variable) (let* other body ...)) value))))