I'm currently learning some r7rs and I am trying to implement a macro 'begin' as following :
(begin0 expr0 expr1 ... expr2)
With expr being a regular expression (Like (set! x (+ x 1)))
And begin0 as a macro that evaluates all the expression but return only the expr1 result.
For example :
(let ((year 2017))
(begin1 (set! year (+ year 1))
year
(set! year (+ year 1))
year))
It musts return 2018
I've created a begin function first :
(define-syntax begin0
(syntax-rules ()
((begin-0 body-expr-0 body-expr-1 ...)
(let ((tmp body-expr-0)) body-expr-1 ... tmp))))
And now, I'm trying to understand how I can do to return the value of "body-expr-1" ?
I've done the following code, but it says that I'm missing some ellipsis and I don't understand how to do it.
(define-syntax begin1
(syntax-rules ()
((begin1 body-expr-0 body-expr-1 ... body-expr-2)
(let ((tmp body-expr-0) body-expr-1 ... tmp)
(cond (eq? tmp body-expr-1)
(begin . tmp))))))
I hope that it is understandable enough, thanks for the answers.
This can be done, but the macro will interfere such that you cannot do all the things with begin1 as with begin.
(define-syntax begin1
(syntax-rules ()
((_ expr0 expr1 exprn ...)
(begin
expr0
(let ((result expr1))
exprn ...
result)))))
The code that does not work is this:
(begin1
(define global1 10)
test3
(define global2 20))
The reason is obvious. It expands to:
(begin1
(define global1 10)
(let ((result~1 test3))
(define global2 20)
result~1))
The second define will be changed to a letrec such that the variable global2 is only available for the duration of the let. I have no fix for this since it requires you to be able to do global define from a closure.
begin1 is rather strange feature. In Racket and perhaps other Scheme dialects we have begin0 that returns the result of the first expression. This is very useful. eg. here is a counter:
(define (get-counter from)
(lambda ()
(let ((tmp from))
(set! from (+ from 1))
tmp)))
And with begin0:
(define (get-counter from)
(lambda ()
(begin0
from
(set! from (+ from 1)))))
In Racket begin0 is a primitive. So it is a form supported in the fully expanded program and thus implemented in C, just like begin..
So, I found a possible way to do it, I didn't though we could just ask a condition on the immediate value :
(define-syntax begin1
(syntax-rules ()
((begin1 body-expr-0 body-expr-1 body-expr-2 ...)
(if body-expr-1
(write body-expr-1)))))
Related
Does call/cc in Scheme the same thing with yield in Python and JavaScript?
I am not clear about generators. In my opinion, yield gives a language the ability to generate iterators without pain. But I am not sure whether I am right.
Does call/cc in Scheme has something related to yield in other languages? If so, are they the same thing, or what is the difference?
Thanks!
call/cc is a much more general language feature than generators. Thus you can make generators with call/cc, but you cannot make call/cc with generators.
If you have a program that computes values and use those values in other places its basically a step machine.. One might think of it as a program that have one function for each step and a continuation for the rest of the steps. Thus:
(+ (* 3 4) (* 5 6))
Can be interpreted as:
((lambda (k)
(k* 3 4 (lambda (v34)
(k* 5 6 (lambda (v56)
(k+ v34 v56 k)))))
halt)
The k-prefix just indicate that it's a CPS-version of the primitives. Thus they call the last argument as a function with the result. Notice also that the order of evaluation, which is not defined in Scheme, is in fact chosen in this rewrite. In this beautiful language call/cc is just this:
(define (kcall/cc kfn k)
(kfn (lambda (value ignored-continuation)
(k value))
k))
So when you do:
(+ (* 3 4) (call/cc (lambda (exit) (* 5 (exit 6)))))
; ==> 18
Under the hood this happens:
((lambda (k)
(k* 3 4 (lambda (v34)
(kcall/cc (lambda (exit k)
(exit 6 (lambda (v6)
(k* 5 v6 k)))
k))))
halt)
By using the substitution we can prove that this actually does exactly as intended. Since the exit function is invoked the original continuation is never called and thus the computation cancelled. In contrast to call/cc giving us this continuation that doesn't seem obvious it's no magic in CPS. Thus much of the magic of call/cc is in the compiler stage.
(define (make-generator procedure)
(define last-return values)
(define last-value #f)
(define (last-continuation _)
(let ((result (procedure yield)))
(last-return result)))
(define (yield value)
(call/cc (lambda (continuation)
(set! last-continuation continuation)
(set! last-value value)
(last-return value))))
(lambda args
(call/cc (lambda (return)
(set! last-return return)
(if (null? args)
(last-continuation last-value)
(apply last-continuation args))))))
(define test
(make-generator
(lambda (collect)
(collect 1)
(collect 5)
(collect 10)
#f)))
(test) ; ==> 1
(test) ; ==> 5
(test) ; ==> 10
(test) ; ==> #f (procedure finished)
One might make a macro to make the syntax more similar, but it's just sugar on top of this.
For more examples I love Matt Mights page with lots of examples on how to use continuations.
Here's code to define a generator:
(define-syntax define-generator
(lambda (x)
(syntax-case x (lambda)
((stx name (lambda formals e0 e1 ...))
(with-syntax ((yield (datum->syntax (syntax stx) 'yield)))
(syntax (define name
(lambda formals
(let ((resume #f) (return #f))
(define yield
(lambda args
(call-with-current-continuation
(lambda (cont)
(set! resume cont)
(apply return args)))))
(lambda ()
(call-with-current-continuation
(lambda (cont)
(set! return cont)
(cond (resume (resume))
(else (let () e0 e1 ...)
(error 'name "unexpected return"))))))))))))
((stx (name . formals) e0 e1 ...)
(syntax (stx name (lambda formals e0 e1 ...)))))))
There are examples of the use of generators at my blog. Generators use call-with-current-continuation, in a manner similar to yield in Python, but are much more general.
You can implement generators with call/cc. Here is an example:
coroutines.ss
They work in a similar way to python and ECMAScript generators.
I want to be able to take a procedure and see what it looks like. Is this possible?
For example, let's say I have:
(define (some-func x)
(+ x 1))
What I want to do is apply some amazing function (say, stringify) to some-func and be able to look at its guts.
\> (stringify some-func)
"(lambda (x) (+ x 1))"
I haven't found any Racket libraries that do it. Can it be done?!
In R6RS, there is no sure way to determine if two procedures are equivalent; even an expression like (let ((p (lambda () 42))) (eqv? p p)) is not guaranteed to be true.
R7RS addresses that by using the concept of "location tags", where each lambda expression generates a unique location tag. Then eqv? works for procedures by comparing location tags: thus, (let ((p (lambda () 42))) (eqv? p p)) is true, and (eqv? (lambda () 42) (lambda () 42)) is false.
There is no reliable way to get the source of a procedure (many implementations macro-expand and compile the procedures, discarding the original source), and even if you could, you could not use it to compare if two procedures are "equal", because of closures (and that two procedures could have the same "source" but have their free variables bound to different things). For example, consider the two expressions (let ((x 1)) (lambda () x)) and (let ((x 2)) (lambda () x)). They have the same "source", but nobody in their right mind would claim that they are equivalent in any way.
Note, you could easily implement a define alternative to keep the source around. You don't avoid the lexical issues but, modulo that, you've got something with limited use.
(define name->source-mapping '())
(define (name->source name)
(cond ((assq name name->source-mapping) => cdr)
(else #f)))
(define (name->source-extend name source)
(set! name->source-mapping (cons (cons name source) name->source-mapping))
(define-syntax define-with-source
((_ (name args ...) body1 body2 ...)
(define name
(begin (name->source-mapping-extend 'name '(lambda (args ...) body1 body2 ...))
name->source-mapping))
(lambda (args ...) body1 body2 ...)))))
[Above does not replace (define name value) syntax; consider the above an example only.]
I'm currently writing metacircular evaluator in Scheme, following the SICP book's steps.
In the exercise I am asked to implement letrec, which I do in the following way:
(define (letrec->let exp)
(define (make-unassigned var)
(list var '*unassigned*))
(define (make-assign binding)
(list 'set! (letrec-binding-var binding)
(letrec-binding-val binding)))
(let ((orig-bindings (letrec-bindings exp)))
(make-let
(map make-unassigned
(map letrec-binding-var orig-bindings))
(sequence->exp
(append
(map make-assign orig-bindings)
(letrec-body exp))))))
However, when I evaluate the expression as follows, it goes into infinite loop:
(letrec
((a (lambda () 1)))
(+ 1 (a)))
Do I miss anything?
(Full Source Code at GitHub).
I checked result transformation result of (let ((x 1)) x) and got:
((lambda (x) (x)) 1)
instead of:
((lambda (x) x) 1)
obviously problem is in let body processing. If I were you, I would use utility function:
(define (implicit-begin exps)
(if (= 1 (length x))
(car x)
(cons 'begin x)))
By the way: I would say, that your letrec implementation is not very correct. Your transformation returns:
(let ((x1 *unassigned*>) ... (xn *unassigned*))
(set! x1 ...)
...
(set! xn ...)
body)
It much more resembles letrec* which evaluates expressions for variable bindings in left-ro-right order (Scheme itself doesn't specify arguments evaluation order):
syntax: letrec* bindings body
Similar to ‘letrec’, except the INIT expressions are bound to their
variables in order.
‘letrec*’ thus relaxes the letrec restriction, in that later INIT
expressions may refer to the values of previously bound variables.
The more correct code would be:
(let ((x1 *unassigned*) ... (xn *unassigned*))
(let ((t1 ...) ... (tn ...))
(set! x1 t1)
...
(set! xn tn))
body)
Suppose I have something like this:
(define pair (cons 1 (lambda (x) (* x x))
If I want to return the front object of the pair I do this:
(car pair)
And it returns 1. However when the object is a procedure I don't get the exact description of it.
In other words:
(cdr pair)
returns #<procedure> and not (lambda (x) (*x x)).
How do I fix this?
Although there's no way to do this generally, you can rig up something to do it for procedures that you define.
Racket structs can define a prop:procedure that allows the struct to be applied (called) as a procedure. The same struct can hold a copy of your original syntax for the function definition. That's what the sourced struct is doing, below.
The write-sourced stuff is simply to make the output cleaner (show only the original sexpr, not the other struct fields).
The define-proc macro makes it simpler to initialize the struct -- you don't need to type the code twice and hope it matches. It does this for you.
#lang racket
(require (for-syntax racket/syntax))
;; Optional: Just for nicer output
(define (write-sourced x port mode)
(define f (case mode
[(#t) write]
[(#f) display]
[else pretty-print])) ;nicer than `print` for big sexprs
(f (sourced-sexpr x) port))
(struct sourced (proc sexpr)
#:property prop:procedure (struct-field-index proc)
;; Optional: Just to make cleaner output
#:methods gen:custom-write
[(define write-proc write-sourced)])
;; A macro to make it easier to use the `sourced` struct
(define-syntax (define-proc stx)
(syntax-case stx ()
[(_ (id arg ...) expr ...)
#'(define id (sourced (lambda (arg ...) expr ...)
'(lambda (arg ...) expr ...)))]))
;; Example
(define-proc (foo x)
(add1 x))
(foo 1) ; => 2
foo ; => '(lambda (x) (add1 x))
The procedure cons evaluates its arguments: 1 is self-evaluating to 1; (lambda ...) evaluates to an anonymous procedure. If you want to 'prevent' evaluation, you need to quote the argument, as such:
> (define pair (cons 1 '(lambda (x) (* x x))
> (cdr pair)
(lambda (x) (* x x))
This seems to work, it's a macro that expands to successive integers depending on how many times it has been expanded.
;; Library (test macro-state)
(library
(test macro-state)
(export get-count incr-count)
(import (rnrs))
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1)))
)
;; Program
(import (rnrs) (for (test macro-state) expand))
(define-syntax m
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count)))))))
(write (list (m) (m) (m)))
(newline)
;; prints (1 2 3)
But it's clumsy to me because the macro state *count* and the macro m itself are in different modules. Is there a better way to do this in r6rs, preferably one that doesn't split the implementation over two modules?
EDIT
I should make it clear that although this example is just a single macro, in reality I'm looking for a method that works when multiple macros need to share state.
You can make the state local to the macro transformer:
(define-syntax m
(let ()
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1)))
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count))))))))
Edited to add: In Racket, you can also do this:
(begin-for-syntax
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1))))
(define-syntax m
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count)))))))
But I don't think R6RS has anything that corresponds to begin-for-syntax.