guile-user
[Top][All Lists]
Advanced

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

Re: with-syntax return error in Guile, not in Kawa or Racket


From: Damien Mattei
Subject: Re: with-syntax return error in Guile, not in Kawa or Racket
Date: Fri, 10 May 2024 23:57:32 +0200

On Fri, May 10, 2024 at 5:24 PM Jean Abou Samra <jean@abou-samra.fr> wrote:

>
> the built-in let macro creates a kind of "access token" for the variable
> lin, and marks the body (display (mac lin)) with that token so that it
> has the variable lin in scope. This is so that forms introduced by macros
> (like mac here) which happen to also use the name lin will not interfere.
> Now, when you do the syntax->datum, you strip away all that information,
> and with (datum->syntax #f …), you convert the symbols back to syntax,
> but with zero scope information (as documented in the Guile manual).
> That means they can only refer to top-level variables. So the lookup
> of the local variable lin fails, but it works if lin is a global variable
> (because global variables are dynamic in Scheme, cf. module-set! and all
> that, unlike local variables which are static).
>
>
> > in Guile the 2 examples works:
> >
> > scheme@(guile-user)> (define-syntax mac
> >   (lambda (sintax)
> >     (syntax-case sintax ()
> >       ((mac arg)
> >        (datum->syntax #f (syntax->datum #'arg))))))
> > scheme@(guile-user)> (define lin 6)
> > scheme@(guile-user)> (display (mac lin))
> > 6scheme@(guile-user)> (let ((lin 5))
> >   (display (mac lin)))
> > 6scheme@(guile-user)>
>
>
> Well, here, the second example runs but display 6, not 5, i.e. it looks
> up the global variable defined earlier, not the local one.
>
>
>
yes with a global variables the things are different , my macro too find
the global variable

here is the simplest counter example i can create,not in a program just at
REPL with this version of Scheme+:

i will use 2 simple example:

(let ((lin 2)) {T[lin  1] <- -5})

and

(let ((lin 2)) {T[lin  1] ← -5})

the first works ,not the second

GNU Guile 3.0.8.99-f3ea8
 scheme@(guile-user)>(use-modules (Scheme+))
scheme@(guile-user)> (use-modules (array))
scheme@(guile-user)> (define T (make-array-2d 5 3 0))
scheme@(guile-user)> T
$1 = #(#(0 0 0) #(0 0 0) #(0 0 0) #(0 0 0) #(0 0 0))
scheme@(guile-user)> (let ((lin 2)) {T[lin  1] <- -5})
<- : #'(index ...) = (#<syntax:unknown file:6:18 lin> #<syntax:unknown
file:6:23 1>)
<- : (syntax->datum #'(index ...)) = (lin 1)
<- : #'parsed-args=#<syntax (#<syntax:assignment.scm:116:64 list> lin 1)>
<- :  (syntax->datum #'parsed-args)=(list lin 1)
scheme@(guile-user)> T
$1 = #(#(0 0 0) #(0 0 0) #(0 -5 0) #(0 0 0) #(0 0 0))
scheme@(guile-user)> (define T (make-array-2d 5 3 0))
scheme@(guile-user)> T
$2 = #(#(0 0 0) #(0 0 0) #(0 0 0) #(0 0 0) #(0 0 0))
scheme@(guile-user)> (let ((lin 2)) {T[lin  1] ← -5})
<- : #'(index ...) = (#<syntax:unknown file:10:18 lin> #<syntax:unknown
file:10:23 1>)
<- : (syntax->datum #'(index ...)) = (lin 1)
<- : #'parsed-args=#<syntax (#<syntax:assignment.scm:116:64 list> lin 1)>
<- :  (syntax->datum #'parsed-args)=(list lin 1)
;;; <stdin>:10:15: warning: possibly unbound variable `lin'
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Unbound variable: lin

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,bt
In current input:
    10:15  1 (_)
In ice-9/boot-9.scm:
  1685:16  0 (raise-exception _ #:continuable? _)




here is a longer example, more near the logiki code and things are worst:

(define (foo) {T ← (make-array-2d 5 3 0)}
                    (for-basic (lin 0 4)
                          (display lin) (newline)
                          {T[lin 1] ← -5})
                      T)

foo should   create T a 2D array : #(#(0 0 0) #(0 0 0) #(0 0 0) #(0 0 0)
#(0 0 0))
the for loop from 0 to 4 display lin ,set T[lin 1] to -5 and return T but
it fails and the compiler warn me about lin undefined (if i define lin at
top level it compile but the code will not use lin of the loop but of top
level and it acts as if there is 2 lin variables! the one of toplevel that
is used in {T[lin 1] ← -5} and the one of the loop for-basic that is used
in  (display lin) (newline) ! :

scheme@(guile-user)> (define lin 1)
scheme@(guile-user)> (define (foo) {T ← (make-array-2d 5 3 0)}
                    (for-basic (lin 0 4)
                          (display lin) (newline)
                          {T[lin 1] ← -5})
                      T)
<- : #'(index ...) = (#<syntax:unknown file:40:29 lin> #<syntax:unknown
file:40:33 1>)
<- : (syntax->datum #'(index ...)) = (lin 1)
<- : #'parsed-args=#<syntax (#<syntax:assignment.scm:116:64 list> lin 1)>
<- :  (syntax->datum #'parsed-args)=(list lin 1)
scheme@(guile-user)> (foo)
0
1
2
3
4
$11 = #(#(0 0 0) #(0 -5 0) #(0 0 0) #(0 0 0) #(0 0 0))

notice only one element of array as been modified

if i use <- directly it works:

scheme@(guile-user)> (define (bar) {T <- (make-array-2d 5 3 0)} (for-basic
(lin 0 4) (display lin)(newline) {T[lin  1] <- -5})
 T)
<- : #'(index ...) = (#<syntax:unknown file:31:90 lin> #<syntax:unknown
file:31:95 1>)
<- : (syntax->datum #'(index ...)) = (lin 1)
<- : #'parsed-args=#<syntax (#<syntax:assignment.scm:116:64 list> lin 1)>
<- :  (syntax->datum #'parsed-args)=(list lin 1)
scheme@
of course all this is made by the datum->syntax in this part of the macro:
;; parse arguments at posteriori here:
     (with-syntax ((parsed-args (datum->syntax stx ; #f
      (cons #'list
           (optimizer-parse-square-brackets-arguments-lister
      (syntax->datum #'(index ...)))))))

to run those example i did not even need to comment/uncomment code or
recompile logiki, i just used the toplevel with scheme+ but in this version
i use the cloning with:

(define-syntax ←
  (syntax-rules ()
    ((← . args)
     (<- . args))))

it is clear that calling <- via ← give a bad result, if instead i use
directly <- code works.


reply via email to

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