[plt-scheme] macros, special forms, and lazy functions
----- Original Message -----
From: "Stephen Bloch" <sbloch at adelphi.edu>
To: "PLTScheme List" <plt-scheme at list.cs.brown.edu>
Sent: Thursday, December 10, 2009 5:53 PM
Subject: [plt-scheme] macros, special forms, and lazy functions
> As far as my beginning students are concerned, "and" and "or" are functions with contract
> Boolean Boolean ... -> Boolean
> They happen to be "smart" about their arguments, not bothering to evaluate the later arguments if the earlier arguments answer
> the question.
In fact -> any (including multiple values), for example:
(and #t #t (values 1 2)) --> multiple value 1 2
> But in fact, they're implemented as macros or special forms. (Is there a difference between a macro and a special form?) Which
> makes no difference in BSL, BSLLA, or ISL, but once we get to ISLL, it makes a difference: one cannot pass "or" or "and" as
> arguments to a function that expects a function.
I think a special form is a is a definition or expression that starts with a syntactic keyword (an identifier that in its scope is
recognized as a syntactioc keyword) A macro or transformer is an expansion time procedure that does the expansion of a special form
(at expansion time)
>
> Is it feasible for a function in (say) ISLL to refer to a function whose definition is in a module written in Lazy Scheme? If
> so, would it be reasonable to define "and" and "or" that way, so they could be passed around as functions?
Imagine you try to use the #%app hook to delay the evaluation of the arguments of and and or. Then write functions <and> and <or>
that do force their arguments as far as necessary. For this you could make a simple language that exports all of scheme or
scheme/base except that it exports its own versions of #%app, and and or. However, in this case <and> and <or> have to be recognized
by #%app at expansion time which means that something like ((if test and or) arg ...) would not work. Mixing eager and lazy code is
very difficult, I think.
>
> Failing that, would it be reasonable to define "and" and "or" in such a way that if they appear other than in function-call
> position, they evaluate to a function that does the right thing, so again they could be passed around as functions?
Something like:
#lang scheme
(provide (rename-out (or* or)))
(define-syntax (or* stx)
(syntax-case stx (or*)
((or* arg ...) #'(or arg ...))
(or* #'or**)))
(define (or** . args)
(cond
((null? args) #t)
((null? (cdr args)) (car args))
(else (or (car args) (apply or** (cdr args))))))
((if #t or* list) 1 (write 2) (write 3))
; --> writes 2 and 3, returns 1
(or* 1 (write 2) (write 2))
; does not write, returns 1.
However it seems pretty messy to me <or> sometimes evaluating all <arguments> and sometimes just as many as needed. Why not stick to
and and or as special forms and use regular functions with slightly different names (like andf and orf) where a function is wanted
(implying that all their arguments are evaluated)
The same questions can be asked for <if>. In regular scheme it is a syntactic keyword, but in lazy scheme it is a variable bound to
a procedure.
#lang lazy
(write ((if #t if list) 1 2 3)) --> writes 2
(write ((if #f if list) 1 2 3)) --> writes (1 2 3)
Jos
>
>
> Stephen Bloch
> sbloch at adelphi.edu
>
> _________________________________________________
> For list-related administrative tasks:
> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>