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

Re: New revision of SRFI 26 available

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



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))))