For a functional programming assignment, I am writing a scheme macro that translates scheme code to coffeescript code. I am using guile on Linux Mint 12, and have (use-syntax (ice-9 syncase)) active.
Currently, I am trying to nest let-syntax in define-syntax and I keep getting an unexpected 'invalid syntax' error. Please excuse any poor programming habits as I am a scheme newbie. :)
My code:
(define-syntax coffee
(syntax-rules (define lambda)
; translate define function
((_ (define arg1 arg2))
(begin
(let-syntax ((temp
(syntax-rules ()
((_) (quote-replace-list 'arg1 'arg2))))))
(if (list? 'arg1)
(string-append (coffee (car 'arg1)) " = "
(comma-splice (cdr 'arg1)) " -> "
(coffee temp))
(string-append (coffee 'arg1) " = "
(coffee arg2)))))))
and my output:
guile> (load "hw2-retry.scm")
guile> (coffee (define (x y) (+ x y)))
ERROR: invalid syntax (let-syntax ((temp (syntax-rules () ((_)
(quote-replace-list (quote #) (quote #)))))))
ABORT: (misc-error)
After several of trying to research this error, I'm starting to think I am just not understanding something fundamental. I was sure you could nest a let-syntax inside a define-syntax. What am I doing wrong?
From the Scheme R5RS specification, let-syntax has the following syntax:
(let-syntax <bindings> <body>)
Syntax: should have the form
((<keyword> <transformer spec>) ...)
The problem with let-syntax in your code (or at least, one of the problems) is that the if should be enclosed in the body portion, as dyoo mentioned. In other words, you should indent the if, remove a closing parenthesis from the end of line 8, and add that closing paren at the end of line 14.
Related
I am generating emacs elisp code from a clojure function. I originally started off using a defmacro, but I realized since I'm going cross-platform and have to manually eval the code into the elisp environment anyway, I can just as easily use a standard clojure function. But basically what I'm doing is very macro-ish.
I am doing this because my goal is to create a DSL from which I will generate code in elisp, clojure/java, clojurescript/javascript, and maybe even haskell.
My "macro" looks like the following:
(defn vt-fun-3 []
(let [hlq "vt"]
(let [
f0 'list
f1 '(quote (defun vt-inc (n) (+ n 1)))
f2 '(quote (ert-deftest vt-inc-test () (should (= (vt-inc 7) 8))))]
`(~f0 ~f1 ~f2)
)))
This generates a list of two function definitions -- the generated elisp defun and a unit test:
(list (quote (defun vt-inc (n) (+ n 1))) (quote (ert-deftest vt-inc-test () (should (= (vt-inc 7) 8)))))
Then from an emacs scratch buffer, I utilize clomacs https://github.com/clojure-emacs/clomacs to import into the elisp environment:
(clomacs-defun vt-fun-3 casc-gen.core/vt-fun-3)
(progn
(eval (nth 0 (eval (read (vt-fun-3)))))
(eval (nth 1 (eval (read (vt-fun-3))))))
From here I can then run the function and the unit test:
(vt-inc 4)
--> 5
(ert "vt-inc-test")
--> t
Note: like all macros, the syntax quoting and escaping is very fragile. It took me a while to figure out the proper way to get it eval properly in elisp (the whole "(quote (list..)" prefix thing).
Anyway, as suggested by the presences of the "hlq" (high-level-qualifier) on the first "let", I want to prefix any generated symbols with this hlq instead of hard-coding it.
Unfortunately, when I use standard quotes and escapes on the "f1" for instance:
f1 '(quote (defun ~hlq -inc (n) (+ n 1)))
This generates:
(list (quote (defun (clojure.core/unquote hlq) -inc (n) (+ n 1)))
(quote (ert-deftest vt-inc-test () (should (= (vt-inc 7) 8)))))
In other words it substitutes 'clojure.core/unquote' for "~" which is not what I want.
The clojure syntax back-quote:
f1 `(quote (defun ~hlq -inc (n) (+ n 1)))
doesn't have this problem:
(list (quote (casc-gen.core/defun vt casc-gen.core/-inc (casc-gen.core/n) (clojure.core/+ casc-gen.core/n 1))) (quote (ert-deftest vt-inc-test () (should (= (vt-inc 7) 8)))))
It properly escapes and inserts "vt" as I want (I still have to work out to concat to the stem of the name, but I'm not worried about that).
Problem solved, right? Unfortunately syntax quote fully qualifies all the symbols, which I don't want since the code will be running under elisp.
Is there a way to turn off the qualifying of symbols when using the syntax quote (back tick)?
It also seems to me that the syntax quote is more "capable" than the standard quote. Is this true? Or can you, by trickery, always make the standard quote behave the same as the syntax quote? If you cannot turn off qualification with syntax quote, how could I get this working with the standard quote? Would I gain anything by trying to do this as a defmacro instead?
The worst case scenario is I have to run a regex on the generated elisp and manually remove any qualifications.
There is no way to "turn off" the qualifying of symbols when using syntax quote. You can do this however:
(let [hlq 'vt] `(~'quote (~'defun ~hlq ~'-inc (~'n) (~'+ ~'n 1))))
Which is admittedly pretty tedious. The equivalent without syntax quote is:
(let [hlq 'vt] (list 'quote (list 'defun hlq '-inc '(n) '(+ n 1))))
There is no way to get your desired output when using standard quote prefixing the entire form however.
As to the issue of using defmacro instead, as far as I understand your intentions, I don't think you would gain anything by using a macro.
Based on the input from justncon, here is my final solution. I had to do a little extra formatting to get the string concat on the function name right, but everything was pretty much like he recommended:
(defn vt-gen-4 []
(let [hlq 'vt]
(let [
f1 `(~'quote (~'defun ~(symbol (str hlq "-inc")) (~'n) (~'+ ~'n 1)))
f2 `(~'quote (~'defun ~(symbol (str hlq "-inc-test")) () (~'should (~'= (~(symbol (str hlq "-inc")) 7) 8))))
]
`(~'list ~f1 ~f2))))
What I learned:
syntax quote is the way to go, you just have to know how to control unquoting at the elemental level.
~' (tilde quote) is my friend here. Within a syntax quote expression, if you specify ~' before either a function or var it will be passed through to the caller as specified.
Take the expression (+ 1 1)
Here is a synopsis of how this expression will expand within a syntax quote expression based on various levels of escaping:
(defn vt-foo []
(println "(+ 1 1) -> " `(+ 1 1)) --> (clojure.core/+ 1 1)
(println "~(+ 1 1) -> " `~(+ 1 1)) --> 2
(println "~'(+ 1 1) -> " `~'(+ 1 1)) --> (+ 1 1)
)
The last line was what I wanted. The first line was what I was getting.
If you escape a function then do not escape any parameters you want escaped. For instance, here we want
to call the "str" function at macro expand time and to expand the variable "hlq" to it's value 'vt:
;; this works
f1 `(quote (defun ~(str hlq "-inc") ~hlq (n) (+ n 1)))
;; doesn't work if you escape the hlq:
f1 `(quote (defun ~(str ~hlq "-inc") ~hlq (n) (+ n 1)))
I guess an escape spans to everything in the unit your escaping. Typically you escape atoms (like strings or symbols), but if it's a list then everything in the list is automatically escaped as well, so don't double escape.
4) FWIW, I ended writing a regex solution before I got the final answer. It's definitely not as nice:
(defn vt-gen-3 []
(let [hlq "vt"]
(let
[
f0 'list
f1 `(quote (defun ~(symbol (str hlq "-inc")) (n) (+ n 1)))
f2 '(quote (ert-deftest vt-inc-test () (should (= (vt-inc 7) 8))))
]
`(~f0 ~f1 ~f2)
))
)
;; this strips out any qualifiers like "casc-gen.core/"
(defn vt-gen-3-regex []
(clojure.string/replace (str (vt-gen-3)) #"([\( ])([a-zA-Z0-9-\.]+\/)" "$1" ))
Macro expansion is very delicate and requires lots of practice.
I'm reading Peter Norvig's Paradigms of AI. In chapter 6.2, the author uses code like below (not the original code, I picked out the troubling part):
Code Snippet:
(progv '(op arg) '(1+ 1)
(eval '(op arg)))
As the author's original intent, this code should return 2, but in sbcl 1.1.1, the interpreter is apparently not looking up op in the environment, throwing out op: undefined function.
Is this implementation specific? Since the code must have been tested on some other lisp.
p.s Original code
You probably mean
(progv '(op arg) '(1+ 1)
(eval '(funcall op arg)))
Edit(2013-08-21):
PAIP was written in pre-ANSI-Common-Lisp era, so it's possible the code
there contains a few noncompliances wrt the standard. We can make
the examples work with the following revision:
(defun match-if (pattern input bindings)
"Test an arbitrary expression involving variables.
The pattern looks like ((?if code) . rest)."
(and (eval (reduce (lambda (code binding)
(destructuring-bind (var . val) binding
(subst val var code)))
bindings :initial-value (second (first pattern))))
(pat-match (rest pattern) input bindings)))
;; CL-USER> (pat-match '(?x ?op ?y is ?z (?if (eql (?op ?x ?y) ?z))) '(3 + 4 is 7))
;; ((?Z . 7) (?Y . 4) (?OP . +) (?X . 3) (T . T))
;; CL-USER> (pat-match '(?x ?op ?y (?if (?op ?x ?y))) '(3 > 4))
;; NIL
Elements in first positions are not looked up as values, but as functions and there is no concept of dynamic binding in the function namespace.
I'd say after a quick look that the original code was designed to evaluate in a context like
(progv '(x y) '(12 34)
(eval '(> (+ x y) 99)))
i.e. evaluating a formula providing substitution for variables, not for function names.
The other answers so far are right, in that the actual form being evaluated is not the variables being bound by progv (simply (op arg)), but none have mentioned what is being evaluated. In fact, the comments in the code you linked to provide a (very) short explanation (this is the only code in that file that uses progv):
(defun match-if (pattern input bindings)
"Test an arbitrary expression involving variables.
The pattern looks like ((?if code) . rest)."
;; *** fix, rjf 10/1/92 (used to eval binding values)
(and (progv (mapcar #'car bindings)
(mapcar #'cdr bindings)
(eval (second (first pattern))))
(pat-match (rest pattern) input bindings)))
The idea is that a call to match-if gets called like
(match-if '((?if code) . rest) input ((v1 val1) (v2 val2) ...))
and eval is called with (second (first pattern)), which the value of code. However, eval is called within the progv that binds v1, v2, &c., to the corresponding val1, val2, &c., so that if any of those variables appear free in code, then they are bound when code is evaluated.
Problem
The problem that I see here is that, by the code we can't tell if the value is to be saved as the variable's symbol-value or symbol-function. Thus when you put a + as a value to some corresponding variable, say v, then it'll always be saved as the symbol-value of var, not it's symbol-function.
Therefore when you'll try to use it as, say (v 1 2) , it won't work. Because there is no function named v in the functions' namespace(see this).
So, what to do?
A probable solution can be explicit checking for the value that is to be bound to a variable. If the value is a function, then it should be bound to the variable's function value. This checking can be done via fboundp.
So, we can make a macro functioner and a modified version of match-if. functioner checks if the value is a function, and sets it aptly. match-if does the dynamic local bindings, and allows other code in the scope of the bound variables.
(defmacro functioner (var val)
`(if (and (symbolp ',val)
(fboundp ',val))
(setf (symbol-function ',var) #',val)
(setf ,var ,val)))
(defun match-if (pattern input bindings)
(eval `(and (let ,(mapcar #'(lambda (x) (list (car x))) bindings)
(declare (special ,# (mapcar #'car bindings)))
(loop for i in ',bindings
do (eval `(functioner ,(first i) ,(rest i))))
(eval (second (first ',pattern))))
(pat-match (rest ',pattern) ',input ',bindings))))
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)))))
I am trying to write a wrapper for define, that stores the values passed to it. I've been approaching it in baby steps (being new to Lisp in general, and even newer to Scheme) but have run into a wall.
In Racket, I'm starting with:
> (require (lib "defmacro.ss"))
> (define-macro (mydefine thing definition)
`(define ,thing ,definition))
> (mydefine a 9)
> a
9
Okay, that works. Time to do something in the macro, prior to returning the s-exprs:
> (define-macro (mydefine thing definition)
(display "This works")
`(define ,thing ,definition))
> (mydefine a "bob")
This works
> a
"bob"
Nice. But I can't for the life of me get it to set a global variable instead of displaying something:
> (define *myglobal* null)
> (define-macro (mydefine thing definition)
(set! *myglobal* "This does not")
`(define ,thing ,definition))
> (mydefine a ":-(")
set!: cannot set identifier before its definition: *myglobal*
Any suggestions on how to accomplish this would be greatly appreciated.
I suspect that I'm trying to swim against the current here, either by fiddling with globals from a macro in Scheme, or by using define-macro instead of learning the Scheme-specific syntax for macro creation.
You're running against Racket's phase separation -- which means that each phase (the runtime and the compile-time) operate in different worlds. As Vijay notes, one way to solve this is to do what you want at runtime, but that will probably not be what you need in the long run. The thing is that trying these things usually means that you will want to store some syntactic information at the compile-time level. For example, say that you want to store the names of all of your defined names, to be used in a second macro that will print them all out. You would do this as follows (I'm using sane macros here, define-macro is a legacy hack that shouldn't be used for real work, you can look these things up in the guide, and then in the reference):
#lang racket
(define-for-syntax defined-names '())
(define-syntax (mydefine stx)
(syntax-case stx ()
[(_ name value)
(identifier? #'name)
(begin (set! defined-names (cons #'name defined-names))
#'(define name value))]
;; provide the same syntactic sugar that `define' does
[(_ (name . args) . body)
#'(mydefine name (lambda args . body))]))
Note that defined-names is defined at the syntax level, which means that normal runtime code cannot refer to it. In fact, you can have it bound to a different value at the runtime level, since the two bindings are distinct. Now that that's done, you can write the macro that uses it -- even though defined-names is inaccessible at the runtime, it is a plain binding at the syntax level, so:
(define-syntax (show-definitions stx)
(syntax-case stx ()
[(_) (with-syntax ([(name ...) (reverse defined-names)])
#'(begin (printf "The global values are:\n")
(for ([sym (in-list '(name ...))]
[val (in-list (list name ...))])
(printf " ~s = ~s\n" sym val))))]))
The statement (set! *myglobal* "This does not") is executed in the transformer environment, not the normal environment. So it's not able to find *myglobal. We need to get both the expressions executed in the environment where *myglobal* is defined.
Here is one solution:
(define *defined-values* null)
(define-macro (mydefine thing definition)
`(begin
(set! *defined-values* (cons ,definition *defined-values*))
(define ,thing ,`(car *defined-values*))))
> (mydefine a 10)
> (mydefine b (+ 20 30))
> a
10
> b
50
> *defined-values*
(50 10)
> (define i 10)
> (mydefine a (begin (set! i (add1 i)) i)) ;; makes sure that `definition`
;; is not evaluated twice.
> a
11
If the Scheme implementation does not provide define-macro but has define-syntax, mydefine could be defined as:
(define-syntax mydefine
(syntax-rules ()
((_ thing definition)
(begin
(set! *defined-values* (cons definition *defined-values*))
(define thing (car *defined-values*))))))
I am trying to write a macro that defines a special class of data structure with associated functions.
I know this is possible; it is done multiple times in the core language itself.
As a specific example, how would I define the define-struct macro in Scheme itself. It needs to create make-struct, struct-<<field>>, etc functions.
I tried doing this using define, however, this only defines the function in the macro's lexical scope.
How can I actually define a function in a macro?
The key for an answer is datum->syntax. The basic idea is that you want to take some random data and turn it into a syntax -- in this case, turn a symbol into an identifier. An identifier is basically a symbol with some lexical information that (very roughly) indicates how it is bound. Using datum->syntax you can do exactly that: it expects an existing piece of syntax which is where it copies the binding from, and a datum (a symbol here) which is the value that is contained in the syntax wrapper.
Here's an example that demonstrates a define-struct-like tool using this:
#lang scheme
;; implements a defstruct-like macro that uses association lists
(define-syntax (defstruct-lite stx)
(syntax-case stx ()
[(defstruct-lite name field ...)
(let ([make-id
(lambda (template . ids)
(let ([str (apply format template (map syntax->datum ids))])
(datum->syntax stx (string->symbol str))))])
(with-syntax ([make-name (make-id "make-~a" #'name)]
[name? (make-id "~a?" #'name)]
[(arg ...) (generate-temporaries #'(field ...))]
[(name-field ...)
(map (lambda (f) (make-id "~a-~a" #'name f))
(syntax->list #'(field ...)))])
#'(begin
(define (make-name arg ...) (list 'name (cons 'field arg) ...))
(define (name? x) (and (pair? x) (eq? 'name (car x))))
(define (name-field x)
(and (name? x) (cdr (assq 'field (cdr x)))))
...)))]))
And here's an example of using it:
(defstruct-lite point x y)
(point-y (make-point 1 2))