guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: define anywhere


From: Linus Björnstam
Subject: Re: define anywhere
Date: Wed, 09 Jun 2021 12:11:21 +0200
User-agent: Cyrus-JMAP/3.5.0-alpha0-519-g27a961944e-fm-20210531.001-g27a96194

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.internet@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.internet@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
> > > > > 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]