Hi Damien! The problem that define only defines a variable in the current lexical environment. Even if a definition in an if block would work from a syntactical standpoint, it would be pointless.
As per r6rs, internal (define ...) are akin to letrec, but are only allowed in definition context. Guile 3 relaxes this for function bodies, whereas the macros I linked above relaxes this for some additional forms. It cannot however "export" bindings to any outer environment. What you can do is use module reflection to create top-level variables in the current module, but that makes everyone flinch about 105% of the time. -- Linus Björnstam On Wed, 9 Jun 2021, at 11:29, Damien Mattei wrote: > hello, i'm just answering now because my ten years old Mac book pro > definitely died sunday evening RIP > > i was trying to make macro that set! variable if they exist or create > it before if the variable is not defined (tested by the Guile procedure > 'defined?' which is not R*RS in any version) > > but it seems that Guile 3.0 'define' can not create variable in local > blocks, as in Python : > (if test > (begin > (define x 7) > (foo x)) > (else-block)) > will not work. > > This behavior force the definition of all variable at the upper level > of the function, the only advantage of guile 3.0 is perhaps (i have not > tested it fully) that you can put define not only at beginning of > function. > > This would be interesting to be able to define local variables with > 'define',defining variable only in the block they are usefull. > > With those limitation in mind i defined a few more macros: > (define-syntax <+ > (syntax-rules () > ((_ var expr) (define var expr)))) > > { x <+ 7 } is equivalent to : (<- x 7) or (define x 7) > > := is the same as <+ > (define-syntax := > (syntax-rules () > ((_ var expr) (define var expr)))) > > { x := 7 } is equivalent to : (:= x 7) or (define x 7) > > ;; definition without a value assigned > ;; (def x) > (define-syntax def > (syntax-rules () > ((_ var) (define var '())))) > > i added all that to my previous macro system in my Scheme+ > (unfortunately my github account is on my dead mac,so no commit for now) > > i do not think i can do more for now, define anywhere in code could be > a good solution to let letrec let* that in my opinion should no longer > exist in Scheme. > > Here is an example on the famous sub set sum problem algorithm in two > versions one with define 'anywhere' and the other with my previous > macro of Scheme+: > scheme@(guile-user)> (define L-init '(1 3 4 16 17 64 256 275 723 889 > 1040 1041 1093 1111 1284 1344 1520 2027 2734 3000 4285 5027)) > scheme@(guile-user)> (start-ssigma-sol-approx-pack-define-anywhere > L-init 19836) > $1 = (1 3 4 16 17 256 275 723 1040 1041 1284 1344 1520 3000 4285 5027) > scheme@(guile-user)> (apply + '(1 3 4 16 17 256 275 723 1040 1041 1284 > 1344 1520 3000 4285 5027)) > $2 = 19836 > > code: > *Preview:* > > (define (start-ssigma-sol-approx-pack-define-anywhere L t) ;; Sub Set > Sum problem (find solution or approximation) > ;; { } are for infix notation as defined in SRFI 105 > ;; <+ and := are equivalent to (define var value) > { best-sol <+ (lambda (L1 L2) > > {s1 <+ (apply + L1)} > {s2 <+ (apply + L2)} > > (if {(abs {t - s1}) <= (abs {t - s2})} > L1 > L2)) } > > ;; := is the same macro as <+ > { best-sol3 := (lambda (L1 L2 L3) > > {L22 <+ (best-sol L2 L3)} > (best-sol L1 L22)) } > > > { ssigma-sol-approx <+ (lambda (L) > ;; def is a macro for declared but unasigned > variable, it is same > as (define var '()) > (def c) > (def R) > > (if (null? L) > L > (begin {c <- (first L)} > {R <- (rest L)} > > (cond [ {c = t} (list c) ] ;; c is the > solution > [ {c > t} (best-sol (list c) > (ssigma-sol-approx R)) ] ;; c is > to big to be a solution but could be an approximation > ;; c < t at this point, 3 > possibilities : > ;; c is the best solution > ;; c is part of the solution or his > approximation > ;; or c is not part of solution or > his approximation > [ else (best-sol3 (list c) ;; c is > the best solution > > ;; c part of > solution or is approximation > (cons c > (start-ssigma-sol-approx-pack-define-anywhere R {t > - c})) ;; we have to find a solution or an approximation for t-c now > > ;; c is not part > of solution or his approximation > > (ssigma-sol-approx R))])))) } > > > ;; start the function > (ssigma-sol-approx L)) > * > * > > with other macros of Scheme+ code looked like this:* > * > > * > * > > *Preview:* > > ;; scheme@(guile-user)> (define L-init '(1 3 4 16 17 64 256 275 723 889 > 1040 1041 1093 1111 1284 1344 1520 2027 2734 3000 4285 5027)) > ;; scheme@(guile-user)> (start-ssigma-sol-approx-pack L-init 19836) > ;; $1 = (1 3 4 16 17 256 275 723 1040 1041 1284 1344 1520 3000 4285 > 5027) > > (define (start-ssigma-sol-approx-pack L t) ;; Sub Set Sum problem (find > solution or approximation) > > > (letrec-arrow* [ best-sol ← (lambda (L1 L2) > > (let-arrow* [ s1 ← (apply + L1) > s2 ← (apply + L2) ] > > (if {(abs {t - s1}) <= (abs {t - > s2})} > L1 > L2))) > > best-sol3 ← (lambda (L1 L2 L3) > > (let [(L22 (best-sol L2 L3))] > (best-sol L1 L22))) > > ssigma-sol-approx ← (lambda (L) > > (if (null? L) > > L > > (let-arrow* [ c ← (first L) > R ← (rest L) ] > > (cond [ {c = t} (list c) ] ;; c is > the solution > [ {c > t} (best-sol (list c) > (ssigma-sol-approx R)) ] ;; c is > to big to be a solution but could be an approximation > ;; c < t at this point, 3 > possibilities : > ;; c is the best solution > ;; c is part of the solution > or his approximation > ;; or c is not part of > solution or his approximation > [ else (best-sol3 (list c) ;; > c is the best solution > > ;;(begin > ;; > (display "append c=") (display c) (newline) > ;; c part > of solution or is approximation > (cons c > (start-ssigma-sol-approx-pack R {t - c}));;) ;; we > have to find a solution or an approximation for t-c now > > ;; c is not > part of solution or his approximation > > (ssigma-sol-approx R))])))) > > > ] > > ;; start the function > (ssigma-sol-approx L))) > > > the use of define anywhere will make code more readable, infixe > notation and macros too... > > A last example in Scheme+ with arrays on the dynamic solution of subset > sum problem (just answer if a solution exist or not): > > *Preview:* > > (include "../library-FunctProg/first-and-rest.scm") > (include "../library-FunctProg/guile/array.scm") > (include "../library-FunctProg/pair.scm") > (include "../library-FunctProg/number.scm") > (include "../library-FunctProg/list.scm") > (include "../library-FunctProg/let.scm") > > > (define L-init '(1 3 4 16 17 24 45 64 197 256 275 323 540 723 889 915 > 1040 1041 1093 1099 1111 1284 1344 1520 2027 2500 2734 3000 3267 3610 > 4285 5027)) > > (define t-init 35267) > > (define ls (length L-init)) > > (define dyna (make-array 0 {ls + 1} {t-init + 1})) > > (define (one-two b) > (if b 1 2)) > > (define cpt 0) > > ;; scheme@(guile-user)> (ssigma-dyna-define-anywhere L-init t-init) > ;; $1 = #t > ;; scheme@(guile-user)> cpt > ;; $2 = 147801 > (define (ssigma-dyna-define-anywhere L t) > > {cpt <- {cpt + 1}} ;; cpt is defined at toplevel > > ;;(display L) (display " ") (display t) (newline) > > {ls <+ (length L)} > {dyn <+ {dyna[ls t]}} > > (def c) > (def R) > > ;; dyna[ls t] means 0: unknown solution, 1: solution found, 2: no solution > (one? > (if (not (zero? dyn)) > > dyn > > ;; set the array but return the variable > { dyna[ls t] <- (one-two > (if (null? L) > #f > (begin > {c <- (first L)} > {R <- (rest L)} > (cond [ {c = t} #t ] ;; c is the solution > [ {c > t} (ssigma-dyna-define-anywhere R > t) ] ;; c is to big > to be a solution but can be an approximation > ;; c < t at this point > ;; c is part of the solution or his > approximation > ;; or c is not part of solution or his > approximation > [ else {(ssigma-dyna-define-anywhere R {t > - c}) or > (ssigma-dyna-define-anywhere R t)} ] )))) } ))) > > > Damien > > > On Sun, Jun 6, 2021 at 7:32 PM Linus Björnstam > <linus.inter...@fastmail.se> wrote: > > Try > > ,expand (new-set! X 7) at the repl. > > > > That will however not do what you want. define does not work like that. > > Define adds the binding in what is called the current lexical environment: > > a define inside an if will not be visible outside that if (even if it would > > have been valid syntax). > > > > What are you trying to write? > > > > -- > > Linus Björnstam > > > > On Sun, 6 Jun 2021, at 17:16, Damien Mattei wrote: > > > macros... i can not figure out how to make this one works: > > > (define-syntax new-set! > > > (syntax-rules () > > > ((_ var expr) (if (defined? (quote var)) > > > (set! var expr) > > > (define var expr))))) > > > > > > scheme@(guile-user)> (new-set! x 7) > > > ;;; <stdin>:24:0: warning: possibly unbound variable `x' > > > ;;; <stdin>:24:0: warning: possibly unbound variable `x' > > > ice-9/boot-9.scm:1669:16: In procedure raise-exception: > > > Unbound variable: x > > > > > > Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. > > > scheme@(guile-user) [1]> ,bt > > > In current input: > > > 24:0 1 (_) > > > In ice-9/boot-9.scm: > > > 1669:16 0 (raise-exception _ #:continuable? _) > > > > > > any idea? > > > > > > Damien > > > > > > On Sat, Jun 5, 2021 at 5:24 PM Linus Björnstam > > > <linus.inter...@fastmail.se> wrote: > > > > I implemented this hack before guile 3 got defines in function bodies: > > > > https://hg.sr.ht/~bjoli/guile-define > > > > > > > > Even I guile 3 it allows a more liberal placement of define, but it > > > > won't work for things like bodies of imported macros (like match) > > > > -- > > > > Linus Björnstam > > > > > > > > On Sat, 5 Jun 2021, at 00:27, Damien Mattei wrote: > > > > > hello, > > > > > i'm was considering that i want to be able to define a variable > > > > > anywhere in > > > > > code, the way Python do. Few scheme can do that (Bigloo i know) > > > > > ( the list here is not exact: > > > > > https://www.reddit.com/r/scheme/comments/b73fdz/placement_of_define_inside_lambda_bodies_in/ > > > > > ) > > > > > is it possible in guile to do it? i do not know, so could it be > > > > > added > > > > > to > > > > > the language specification for future release? > > > > > > > > > > regards, > > > > > Damien > > > > >