Email list hosting service & mailing list manager

New revision of SRFI 26 available sperber@xxxxxx (04 Jun 2002 16:27 UTC)
Re: New revision of SRFI 26 available Al Petrofsky (04 Jun 2002 18:58 UTC)

Re: New revision of SRFI 26 available Al Petrofsky 04 Jun 2002 18:57 UTC

Some issues with the latest draft:

In the code samples within the html, like this:

  <code>(cut cons (+ a 1) <>)</code>

My browser is displaying this as (cut cons (+ a 1) ).  The angle
brackets need to be escaped.

  (apply + (map (cut if <> 0 1) '(#f #t #t #f)))

This is an error according to the specification that "const"s must be
expressions.  I suggest you keep that requirement and drop support for
this usage unless you can come up with a reasonable semantics for (cut
quasiquote <>), or some way to specify which non-expressions are and
are not allowed as "const"s.

   <const-or-slot> --> <>              ; a "slot"
                       | <expression>  ; a constant, not directly dependent
				       ;  on the slots

The constants aren't indirectly dependent on the slots either.
Perhaps "a `constant', an expression independent of the slot values"
would be clearer.

  In case there is a rest-slot symbol for the residual arguments of a
  variable arity procedure, the resulting procedure is also of
  variable arity

If a system provides a variable-arity? procedure, I would expect it to
interact with cut like this:

  (variable-arity? list)             => #t
  (variable-arity? (cut list <>))    => #f
  (variable-arity? cons)             => #f
  (variable-arity? (cut cons <...>)) => #t

Hence, I think it would be simpler and more accurate to say:

  If there is a rest-slot symbol for residual arguments, the resulting
  procedure is of variable arity

The implementation gets the second of these tests wrong:

  (let* ((x 'cute) (y (cut  list x))) (set! x 'cut) (y))  => cut
  (let* ((x 'cute) (y (cute list x))) (set! x 'cut) (y))  => cute

Two non-bug drawbacks to the implementation are that it doesn't catch
errors like (cut if <> 0 1) and it forces an evaluation order for the
"const"s in a cute expression.  Here's one way to address all three
issues:

; (srfi-26-internal-cut slot-names combination . cs)
;   transformer used internally
;     slot-names  : the internal names of the slots
;     combination : procedure being specialized, followed by its arguments
;     cs          : consts-or-slots, the qualifiers of the macro

(define-syntax srfi-26-internal-cut
  (syntax-rules (<> <...>)

    ;; construct fixed- or variable-arity procedure
    ((srfi-26-internal-cut (slot-name ...) (proc arg ...))
     (lambda (slot-name ...) ((begin proc) arg ...)))
    ((srfi-26-internal-cut (slot-name ...) (proc arg ...) <...>)
     (lambda (slot-name ... . rest-slot) (apply proc arg ... rest-slot)))

    ;; process one const-or-slot
    ((srfi-26-internal-cut (slot-name ...)   (position ...)      <>    . cs)
     (srfi-26-internal-cut (slot-name ... x) (position ... x)          . cs))
    ((srfi-26-internal-cut (slot-name ...)   (position ...)      const . cs)
     (srfi-26-internal-cut (slot-name ...)   (position ... const)      . cs))))

; (srfi-26-internal-cute slot-names const-bindings combination . cs)
;   transformer used internally
;     slot-names     : the internal names of the slots
;     const-bindings : let-style bindings for the constants.
;     combination    : procedure being specialized, followed by its arguments
;     cs             : consts-or-slots, the qualifiers of the macro

(define-syntax srfi-26-internal-cute
  (syntax-rules (<> <...>)
    ;; If there are no const-or-slots to process, then:
    ;; construct a fixed-arity procedure,
    ((srfi-26-internal-cute
      (slot-name ...) const-bindings (proc arg ...))
     (let const-bindings (lambda (slot-name ...) (proc arg ...))))
    ;; or a variable-arity procedure
    ((srfi-26-internal-cute
      (slot-name ...) const-bindings (proc arg ...) <...>)
     (let const-bindings (lambda (slot-name ... . x) (apply proc arg ... x))))

    ;; otherwise, process one slot:
    ((srfi-26-internal-cute
      (slot-name ...)         const-bindings  (position ...)   <>    . cs)
     (srfi-26-internal-cute
      (slot-name ... x)       const-bindings  (position ... x)       . cs))
    ;; or one const
    ((srfi-26-internal-cute
      slot-names              const-bindings  (position ...)   const . cs)
     (srfi-26-internal-cute
      slot-names ((x const) . const-bindings) (position ... x)       . cs))))

; exported syntax

(define-syntax cut
  (syntax-rules (<> <...>)
    ((cut . consts-or-slots)
     (srfi-26-internal-cut () () . consts-or-slots))))

(define-syntax cute
  (syntax-rules (<> <...>)
    ((cute . consts-or-slots)
     (srfi-26-internal-cute () () () . consts-or-slots))))