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, <damien.mat...@gmail.com> 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 <taylan.kam...@gmail.com>
> 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
>>
>

Reply via email to