Just a comment about how to compare identifiers. In some cases, using
equal? and syntax-e gives the wrong result. It's better to use
free-identifier=? . For example, in this program we can use three
methods to compare identifiers (there are more!).

The program has two macros:

clasify-id: shows the result of three methods to compare identifiers.

show: it creates an unuseful temporal variable, and shows the value of
the "argument" and the value of the unuseful variable.

The problem is that that temporal variable is called temp, so it can
confuse the comparison methods because it has the same name that one
of the module level variables. But if free-identifier=? does a more
thoughtful comparison.

;---
#lang racket

(define-syntax (clasify-id stx)
  (syntax-case stx ()
    [(_ x y)
     (begin
       (displayln
        (list (equal? #'x #'y)
              (equal? (syntax-e #'x) (syntax-e #'y))
              (free-identifier=? #'x #'y)))
       #'(void))]))

(define-syntax (showln stx)
  (syntax-case stx ()
    [(_ var)
     #'(let ([temp (random)])
         (displayln (list temp var))
         (clasify-id temp var))]))

(define x 5)
(define temp 5)

(clasify-id x temp)  ;==> (#f #f #f)
(clasify-id x x)     ;==> (#F #t #t) <-- the first is wrong
(showln x)           ;==> (#f #f #f)
(showln temp)        ;==> (#f #T #f) <-- the seccond is wrong
;---

Gustavo


On Sun, Sep 11, 2016 at 12:26 PM, Vasily Rybakov <madbada...@gmail.com> wrote:
> Hi, gustavo!
>
> Thanks for your answer, it was very helpful.
>
> So i rewrote my (substitute-term) macro like this:
>
> (define-syntax (substitute-term stx)
>   (syntax-case stx ()
>     [(_ term-from term-to (body0 body ...))
>      #`#,(append (if (equal? (syntax-e #'body0) (syntax-e #'term-from))
>                      (list #'term-to)
>                      (list #'body0))
>                  #'((substitute-term term-from term-to body) ...))]
>     [(_ term-from term-to body)
>      (if (equal? (syntax-e #'body)
>                  (syntax-e #'term-from))
>          #'term-to
>          #'body)]))
>
> The (syntax-e) parts is kept because (equal? #'body #'term-from) won't yield 
> #t.
>
> Now it works:
>>(substitute-term and or (and #t #f))
> #t
>
> After a little bit tinkering I returned to (case) form, so it can substitute 
> not only single terms, but whole expressions:
>
> (define-syntax (substitute-syntax stx)
>   (syntax-case stx ()
>     [(_ term-from term-to body)
>      (cond
>        [(equal? (syntax->datum #'body) (syntax->datum #'term-from)) #'term-to]
>        [(list? (syntax->datum #'body)) #`#,(append (if (equal? (syntax->datum 
> (car (syntax-e #'body)))
>                                                                (syntax->datum 
> #'term-from))
>                                                        (list #'term-to)
>                                                        (list #`#,(car 
> (syntax-e #'body))))
>                                                    (map (lambda (x)
>                                                           (append (syntax-e 
> #'(substitute-syntax term-from term-to))
>                                                                   (list x)))
>                                                         (cdr (syntax-e 
> #'body))))]
>          [else #'body])]))
>
>>(substitute-syntax (and #t #f) or ((and #t #f) #f #t))
> Expands into (or #t #f)
> #t
>
> And my final version of recursion looks like this:
> (define-syntax recursion
>   (syntax-rules ()
>     [(_ (args ...) body ...)
>      ((lambda (x) (x x))
>       (lambda (generated-label)
>         (lambda (args ...)
>           (substitute-syntax recursion (generated-label generated-label) 
> body) ...)))]
>     [(_ label (args ...) body ...)
>      ((lambda (x) (x x))
>       (lambda (label)
>         (lambda (args ...)
>           (substitute-syntax label (label label) body) ...)))]))
>
> So it can be used without label, if there are no nested recursions:
>>((recursion (n)
>             (if (zero? n)
>                 1
>                 (* n (recursion (sub1 n))))) 5)
> 5
>
> Now it works, as intended.
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to