Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you rewrite "begin" in Scheme?

Tags:

scheme

As the Wikipedia article explains, begin in Scheme is a library form that can be rewritten using more fundamental forms like lambda.

But how do you rewrite a begin, especially considering the following?

x
===> error: undefined identifier: x
(begin (define x 28) x)
===> 28
x
===> 28
like image 747
eljenso Avatar asked Nov 05 '09 21:11

eljenso


People also ask

What is begin in Scheme?

Scheme begin expressions aren't just code blocks, though, because they are expressions that return a value. A begin returns the value of the last expression in the sequence. For example, the begin expression above returns the value returned by the call to bar . The bodies of procedures work like begin s as well.

What is an expression in Scheme?

A Scheme expression is a construct that returns a value, such as a variable reference, literal, procedure call, or conditional. Expression types are categorized as primitive or derived. Primitive expression types include variables and procedure calls.

How do you define a constant in a Scheme?

Just define the value at the toplevel like a regular variable and then don't change it. To help you remember, you can adopt a convention for naming these kinds of constants - I've seen books where toplevel variables are defined with *stars* around their name.

How does let work in Scheme?

In Scheme, you can use local variables pretty much the way you do in most languages. When you enter a let expression, the let variables will be bound and initialized with values. When you exit the let expression, those bindings will disappear.


2 Answers

You cannot. The thing is that begin has two roles: one is sequence a bunch of side-effectful expressions, and the other is that it is used to "splice" macro results. The fact that you can use begin with a definition as in the above is a result of this second feature, and you cannot write it yourself.

If you really want to follow the whole story, then you could define begin as the simple macro which makes it do only the sequencing aspect (and it can indeed be implemented as such, though usually it isn't). But, you need to add explicit recognition of begins to splice definitions (toplevel or internal). This means that a macro implementation is fine, but it cannot really be a library because the core expander should know about it. (And because the language is lexically scoped, there is no good way for the core expander to identify begins that are not defined in the core language.)

To summarize all of this, you could say that R5RS is only wrong in classifying begin as "library syntax", since it can't be defined in a library... but even that's not entirely accurate since R5RS defines "library syntax" as just "derived expressions". The real wrong point is, therefore, the fact that one of begins two faces is implemented elsewhere, in the expander (for definition contexts).

Note also that R6RS clarifies the whole deal: the two faces of begin are made explicit, and it is now part of the core language, not a "library form", and not even a derived form.

like image 155
Eli Barzilay Avatar answered Oct 20 '22 12:10

Eli Barzilay


You are still welcome to try writing a version of begin which satisfies its first role: sequencing.

(define-syntax sequencing
  (syntax-rules ()
    [(_ expression) expression]
    [(_ expression expressions ...)
     ((lambda (ignored) (sequencing expressions ...)) expression)]))

Here is the post from which I took that snippet. It provides better context if you are interested, and you might be.

like image 21
grettke Avatar answered Oct 20 '22 12:10

grettke