Re: Scheme closures

From: Jeff Dalton (jeff_at_todday.inf.ed.ac.uk)
Date: 04/24/04


Date: 24 Apr 2004 17:45:22 +0100


"Anton van Straaten" <anton@appsolutions.com> writes:

> Jeff Dalton wrote:
> > The promise of the rule language, like the promise of
> > backquote and quasiquote, was that you'd see a nice
> > picture of the result in the macro definition, thus
> > making it easy to understand.
>
> One of the promises, yes. Another goal for syntax-rules in particular was
> to deliberately restrict the sort of computation the compiler has to deal
> with at compile time, and/or to limit the bad things the programmer could do
> with it. It's these latter considerations that really limit syntax-rules.
> I demonstrate this below with a comparison to syntax-case.

Ok, but I wasn't trying to talk specifically about syntax-rules.

> > But when in rules it is broken down into a number of smaller
> > pictures, it can be hard to see what they all add up to.
>
> I think a lot can depend on how well they're written, how descriptive the
> names are, whether they're written to be easy to understand or to meet some
> other constraint, etc.

Absolutely right. However, none of the posted definitions
were easy to read, yet presumably their authors thought they
were writing the macro in a good way. That suggests that
there is a problem with the language.

Later you wrote:

> Re an earlier point about positional arguments, where e.g. an unnamed () may
> appear in a pattern argument list: I think that's pretty familiar to anyone
> who uses argument pattern matching, not just in macros. You also see it in
> functional languages like ML & Haskell.

I like the sort of pattern-matching used in functional languages
enough that I wrote macros to provide it in Lisp. Nonetheless,
I think it has some serious problems.

For instance, you see code that presents a picture of a data structure
(a constructor call) in which what goes with what is determined only
by position. In simple cases, it's nice.

But if you later change the data structure, such as by adding
a field, you have to go around and change all the patters.

There's the same problem in Prolog; and usually someone will
defend those languages by saying something about what good
code would do. Nonetheless, one still sees lots of code full of
positional patterns, written by good programmers, published
in well-regarded books, and so on.

These days, "refactoring" tools may be available. But people
wrote such code even when such tools did not exist.

(Perhaps someone will make a point about procedures having
positional parameters and so they can't really be so bad.
But the existence of a case that isn't too troublesome
does not show there's no problem in any case. Pattern-
matching tends to be used for things that would otherwise
be non-positional, such as saying "obj.field".)

> When you see something like that,
> you know it's a base case, and you look to one of the other patterns
> for a name for it. It's not something I'm usually consciously aware
> of.

Sure, and as I mentioned people can also get used to recognizing the
constructs that do the equivalent of calling map; but it's kind of
like saying map isn't a benefit, because programmers could develop
the ability to recognize the pattern. They still have to at least
look at more text; and that's a cost.

> > Also, I don't understand why _this_ macro is so hard.
> >
> > It had seemed like it ought to be one of the really
> > straightforward ones.

> Probably the biggest limitation is the lack of a shortcut to define
> temporary variables in syntax-rules. For define-values, it would be
> nice to be able to write something like this:
>
> (define-syntax define-values
> (syntax-rules ()
> ((define-values (var ...) expr)
> (begin
> (define var (if #f #f)) ...
> (call-with-values
> (lambda () expr)
> (lambda (var ...) (set! var var) ...))))))
>
> But in syntax-rules, there's no way to disambiguate the two uses of 'var' in
> the last lambda, and no way - without using additional rules or macros - to
> generate temporaries corresponding to the vars.

Why do you have (define var (if #f #f)) instead of, say
(define var #f)?

> We can easily do this with syntax-case, though:
>
> (define-syntax (define-values stx)
> (syntax-case stx ()
> ((define-values (var ...) expr)
> (with-syntax (((tmp ...) (generate-temporaries (syntax (var ...)))))
> (syntax
> (begin
> (define var (if #f #f)) ...
> (call-with-values
> (lambda () expr)
> (lambda (tmp ...) (set! var tmp) ...))))))))
>
> This does the trick.

That's much nicer, though I wonder about the "stx" and the
"(if #f #f)".

> > Despite the always confusing use of "_" (which breaks the picture
> > model), I find it easy to understand.
>
> You probably know that the "_" is an optional shorthand - you can use the
> name of the macro if you like.

Yes.

> I think this is one of those shortcuts which
> which may look confusing at first, but which experienced users tend to
> quickly adopt, because its benefits soon become obvious. The benefit is
> that you're not repeating the name of the macro over and over in the
> patterns.

What happens in nested definitions? Also, I'm more concerned
about reading. That the name would be repeatedly typed doesn't
seem like much of a cost, especially since editors will
typically be able to complete it when only partially typed.

It might be a benefit when reading, but it's not clear. In some
cases, it would be, because it would be easier to pick out the "_"s
than to pick out the instances of the macro name.

A similar abbreviation hasn't been defined for procedures,
though it might also be useful. Though procedures are a
different case, it still suggests that the benefits are
not large.

-- jd



Relevant Pages

  • Re: Design Patterns and Functional programming
    ... OCaml, Standard ML and Scala. ... Impurity is not required, as purely functional languages do exist, but it ... the model-view-controller design pattern. ... Then you can use pattern matching to manipulate ...
    (comp.object)
  • Universal Translators - undoing babel
    ... the hologram to encode it as a specific image. ... The interference pattern diffracts beams of light creating ... sound waves can be interfered and diffracted as well. ... sounded natural continuous and in each of our respective languages. ...
    (rec.arts.startrek.tech)
  • Re: Design Patterns and Functional programming
    ... OCaml, Standard ML and Scala. ... Impurity is not required, as purely functional languages do exist, but it ... this form of static checking requires the pattern matcher to be ... compiler use to parse literals of the type t, that is up to the compiler. ...
    (comp.object)
  • Re: Design Patterns and Functional programming
    ... Impure functional programming languages like Mathematica, Lisp, Scheme, ... a pattern match gives yes/no ... What is the subject of matching. ... body of another function, here a constructor. ...
    (comp.object)
  • Re: Styles help
    ... Your other 'procedures' probably have a different pattern when you reveal ... were looking for in your original macro that you posted. ... But the heading ... To provide instruction for flushing the lube oil system on RFW DT 1B and RFW ...
    (microsoft.public.word.vba.general)