(define-macro slambda
(lambda (args body)
`(let ((self (lambda ,args ,body)))
self)))
Hello, I have a "problem" with this macro for self-referencing lambda.. It works, but fails when I want to refer to "self" from outside.. meaning that first aplication works, second doesn't
((slambda (x) (+ x 1)) 10)
((slambda () self))
Perhaps it would work better you replaced let for letrec like this:
(define-macro slambda
(lambda (args body)
`(letrec ((self (lambda ,args ,body)))
self)))
In Scheme you have lexical scope and self is not in effect until the body of the let. The procedure called self in the body of the let is not defined by that name inside itself. It's perhaps easier to see if you desugar let:
((lambda (self) ...)
(lambda () self)) ; self referenced outside procedure that defines it
Notice that define-macro isn't a standard scheme syntax so you should have specified which implementation you are using. Luckily this problem had nothing to do with macros.
If you are using scheme you might be better off using standard define-syntax rather than the not-always-supported define-macro. With define-syntax, you have to use datum->syntax to get the macro to act unhygienically and inject the name 'self' into the output syntax. This is your code translated to define-syntax, as tested with guile:
(define-syntax slambda
(lambda (x)
(syntax-case x ()
[(slambda formals body0 body1 ...)
(with-syntax ([self (datum->syntax #'slambda 'self)])
#'(letrec ([self (lambda formals body0 body1 ...)])
self))])))
You need to quote the lambda-part where you quasiqute so it can be assigned to self.
(define-macro slambda
(lambda (arg1 . arg2)
`(let ((self '(slambda ,arg1 ,#arg2)))
(lambda ,arg1 ,#arg2))))
The dot and unquote-splicing is needed there if you want to use it with more than one argument.
Sylwester's answer is correct, but I wanted to make a bigger point: unless your Scheme implementation doesn't provide a hygienic procedural macro system, there is no good reason to use define-macro.
For anaphoric macros, such as the one you want to write, it's best to use syntax parameters, if you're using a Scheme implementation that supports it, such as Racket or Guile. Here's a Racket example:
#lang racket
(provide slambda self)
(require racket/stxparam srfi/31)
(define-syntax-parameter self
(lambda (stx)
(raise-syntax-error 'self "Can only be used inside slambda")))
(define-syntax slambda
(syntax-rules ()
((_ params body ...)
(rec (ohai . params)
(syntax-parameterize ((self (make-rename-transformer #'ohai)))
body ...)))))
Of course, as you can see in my example, I used rec. In the general case where you want to make self-referential procedures, it's best to use rec for that; you simply specify the name you want to refer to the procedure by (rather than using a hardcoded self). Since rec is not anaphoric, its definition is much simpler:
(define-syntax rec
(syntax-rules ()
((_ (id . params) body ...)
(rec id (lambda params body ...)))
((_ id value)
(letrec ((id value)) id))))
You would use it like this (in this case, I use recur as the self-reference; of course, you can choose any name you like):
(define nested-length
(rec (recur x)
(cond ((null? x) 0)
((pair? x) (+ (recur (car x)) (recur (cdr x))))
(else 1))))
Related
I remember I read somewhere it is not a macro and is built into the core language. Something like that, I am not sure, because I can no longer remember from where I read it. So is struct a macro in Racket or not? If not, why is it built into the core language?
A macro; struct.rkthas
(define-syntax (struct stx)
(define (config-has-name? config)
(cond
[(syntax? config) (config-has-name? (syntax-e config))]
[(pair? config) (or (eq? (syntax-e (car config)) '#:constructor-name)
(eq? (syntax-e (car config)) '#:extra-constructor-name)
(config-has-name? (cdr config)))]
[else #f]))
(with-syntax ([orig stx])
(syntax-case stx ()
[(_ id super-id fields . config)
(and (identifier? #'id)
(identifier? #'super-id))
(if (not (config-has-name? #'config))
(syntax/loc stx
(define-struct/derived orig (id super-id) fields #:constructor-name id . config))
(syntax/loc stx
(define-struct/derived orig (id super-id) fields . config)))]
[(_ id fields . config)
(identifier? #'id)
(if (not (config-has-name? #'config))
(syntax/loc stx
(define-struct/derived orig id fields #:constructor-name id . config))
(syntax/loc stx
(define-struct/derived orig id fields . config)))]
[(_ id . rest)
(identifier? #'id)
(syntax/loc stx
(define-struct/derived orig id . rest))]
[(_ thing . _)
(raise-syntax-error #f
"expected an identifier for the structure type name"
stx
#'thing)]))))
In Racket IDE, you can use the Open Defining File function to locate the source code (if available).
It looks like I misunderstood the question, when I answered before. So here's an answer to the question that was meant:
Structs are built-in and primitive; they underpin the implementation. In fact, circa 2007, Matthew Flatt commented that in PLT Scheme (as Racket was known then), in a sense everything is a struct:
> At Thu, 31 May 2007 16:45:25 -0700, YC wrote:
> Out of curiosity - does PLT scheme actually use struct as the fundamental
> compound type, i.e. implement closure/etc on top of struct.
The way I think about it, everything is a struct, but some things use a
special-case representation because they're important enough. (The
extreme case is a fixnum).
But an equally valid answer would be: no, not all compound types use
the same representation as values from a struct constructor.
-- Source.
Start of the thread.
In addition to usepla's great answer, I wanted to add:
In the Racket documentation, the "blue box" has a phrase in the top right corner such as procedure or syntax. For struct it says syntax.
If you think about what struct does, among other things it defines named functions derived from the name of the struct. So (struct foo (a b)) will define a foo? predicate and accessors foo-a, foo-b. A plain function can't define new named things like this, so, it must be a macro.
Reading through the implementation code in define-struct.rkt, if you want to do the same thing manually, the following code is a much simplified version of what it is doing.
(define-syntax (struct stx)
;
; Function that creates compound names using syntax objects
(define (make-name id . parts)
(datum->syntax
id
(string->symbol
(apply string-append
(map (lambda (p)
(if (syntax? p)
(symbol->string (syntax-e p))
p))
parts)))
id))
;
(syntax-case stx ()
;
; parse the input and extract the name and variable
; this version uses only one variable for simplicity (3)
[(_ id avar)
;
; guard to ensure we have an identifier
(identifier? #'id)
;
; Create the names (1)
(let ((? (make-name #'id #'id "?"))
(v (make-name #'id #'id "-" #'avar)))
; Generate code to define the various functions associated with
; the new struct (2)
#`(begin
(define id (lambda (vx) (list id vx)))
(define #,? (lambda (x) (eq? (car x) id)))
(define #,v (lambda (x) (second x)))))]
))
1) We have to create the names we will define: but we need to use syntax objects to do so
2) We generate code that will define all of the functions associated with the new object in the global namespace
3) In the real version, most of the code deals with the properties that can be used a struct definition. The real version also needs to handle arbitrary numbers of variables and alternative forms, defaults etc...
I'm trying to define a macro that generates an anonymous function taking one argument named it, for succinctness, so that instead of
(λ (it) body)
I can write
(λλ body)
(In other words, (λλ body) transforms to (λ (it) body))
(define-syntax-parameter it #f)
(define-syntax λλ
(syntax-rules ()
((_ body)
(λ (x) (syntax-parameterize ((it x)) body)))))
(λλ (< it 0)) ; For testing
I get operators.rkt:13:28: ?: literal data is not allowed; no #%datum syntax transformer is bound in the transformer environment in: #f at (define-syntax-parameter if #f), but as far as I can tell, this is exactly like the example given in racket's doc for how to use define-syntax-parameter. I can suppress the error by replacing #f with a function (I used member, but not for any real reason), but after doing that, I get operators.rkt:17:38: x: identifier used out of context in: x. What am I doing wrong?
You left out the syntax-id-rules part in the example. It's the part that specifies that it should expand to x. Alternatively, you can use make-rename-transformer:
#lang racket
(require racket/stxparam)
(define-syntax-parameter it #f)
(define-syntax λλ
(syntax-rules ()
((_ body)
(λ (x) (syntax-parameterize ([it (make-rename-transformer #'x)]) body)))))
((λλ (< it 0)) 5)
((λλ (< it 0)) -5)
=>
#f
#t
Syntax parameters are not the only way to implement the macro you have in mind. A simpler (IMO) way is to just use datum->syntax to inject the identifier it:
(define-syntax (λλ stx)
(syntax-case stx ()
((_ body ...)
(with-syntax ((it (datum->syntax stx 'it)))
#'(λ (it) body ...)))))
To use your example:
(define my-negative? (λλ (< it 0)))
(my-negative? -1) ;; => #t
This R5RS macro is what I have tried and is pretty much what I want to do. Racket or other implementations don't like this macro exactly where I wanted the magic to happen.
(define-syntax quote-unique
(syntax-rules (magic end)
;; end case
((quote-unique magic processed end)
'processed)
;; finished iteration
((quote-unique magic (processed ...) sym1 end rest ... )
(quote-unique magic (processed ... sym1) rest ... end))
;; match (doesn't work since racket doesn't like sym1 twice in template)
;; but I'm looking for the same expression twice
((quote-unique magic processed sym1 sym1 . rest )
(quote-unique magic processed sym1 . rest))
;; rotate
((quote-unique magic processed sym1 sym2 rest ... )
(quote-unique magic processed sym1 rest ... sym2))
;; start iteration
((quote-unique rest ...)
(quote-unique magic () rest ... end))))
This would have been easy in Common Lisp:
(defmacro quote-unique ( &rest xs )
(labels ((remove-duplicates (lis)
(if lis
(if (member (car lis) (cdr lis))
(remove-duplicates (cdr lis))
(cons (car lis) (remove-duplicates (cdr lis)))))))
(list 'quote (remove-duplicates xs))))
I also have been reading Define syntax primer and think the implementation of is-eqv? would have pointed me in the right directions, but it seems it's not a macro that is defined there.
If it's not possible in R5RS compile time, how could this be done with R6RS?
The remove-id example of Chris Jester-Young's answer is expressible in R5RS:
(define-syntax remove-id
(syntax-rules ()
((remove-id s (t ...))
(letrec-syntax ((aux (syntax-rules (s)
((aux p* ())
'p*)
((aux p* (s . rest))
(aux p* rest))
((aux (p (... ...)) (u . rest))
(aux (p (... ...) u) rest)))))
(aux () (t ...))))))
(Note that quoting the ellipsis by (... ...) is not strictly R5RS (only R7RS), but is only used to have the resulting sequence in the given order and not reversed. Thus by adding another macro, you can even ditch the ellipsis.)
I hope this example makes it clear how to solve your original problem. If something can be solved with hygienic macros, one should think twice before using a procedural macro or a macro facility that probably won't be standardized after R6RS.
You can't do this using syntax-rules, but you can do it using syntax-case, by using a guard that uses free-identifier=?. Here's an example:
(define-syntax (remove-id stx)
(syntax-case stx ()
((_ head ())
#''())
((_ head (next tail ...)) (free-identifier=? #'head #'next)
#'(remove-id head (tail ...)))
((_ head (next tail ...))
#'(cons 'next (remove-id head (tail ...))))))
> (remove-id foo (foo bar baz qux foo bar))
; => (bar baz qux bar)
But of course, if you're going to use syntax-case, there's a much simpler way to implement your quote-unique (this implementation uses Racket's custom hashtables):
(require (for-syntax racket/dict))
(define-syntax (quote-unique stx)
(define (id-dict ids)
(foldl (lambda (id d)
(dict-set d id #t))
(make-immutable-custom-hash free-identifier=? (compose eq-hash-code syntax-e))
(syntax-e ids)))
(syntax-case stx ()
((_ ids ...)
(with-syntax ((unique (dict-keys (id-dict #'(ids ...)))))
#''unique))))
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 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))