Newsgroups: comp.lang.scheme
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!fas-news.harvard.edu!newspump.wustl.edu!news.ecn.bgu.edu!vixen.cso.uiuc.edu!howland.reston.ans.net!ix.netcom.com!netcom.com!activis
From: activis@netcom.com (ActiVision)
Subject: Re: Streams with MacGambit 2.2
Message-ID: <activisDFHG3q.CqA@netcom.com>
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
X-Newsreader: TIN [version 1.2 PL1]
References: <robcorp-2109951219290001@goldfish.pond.com>
Date: Mon, 25 Sep 1995 22:35:49 GMT
Lines: 71
Sender: activis@netcom20.netcom.com

Robert C. Houser (robcorp@pond.com) wrote:
: I'm trying to implement streams as discussed in SICP (great book, btw)
: with MacGambit v 2.2.  The problem is, I need to define cons-stream as a
: special form and I don't think I can do this.

: I'm using the following defines:

: (define (cons-stream h t)
:    (cons h (delay t)))

: (define (head stream)
:    (car stream))

: (define (tail stream)
:    (force (cdr stream)))

: When I try to create a simple, infinite stream of 1's with the following:

: (define ones (cons-stream 1 ones))

: I get the following error:
: *** ERROR -- Unbound variable: ones

: I assume this is due to the fact that the evaluator is trying to evaluate
: the variable ones within the cons-stream expression.

: Any help would be appreciated.  I'm also interested in how this can be
: done with XLISP 2.1g.

You've already answered your own question: `ones' in your example is indeed
being evaluated, as you surmise, and your assertion that you need to make
cons-stream a special form is also correct.

Fortunately, Gambit allows you to create your own special forms using a non-
standard extension to the language, ##define-macro.  The thing to remember
about ##define-macro is that it's used to hand off what amount to templates
to be evaluated, with the templates filled in by evaluating arbitrary
expressions.

For example, cons-stream might look like this:

(##define-macro (cons-stream (thing stream)
  `(cons ,thing (delay ,stream))))

This obviously isn't terribly different from your define form.  What's
different about it is that anywhere you invoke cons-stream it will be replaced
with the literal code provided in the template.  One way that you know that
a template is a template is by the backquote.  Backquote is a lot like the
single quote (') that you use to denote a literal value, except that it leaves
room for placeholders.  A placeholder is denoted by a comma (,) and almost
always refers to a parameter of the macro, which is just spliced in as is.

For example, (define ones (cons-stream 1 ones)) would be replaced with:

(define ones (cons 1 (delay ones)))

and since it's a direct substitution, the use of `ones' wouldn't be evaluated,
and since delay is a built-in special form, `ones' _still_ wouldn't be
evaluated, and in fact would be delayed, which is the whole point of streams.
`ones' would then be what you are expecting: an infinitely long stream of
the fixnum value 1.

: Thanks.

: Robert C. Houser
: ROBcorp

I hope that this clarifies things,

Paul Snively
psnively@activision.com
