i already do it this way for internal defines ,using a recursive macro that build a list of variable using an accumulator. It can works but macro expansion seems slow, it was not immediate at compilation on a little example (oh nothing more that 2 seconds) but i'm not sure it is easily maintainable, it is at the limit what macro can do i think ,for speed reasons. In fact i can not really understand in Guile as it is based on C and compiled when macro expansion happens,what is the time cost... so for all those ,perhaps not objective reason ,i prefer to avoid. On Wed, Sep 22, 2021 at 11:06 AM William ML Leslie < william.leslie.ttg@gmail.com> wrote: > You could do it the same way python does it: have `def` be a macro that > inspects its body for assignments to symbols, and then let-bind them at the > top of the function. > > On Wed, 22 Sep 2021, 6:45 pm Damien Mattei, > wrote: > >> Hi Taylan, >> >> i have used Module System Reflection, and it works almost for what i >> wanted to do,the only big problem is that it creates variable binding >> global, seen from every where and that breaks my example code, by the way i >> will display for everybody an example of use of such a macro,so everyone >> can understand the Scheme extension i want to do. I try to extend the >> language, so i'm in a way construncting code from outside but not >> completely, you can consider yes if you consider macro is a way to >> construct code from outside in the way it expand in a new code from >> another... hash table is not solution,too complex, need a global >> variable... it try to make thing as simple as possible to keep speed >> expansion and code up,so do not use recursive macro expansion,for now >> things are fast. >> >> Here is a partial solving probleme solution with Module System Reflection >> but i hope to be able to create local lexical scoping variable not only >> global ones,because instead i will have to use 2 different assignment >> operators (one replacing define and one replacing set!) and want things as >> simple as possible and Scheme-like but Python in a function creates only >> variables global to the function,i can include an option to do that too in >> Scheme+ . >> >> So here is the assignment operator and an example code explaining its >> caveats: >> >> *Preview:* >> >> (define-syntax <- >> (syntax-rules () >> ((_ var expr) (let* ((modul (current-module)) >> (exist-var (module-variable modul (quote var)))) >> (if exist-var >> (module-set! modul (quote var) expr) >> (module-define! modul (quote var) expr)))))) >> >> >> notice that the <- operator defined above has been removed of the >> arrays,vectors,etc support for readability, here i focus only on "simple" >> scheme variable ,arrays,vectors is working great already. >> >> *Preview:* >> >> (define (subset-sum-guile L t) >> >> {ls <- (length L)} >> {dyn <- dyna[ls t]} >> >> ;; dyna[ls][t] means 0: unknown solution, 1: solution found, 2: no solution >> >> (condx [{dyn <> 0} (one? dyn)] >> [(null? L) {dyna[ls t] <- 2} #f] ;; return #f >> >> [exec {c <- (first L)}] >> ;; c is the solution >> [{c = t} {dyna[ls t] <- 1} #t] ;; return #t >> >> [exec {R <- (rest L)}] >> ;; continue searching a solution in the rest >> [{c > t} {s <- (subset-sum-guile R t)} >> {dyna[ls t] <- (one-two s)} >> s] ;; return boolean value >> >> ;; else : c < t at this point >> ;; c is part of a solution OR not part of a solution >> [else {s <- {(subset-sum-guile R {t - c}) or (subset-sum-guile R t)}} >> {dyna[ls t] <- (one-two s)} >> s])) ;; return boolean value >> >> >> note that condx (conditionnal with pre execution) is just a cond allowing >> to execute code before testin next condition and so on... >> >> here how it "compiles" in Guile Scheme+: >> >> scheme@(guile-user)> (load "SssDyna.scm") >> ;;; note: source file >> /home/mattei/Dropbox/git/library-FunctProg/SssDyna.scm >> ;;; newer than compiled >> /home/mattei/.cache/guile/ccache/3.0-LE-8-4.2/home/mattei/Dropbox/git/library-FunctProg/SssDyna.scm.go >> ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0 >> ;;; or pass the --no-auto-compile argument to disable. >> ;;; compiling /home/mattei/Dropbox/git/library-FunctProg/SssDyna.scm >> ;;; SssDyna.scm:73:8: warning: possibly unbound variable `array-ref-set!' >> ;;; SssDyna.scm:192:28: warning: possibly unbound variable `ยง' >> ;;; SssDyna.scm:400:2: warning: possibly unbound variable `dyn' >> ;;; SssDyna.scm:408:10: warning: possibly unbound variable `dyn' >> ;;; SssDyna.scm:408:21: warning: possibly unbound variable `dyn' >> ;;; SssDyna.scm:411:15: warning: possibly unbound variable `c' >> ;;; SssDyna.scm:413:10: warning: possibly unbound variable `c' >> ;;; SssDyna.scm:415:15: warning: possibly unbound variable `R' >> ;;; SssDyna.scm:417:10: warning: possibly unbound variable `c' >> ;;; SssDyna.scm:417:24: warning: possibly unbound variable `R' >> ;;; SssDyna.scm:417:24: warning: possibly unbound variable `R' >> ;;; SssDyna.scm:417:18: warning: possibly unbound variable `s' >> ;;; SssDyna.scm:418:33: warning: possibly unbound variable `s' >> ;;; SssDyna.scm:408:2: warning: possibly unbound variable `s' >> ;;; SssDyna.scm:423:22: warning: possibly unbound variable `R' >> ;;; SssDyna.scm:423:42: warning: possibly unbound variable `c' >> ;;; SssDyna.scm:423:54: warning: possibly unbound variable `R' >> ;;; SssDyna.scm:423:22: warning: possibly unbound variable `R' >> ;;; SssDyna.scm:423:42: warning: possibly unbound variable `c' >> ;;; SssDyna.scm:423:54: warning: possibly unbound variable `R' >> ;;; SssDyna.scm:423:15: warning: possibly unbound variable `s' >> ;;; SssDyna.scm:424:30: warning: possibly unbound variable `s' >> ;;; SssDyna.scm:408:2: warning: possibly unbound variable `s' >> ;;; compiled >> /home/mattei/.cache/guile/ccache/3.0-LE-8-4.2/home/mattei/Dropbox/git/library-FunctProg/SssDyna.scm.go >> >> it compiles well, you will notice that variables seems unbound to >> compiler because they are created *dynamically* by the macro of <- >> operator but that is not a problem. >> >> They create well but they create globally. >> >> i ran the test code example like this: >> (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)) >> it search if exist a solution to the subset sum problem on the list >> L-init with sum being 35267, >> there exist such a solution so the return answer must be #t. >> >> with global definitions the return value is wrong (#f) because variables >> are created globallly. >> the problem is in those lines: >> [exec {R <- (rest L)}] >> will assign (rest L) to R, but R is a global variable! ,R must be local >> to function, it is worse than Python because <- create toplevel variables >> !!!, and then when i execute: >> [else {s <- {(subset-sum-guile R {t - c}) or (subset-sum-guile R t)}} >> the first clause of or run well: (subset-sum-guile R {t - c}) >> but modify R as it is not a local variable and then the second clause of >> or: (subset-sum-guile R t) return wrong result because it is called with R >> containing a bad value: >> (subset-sum-guile L-init t-init) >> #f >> scheme@(guile-user)> R >> () >> R exist now at top-level !!! >> >> the solution to make the code run well in this case was just to create a >> local variables,using another assignment operator <+ that add a local >> variable in local lexical scope the way define do it: >> [exec {R <- (rest L)}] is equivalent to [exec (define R (rest L))] >> and then the code succeed again and return #t value. >> >> So i want now to have by default a lexical scope for <- and new variables >> to be local to the nested block ,not global, even not local to function (as >> in Python) even if in this particuliar example code would have run well >> with local scoping. (but note that if <- is called on an already existing >> variable of a different scope,upper or global,or top-level, i want ot be >> able to set! it) >> I want to be able to control the scoping of variables so i can make this >> assignment operator the way i want,and also propose different assignment >> operators with different variable scope. >> >> Damien >> >> >> On Sun, Sep 19, 2021 at 11:39 PM Taylan Kammer >> wrote: >> >>> On 19.09.2021 09:54, Damien Mattei wrote: >>> > hello, >>> > i'm developing an extension to Scheme >>> > and i need a procedure or macro that define a variable only if it is >>> not bind and if it is just set! it. >>> > >>> > I can not do it in Guile or any Scheme,and i'm desperately searching a >>> way to do that. I finally conclude that it can be done only by adding it in >>> the language. >>> > >>> > Can someone include a such function in Guile next release? >>> > i know guile have a predicate defined? to test binfing of a vairable >>> but writing a macro with it is not possible because define can be used in >>> an expression context. >>> > >>> > Thank in advance for any help >>> > Damien >>> >>> What is the utility of such a function? Since Scheme is lexically >>> scoped, >>> it's generally obvious whether a variable has already been defined or >>> not, >>> rendering such an operation useless. >>> >>> If you're constructing code from outside input so that you don't know >>> whether a provided variable name represents a variable that's already >>> been >>> defined or not, then you could use the module reflection API: >>> >>> >>> https://www.gnu.org/software/guile/manual/html_node/Module-System-Reflection.html >>> >>> Sounds like 'module-define!' does exactly what you ask for. I wonder >>> what >>> exactly your use-case is though. Chances are that your use-case is best >>> served with a simple data structure like a hash table... >>> >>> -- >>> Taylan >>> >>