[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

SRFI-31 (rec): name; overjustification; formal specification

This page is part of the web mail archives of SRFI 31 from before July 7th, 2015. The new archives for SRFI 31 contain all messages, not just those from before July 7th, 2015.



I just noticed that a new draft was made two months ago.

[Note to srfi editors: I would actually prefer it if the entirety of
each draft revision was automatically sent out on the srfi's
discussion list.  Well, perhaps very long drafts shouldn't be emailed,
but they should certainly all be archived.  It is sometimes difficult
to extract wisdom from the discussion archives when there is no
archive of the drafts being discussed.  [Query to srfi editors: where
should this suggestion be discussed?  Should there be a srfi-srfi
mailing list?]]

The name of the srfi should include rec, as in "Rec: a special form
for recursive evaluation".  It's quite annoying that the full title of
srfi-11, "Syntax for receiving multiple values", fails to indicate
whether it's the let-values srfi or the receive srfi.

I think the rationale section is too long and distracting.  Rec is not
a novel feature, and there's no need to go into detail about the
difference between a definition and an expression.  How about a simple
"Rec provides a concise syntax for those letrec expressions in which
there is a single variable clause and the body is just a reference to
this variable.  It provides an even more concise syntax, consistent
with prototype definitions, for such letrecs in which the initializer
is a lambda expression."

To your list of example factorial expressions, I would add one using
internal define, and one using only lambda, thus making the following
list (in decreasing order of brevity):

  (rec (f n) (if (zero? n) 1 (* n (f (- n 1)))))
  (let () (define (f n) (if (zero? n) 1 (* n (f (- n 1))))) f)
  (lambda (n) (let f ((n n)) (if (zero? n) 1 (* n (f (- n 1))))))
  (letrec ((f (lambda (n) (if (zero? n) 1 (* n (f (- n 1))))))) f)
  ((lambda (f) (f f))
   (lambda (f) (lambda (n) (if (zero? n) 1 (* n ((f f) (- n 1)))))))
  
Your attempt to specify rec's semantics in terms of define (which you
mistakenly call a "command") makes little sense to me, and seems not
to cover many details, such as whether or not (rec x (set! x 1)) is an
error[1].  As you discuss in the rationale, a rec expression is very
different from a definition.  Why not simply specify rec in terms of
letrec?

I think the formal syntax and semantics should more closely follow the
model of r5rs, like so:

  Formal syntax:

    <rec expression> is added to the production for <derived expression>.

    <rec expression> ---> (rec <variable> <expression>)
			| (rec (<variable> <def formals>) <body>)

  Formal semantics:

    A rec expression has the semantics of the letrec expression
    that results from the use of this macro:

    (define-syntax rec
      (syntax-rules ()
	((rec (name . args) . body)
	 (letrec ((name (lambda args . body))) name))
	((rec name expression)
	 (letrec ((name expression)) name))))

BNF and syntax-rules are the right languages to use for these
specifications.  Devising your own method of specification is almost
sure to cause confusion.

-al


[1]  (letrec ((x (set! x 1))) x) is an error in r5rs, but many
implementations allow it.  I will refrain from mentioning that
(call-with-current-continuation (lambda (k) (define x (set! x (k 1))) x))
is a legal r5rs expression that evaluates to 1.