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

Damien Mattei <[email protected]>
Newsgroups gmane.lisp.guile.user
Message-ID <CADEOadcJv29iNCeSG020ZKyaDgzwMo5AmwOUDsrnYe1GQzFp2g@mail.gmail.com>
On Fri, May 10, 2024 at 5:24 PM Jean Abou Samra <[email protected]> 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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.