guile-devel
[Top][All Lists]
Advanced

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

Re: new function


From: Damien Mattei
Subject: Re: new function
Date: Wed, 22 Sep 2021 11:53:59 +0200

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, <damien.mattei@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.kammer@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

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