The R5RS spec states that as part of the requirements for a macro defined using syntax-rules:
If a macro transformer inserts a free reference to an identifier, the reference refers to the binding that was visible where the transformer was specified, regardless of any local bindings that may surround the use of the macro.
I am trying to understand how this works in practice. So for example, if I have the following code:
(define var 'original)
(define-syntax test-var
(syntax-rules (var)
((_ var)
var)
((_ pattern-var)
'no-match)))
I would expect the following, if executed immediately after, to evaluate to original, which it does:
(test-var var)
And I would expect this one to be no-match since the var introduced into scope prior to test-var does not match the binding of var at macro definition:
(let ((var 1)) (test-var var))
However the following example has me puzzled:
(define var 'new-var)
(test-var var)
In Chicken Scheme, this evaluates to new-var. I would have expected it to be no-match for the same reasons as the previous (let) example. I thought that perhaps this was an issue with using define twice, but the result is still new-var even if I use (set! var 'new-var)
Does anyone have any insight as to what is going on here? What should happen per R5RS?
This is the usual trick that Schemes have when dealing with redefinitions on the REPL -- treating them as a mutation for the existing binding. So the second define is not really creating a new binding, and instead it just set!s the existing one.
Related
The problem with the following code is multiple evaluation:
(defmacro with-object (name &body body)
`(let ((,name (create-object)))
,#body
(free-object ,name)))
but I don't know how to do this the right way.
In order to use name in the let binding in your code, it has to hold a symbol. There should be no multiple evaluation problem in the code you supplied, since the symbol held by name is just given a binding in the expansion and evaluated for the free-object call within the context of that binding.
The project I am working on defines some complex structures that receive messages and run within their own thread. The structures are user-defined and transformed via macros to threads and runtime stuff. Roughly speaking we can say that a complex structure consists of some behaviour that implements the logic, and a procedure for spawning an instance of the behaviour. In the code below I have vastly simplified the situation, where a behaviour defined by the create-thread-behaviour macro is a simple thunk that can be spawned via the spawn macro. I'd like to implement the ability for (an instance of) a behaviour to send messages to itself via a self parameter that would be bound to (current-thread) (~ the thread that is running the behaviour).
I've tried to rig something up using syntax-parameterize but for some reason cannot get it to work. The code below implements a simple application that should clarify what I want to achieve - the special point of interest is the (unimplemented) <self> reference towards the bottom.
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (create-thread-behaviour stx)
(syntax-parse stx
[(_ body:expr ...+)
#'(λ () body ...)]))
(define-syntax (spawn stx)
(syntax-parse stx
[(_ behaviour:id)
#'(thread behaviour)]))
(define behaviour
(create-thread-behaviour
(let loop ()
(define message (thread-receive))
(printf "message: ~a~n" message)
(thread-send <self> "And this is crazy.")
(loop))))
(define instance (spawn behaviour))
(thread-send instance "Hey I just met you")
So the thing with syntax parameters that I tried is the following, which raises the self-defined "can only be used in a behaviour" error. I know I have correctly used syntax parameters before, but perhaps I have just been looking at the problem for too long.
(require racket/stxparam)
(define-syntax-parameter self
(lambda (stx) (raise-syntax-error (syntax-e stx) "can only be used in a behaviour")))
(define-syntax (spawn stx)
(syntax-parse stx
[(_ behaviour:id)
#'(thread
(lambda ()
(syntax-parameterize ([self #'(current-thread)])
(behaviour))))]))
You’re right that syntax parameters seem like the right tool for the job here. There are two issues here around your use of them, however, that are causing the issue. Let’s take them one at a time.
First of all, syntax parameters are semantically just syntax transformers, as you can see by your initial use of define-syntax-parameter, which binds the syntax parameter to a function. Your use of syntax-parameterize, in contrast, binds the syntax parameter to a piece of syntax, which is wrong. Instead, you need to bind it to a syntax transformer as well.
An easy way to achieve the behavior you’re looking for is to use the make-variable-like-transformer function from syntax/transformer, which makes a syntax transformer that, as the name would imply, behaves like a variable. More generally, though, it actually produces a transformer that behaves like an expression, which (current-thread) is. For that reason, your use of syntax-parameterize should actually look like this:
(require (for-syntax syntax/transformer))
(syntax-parameterize ([self (make-variable-like-transformer #'(current-thread))])
(behaviour))
This will avoid the “bad syntax” errors when attempting to use self after it has been parameterized.
However, there’s another problem in your code, which is that it appears to use a syntax parameter like a normal, non-syntax parameter, when syntax parameters don’t work like that. Normal parameters are effectively dynamically scoped, so the use of syntax-parameterize to wrap (behavior) would adjust self within the dynamic extent of the call to behavior.
Syntax parameters, however, don’t work like that. In fact, they can’t: Racket is syntactically a lexically scoped language, so you really can’t have a dynamic syntax binding: all syntax transformers are expanded at compile time, so adjusting a binding during the dynamic extent of a call is impossible. Syntax parameters are entirely lexically scoped, they simply hygienically adjust a binding within a particular scope. In that sense, they are really just like let, except that they adjust an existing binding rather than produce a new one.
With this consideration in mind, it becomes clear that putting the syntax-parameterize form in spawn can’t really work, because behavior is lexically defined outside of spawn. You could just move the use of syntax-parameterize to create-thread-behavior, but now there’s another problem, which is that this wouldn’t work:
(define (behavior-impl)
(define message (thread-receive))
(printf "message: ~a~n" message)
(thread-send self "And this is crazy.")
(behavior-impl))
(define behaviour
(create-thread-behavior
(behavior-impl)))
Now, once again, self is used outside of the lexical extent of syntax-parameterize, so it won’t be bound.
You’ve mentioned that this is a simplified example of what you’re actually doing, so maybe your real example requires a more complicated solution. If so, you may just need to require that self is only bound within the lexical extent of create-thread-behavior. However, your current use of self is remarkably simple, and in fact, it never changes: it’s always (current-thread). For that reason, you could actually just ditch syntax parameters entirely and define self directly:
(define-syntax self (make-variable-like-transformer #'(current-thread)))
Now self will work everywhere as a variable-looking reference to the value of a parameter, current-thread. This might be what you actually want, since it allows the value of self to be truly dynamically scoped (since it uses runtime parameters, not syntax parameters), but it still makes it look like a variable instead of a function.
I'm trying to move from Common Lisp to Chicken Scheme, and having plenty of problems.
My current problem is this: How can I write a macro (presumably using define-syntax?) that calls other macros?
For example, in Common Lisp I could do something like this:
(defmacro append-to (var value)
`(setf ,var (append ,var ,value)))
(defmacro something-else ()
(let ((values (list))
(append-to values '(1)))))
Whereas in Scheme, the equivalent code doesn't work:
(define-syntax append-to
(syntax-rules ()
((_ var value)
(set! var (append var value)))))
(define-syntax something-else
(syntax-rules ()
((_)
(let ((values (list)))
(append-to values '(1))))))
The append-to macro cannot be called from the something-else macro. I get an error saying the append-to "variable" is undefined.
According to all the information I've managed to glean from Google and other sources, macros are evaluated in a closed environment without access to other code. Essentially, nothing else exists - except built-in Scheme functions and macros - when the macro is evaluated. I have tried using er-macro-transformer, syntax-case (which is now deprecated in Chicken anyway) and even the procedural-macros module.
Surely the entire purpose of macros is that they are built upon other macros, to avoid repeating code. If macros must be written in isolation, they're pretty much useless, to my mind.
I have investigated other Scheme implementations, and had no more luck. Seems it simply cannot be done.
Can someone help me with this, please?
It looks like you're confusing expansion-time with run-time. The syntax-rules example you give will expand to the let+set, which means the append will happen at runtime.
syntax-rules simply rewrites input to given output, expanding macros until there's nothing more to expand. If you want to actually perform some computation at expansion time, the only way to do that is with a procedural macro (this is also what happens in your defmacro CL example).
In Scheme, evaluation levels are strictly separated (this makes separate compilation possible), so a procedure can use macros, but the macros themselves can't use the procedures (or macros) defined in the same piece of code. You can load procedures and macros from a module for use in procedural macros by using use-for-syntax. There's limited support for defining things to run at syntax expansion time by wrapping them in begin-for-syntax.
See for example this SO question or this discussion on the ikarus-users mailing list. Matthew Flatt's paper composable and compilable macros explains the theory behind this in more detail.
The "phase separation" thinking is relatively new in the Scheme world (note that the Flatt paper is from 2002), so you'll find quite a few people in the Scheme community who are still a bit confused about it. The reason it's "new" (even though Scheme has had macros for a long long time) is that procedural macros have only become part of the standard since R6RS (and reverted in R7RS because syntax-case is rather controversial), so the need to rigidly specify them hasn't been an issue until now. For more "traditional" Lispy implementations of Scheme, where compile-time and run-time are all mashed together, this was never an issue; you can just run code whenever.
To get back to your example, it works fine if you separate the phases correctly:
(begin-for-syntax
(define-syntax append-to
(ir-macro-transformer
(lambda (e i c)
(let ((var (cadr e))
(val (caddr e)))
`(set! ,var (append ,var ,val)))))) )
(define-syntax something-else
(ir-macro-transformer
(lambda (e i c)
(let ((vals (list 'print)))
(append-to vals '(1))
vals))))
(something-else) ; Expands to (print 1)
If you put the definition of append-to in a module of its own, and you use-for-syntax it, that should work as well. This will also allow you to use the same module both in the macros you define in a body of code as well as in the procedures, by simply requiring it both in a use and a use-for-syntax expression.
I want to define a list of accumulators with Emacs Lisp and write the following code, but I got a error saying that initV is a void variable. It seems initV is not evaluated in the function define-accum. Where is I make a mistake? (I just want to know why although I know there is other ways to reach my target.)
(defun define-accum (name initV)
(defalias name (lambda (v) (+ v initV))))
(setq accums '((myadd1 . 1)
(myadd2 . 2)))
(dolist (a accums)
(define-accum (car a) (cdr a)))
(message "result = %d" (+ (myadd1 1) (myadd2 1)))
You need to use backquotes properly. This would work for you, for instance:
(defun define-accum (name initV)
(defalias name `(lambda (v) (+ v ,initV))))
See here for an explanation
Apart from using backquotes, you can activate lexical binding (if you're using Emacs 24 or newer). For example, if I put your code in a .el file and put this on the first line:
;; -*- lexical-binding: t -*-
then I get the output:
result = 5
This works because the lambda function in define-accum will reference the initV in the environment where it's being defined (thus picking the variable in the argument list), and create a closure over this variable. With dynamic binding (the default), the function would look for initV in the environment where it's being called.
To add a little to what others have said -
If the variable (initV) is never actually used as a variable, so that in fact its value at the time the accumulator is defined is all that is needed, then there is no need for the lexical closure that encapsulates that variable and its value. In that case, the approach described by #juanleon is sufficient: it uses only the value at definition time - the variable does not exist when the function is invoked (as you discovered).
On the other hand, the lexical-closure approach lets the function be byte-compiled. In the backquote approach, the function is simply represented at runtime by a list that represents a lambda form. If the lambda form represents costly code then it can make sense to use the lexical-closure approach, even though (in this case) the variable is not really needed (as a variable).
But you can always explicitly byte-compile the function (e.g. ##NAME## in your define-accum. That will take care of the inefficiency mentioned in #2, above.
This is mostly a follow-up to this question. I decided to just keep YAGNI in mind and created a global variable (libpython). I set it to #f initially, then set! it when init is called. I added a function that should handle checking if that value has been initialized:
(define (get-cpyfunc name type)
(lambda args
(if libpython
(apply (get-ffi-obj name libpython type) args)
(error "Call init before using any Python C functions"))))
So now here's what I want to do. I want to define a macro that will take the following:
(define-cpyfunc Py_Initialize (_fun -> _void))
And convert it into this:
(define Py_Initialize (get-cpyfunc "Py_Initialize" (_fun -> _void)))
I've been reading through the macro documentation to try figuring this out, but I can't seem to figure out a way to make it work. Can anyone help me with this (or at least give me a general idea of what the macro would look like)? Or is there a way to do this without macros?
I've answered most of this question in the other one (I didn't see this one). It's fine to use a function that pulls out the bindings like this, but one possible problem here is that since you generate the binding only when the resulting function is called, this binding is re-created on each and every call. An easy way to solve this quickly is using promises, something like this:
(require scheme/promise)
(define (get-cpyfunc name type)
(define the-function
(delay (if libpython
(get-ffi-obj name libpython type)
(error "Call init before using any Python C functions"))))
(lambda args (apply (force the-function) args)))
But this is essentially almost the same as the code I posted in your previous question.
More random notes:
get-ffi-obj will accept a symbol as the name to bind to -- this is intentional, to make such macros (as in the last question) easy.
Using (symbol->string 'name) in a macro is fine. As I noted above in my comment reply to Nathan's comment, this means that it gets called at runtime, but mzscheme should be able to optimize that anyway, so there's no need to try and write some sophisticated macro that does the job at compile time.
Look inside the PLT directory -- you will find a collection called ffi. This is a collection of examples of bindings with various styles. Macros that create the bindings are very common in these examples.
Why don't you change the generated code to
(define Py_Initialize (get-cpyfunc 'Py_Initialize (_fun -> _void)))
and then have get-cpyfunc run (symbol->string name)?
Granted, there is probably a way to do this with syntax-case (I can never remember its syntax though), and definitely if you're using a Scheme with CL-esque define-macro.
It's not the complete answer, but I came up with a macro that meets both requirements (defines a variable and a string with the name of that variable):
> (define-syntax (my-syntax stx)
(syntax-case stx ()
[(_ id)
#'(define-values (id) (values (symbol->string (quote id))))]))
> (my-syntax y)
> y
"y"