guile-user
[Top][All Lists]
Advanced

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

Re: Understanding `symbol??` macro from okmij.org


From: Zelphir Kaltstahl
Subject: Re: Understanding `symbol??` macro from okmij.org
Date: Thu, 14 Mar 2024 13:46:31 +0000

On 3/14/24 02:01, Jean Abou Samra wrote:
Hi!

The explanations are on

https://okmij.org/ftp/Scheme/macros.html#macro-symbol-p

Maybe this version will be easier to understand (we don't really
need continuation-passing style here):

(define-syntax symbol??
   (syntax-rules ()
     ((symbol?? maybe-symbol)
      (let-syntax
          ((test
            (syntax-rules ()
              ((test maybe-symbol) #t)
              ((test _) #f))))
        (test abracadabra)))))

(symbol?? foo) ⇒ #t
(symbol?? (a . b)) ⇒ #f
(symbol?? 5) ⇒ #f
(symbol?? "a") ⇒ #f
(symbol?? #(1 a)) ⇒ #f


Basically: the macro call

(symbol?? <foobar>)

expands to a macro definition of test as

(syntax-rules ()
   ((test <foobar>) #t)
   ((test _) #f))

and a call (test abracadabra). Now, observe that if <foobar>
is a symbol, then it's a catch-all pattern when inserted
in the syntax-rules definition of `test`, so it will match
abracadabra (because it matches anything). On the other hand,
if it's not a symbol, then it won't match abracadabra, by case
analysis: if it's a number it will only match that number; booleans,
strings and characters likewise; if it's a pair it can only match
pairs; if it's a vector it can only match vectors; etc.

I'm not exactly sure why Oleg Kiselyov included special cases for a pair
and a vector, but my guess is that not all Scheme implementations
support vectors in syntax-rules patterns (and the pair check is
necessary because the car or cdr could contain a vector). The Scheme
standards certainly have their opinion on this, and I knew that
stuff by heart at some point (when I implemented a syntax-rules/syntax-case
expander for a university project), but I don't remember, and it's
too late for scouring the standards...

Best,
Jean


On 3/14/24 02:03, Maxime Devos wrote:

(define-syntax symbol??

   (syntax-rules ()

     ;; The check is done by first pattern matching against some other

     ;; forms, that are not a symbol.

     ((symbol?? (x . y) kt kf) kf) ; It's a pair, not a symbol

     ((symbol?? #(x ...) kt kf) kf) ; It's a vector, not a symbol

The first two cases don’t need any explanation I think.

     ;; After those things are excluded, the thing might be a symbol.

     ((symbol?? maybe-symbol kt kf)

      (let-syntax ((test

                    (syntax-rules ()

                      ((test maybe-symbol t f) t)

                      ((test x t f) f))))

        (test abracadabra kt kf)))))

If maybe-symbol is a symbol, then (test abracadabra kt kf) matches (test maybe-symbol t f) (let t=kt, f=kf, maybe-symbol=abracadabra).

If maybe-symbol is not a symbol, for example it is a string “hello”  (please ignore wrong quoting), then

(test maybe-symbol t f) becomes (test “hello” t f).  The string “hello” cannot act as an identifier (because it is a string, not a symbol), so (test abracadabra kt kf) does not match the first case (test maybe-symbol t f). Only the second case (test x t f) remains, and (test abracadabra kt kf) matches this (set x to abracadabra, t to kt, f to kf).

I think the first two cases are superfluous, but perhaps there is a performance advantage.

(I’m wondering if this still works in the case (symbol? ...), because ... is special in syntax-rules)

Best regards,

Maxime Devos.

Thank you both!

Mind-blowing stuff. But I think I understand it now. How clever.

Best regards,
Zelphir

--
repositories:https://notabug.org/ZelphirKaltstahl


reply via email to

[Prev in Thread] Current Thread [Next in Thread]