• Infix notation in Scheme

    From Maciek Godek@21:1/5 to All on Tue Jun 23 07:37:56 2020
    The SRFI has already been finalized, but today I came up with an "even better" implementation:

    (define-syntax extract-placeholders
    (syntax-rules (_ is isnt)
    ((extract-placeholders final (() () body))
    (final (infix/postfix . body)))

    ((extract-placeholders final (() args body))
    (lambda args (final (infix/postfix . body))))

    ((extract-placeholders final (((is . t) . rest) args (body ...)) . *)
    (extract-placeholders final (rest args (body ... (is . t))) . *))

    ((extract-placeholders final (((isnt . t) . rest) args (body ...)) . *)
    (extract-placeholders final (rest args (body ... (isnt . t))) . *))

    ((extract-placeholders final (((h . t) . rest) args body) . *)
    (extract-placeholders final ((h . t) () ()) (rest args body) . *))

    ((extract-placeholders final (() (args ...) body) (rest (args+ ...)
    (body+ ...)) . *)
    (extract-placeholders final (rest (args+ ... args ...)
    (body+ ... body)) . *))

    ((extract-placeholders final ((_ . rest) (args ...) (body ...)) . *)
    (extract-placeholders final (rest (args ... arg) (body ... arg)) . *))

    ((extract-placeholders final ((arg . rest) args (body ...)) . *)
    (extract-placeholders final (rest args (body ... arg)) . *))

    ))


    (define-syntax-rule (is . something)
    (extract-placeholders identity-syntax (something () ())))

    (define-syntax-rule (isnt . something)
    (extract-placeholders not (something () ())))

    The definition of infix/postfix remains the same.

    The new definition allows to use placeholder in a nested position, as in

    (is (length _) < 5)

    is equivalent to

    (lambda (_) (< (length _) 5))

    It also allows to nest the "is" and "isnt" combinators (they are treated specially by the macro itself):

    (is (length (filter (is (modulo _ 2) = 0) _)) < 5)

    is equivalent to

    (lambda (_) (< (length (filter (lambda (_) (= (modulo _ 2) 0)) _)) 5))

    It's a shame that the SRFI process is over ;]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Maciek Godek@21:1/5 to All on Tue Jun 23 12:10:02 2020
    W dniu wtorek, 23 czerwca 2020 16:37:59 UTC+2 użytkownik Maciek Godek napisał:
    The SRFI has already been finalized, but today I came up with an "even better" implementation:

    (define-syntax extract-placeholders
    (syntax-rules (_ is isnt)
    ((extract-placeholders final (() () body))
    (final (infix/postfix . body)))

    ((extract-placeholders final (() args body))
    (lambda args (final (infix/postfix . body))))

    ((extract-placeholders final (((is . t) . rest) args (body ...)) . *)
    (extract-placeholders final (rest args (body ... (is . t))) . *))

    ((extract-placeholders final (((isnt . t) . rest) args (body ...)) . *)
    (extract-placeholders final (rest args (body ... (isnt . t))) . *))

    ((extract-placeholders final (((h . t) . rest) args body) . *)
    (extract-placeholders final ((h . t) () ()) (rest args body) . *))

    ((extract-placeholders final (() (args ...) body) (rest (args+ ...)
    (body+ ...)) . *)
    (extract-placeholders final (rest (args+ ... args ...)
    (body+ ... body)) . *))

    ((extract-placeholders final ((_ . rest) (args ...) (body ...)) . *)
    (extract-placeholders final (rest (args ... arg) (body ... arg)) . *))

    ((extract-placeholders final ((arg . rest) args (body ...)) . *)
    (extract-placeholders final (rest args (body ... arg)) . *))

    ))


    (define-syntax-rule (is . something)
    (extract-placeholders identity-syntax (something () ())))

    (define-syntax-rule (isnt . something)
    (extract-placeholders not (something () ())))

    The definition of infix/postfix remains the same.

    The new definition allows to use placeholder in a nested position, as in

    (is (length _) < 5)

    is equivalent to

    (lambda (_) (< (length _) 5))

    It also allows to nest the "is" and "isnt" combinators (they are treated specially by the macro itself):

    (is (length (filter (is (modulo _ 2) = 0) _)) < 5)

    is equivalent to

    (lambda (_) (< (length (filter (lambda (_) (= (modulo _ 2) 0)) _)) 5))

    It's a shame that the SRFI process is over ;]

    Actually, the new implementation also allows placeholders in operator positions, so that the following expressions are legal (and all evaluate to #t):

    (every (is (+ _ _) even?) '(1 2 3 4) '(5 6 7 8))

    ((is 2 _ 3) <)

    ((is (expt _ 2) _ (expt _ 2) _ (expt _ 2)) 2 <= -2 < -3)

    ((is (_ 5) = 25) (λ (x) (* x x)))

    I don't know what to make of it, but I kinda like it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Maciek Godek@21:1/5 to All on Thu Oct 29 14:43:18 2020
    wtorek, 23 czerwca 2020 o 21:10:05 UTC+2 Maciek Godek napisał(a):

    I have recently found some issues in the above implementation of the is/isnt macros.

    First, they didn't handle improper lists properly, so usages like this one failed to expand:

    (is '(x . y) member '((a . b) (p . q) (x . y))

    Moreover, the placeholders in quoted positions were processed as in all other positions, so the code

    (is '_ member '(_ __ ___))

    expanded to something like

    (lambda (arg1 arg2) (member 'arg1 '(arg2 __ ___)))

    Likewise, quasiquotation wasn't properly supported.

    The implementation can be found here:

    https://github.com/plande/grand-scheme/blob/master/grand/function.scm#L110

    (it still needs some small fixes, because I just found that it doesn't handle unquotation in the tail position properly yet, but I should have it done by tomorrow)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)