On Fri, May 10, 2024 at 5:24 PM Jean Abou Samra <j...@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.