unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* new function
@ 2021-09-19  7:54 Damien Mattei
  2021-09-19 14:41 ` Matt Wette
  2021-09-19 21:38 ` Taylan Kammer
  0 siblings, 2 replies; 19+ messages in thread
From: Damien Mattei @ 2021-09-19  7:54 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 576 bytes --]

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

[-- Attachment #2: Type: text/html, Size: 1239 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-19  7:54 new function Damien Mattei
@ 2021-09-19 14:41 ` Matt Wette
  2021-09-19 14:43   ` Matt Wette
  2021-09-19 21:38 ` Taylan Kammer
  1 sibling, 1 reply; 19+ messages in thread
From: Matt Wette @ 2021-09-19 14:41 UTC (permalink / raw)
  To: guile-devel

On 9/19/21 12:54 AM, 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

Check the manual.

scheme@(guile-user)> (define-once a 1)
scheme@(guile-user)> (define-once a 2)
scheme@(guile-user)> a
$1 = 1
scheme@(guile-user)>





^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-19 14:41 ` Matt Wette
@ 2021-09-19 14:43   ` Matt Wette
  0 siblings, 0 replies; 19+ messages in thread
From: Matt Wette @ 2021-09-19 14:43 UTC (permalink / raw)
  To: guile-devel



On 9/19/21 7:41 AM, Matt Wette wrote:
> On 9/19/21 12:54 AM, 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
>
> Check the manual.
>
> scheme@(guile-user)> (define-once a 1)
> scheme@(guile-user)> (define-once a 2)
> scheme@(guile-user)> a
> $1 = 1
> scheme@(guile-user)>
>

Sorry.  I misread your post.   How about this:

mwette$ guile
scheme@(guile-user)> (define-once a 1)
scheme@(guile-user)> (define-once a 2)
scheme@(guile-user)> a
$1 = 1

scheme@(guile-user)> (define a 1)
scheme@(guile-user)> (define a 2)
scheme@(guile-user)> a
$2 = 2
scheme@(guile-user)>






^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-19  7:54 new function Damien Mattei
  2021-09-19 14:41 ` Matt Wette
@ 2021-09-19 21:38 ` Taylan Kammer
  2021-09-21 12:26   ` Damien Mattei
  2021-09-22  8:44   ` Damien Mattei
  1 sibling, 2 replies; 19+ messages in thread
From: Taylan Kammer @ 2021-09-19 21:38 UTC (permalink / raw)
  To: Damien Mattei, guile-devel

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



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-19 21:38 ` Taylan Kammer
@ 2021-09-21 12:26   ` Damien Mattei
  2021-09-22  8:44   ` Damien Mattei
  1 sibling, 0 replies; 19+ messages in thread
From: Damien Mattei @ 2021-09-21 12:26 UTC (permalink / raw)
  To: Taylan Kammer; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 7145 bytes --]

here is the "draft mail" i think it was better to answer separetely,but i
send it waiting more...

thanks for all the answer,
i'm answering in a single answer to all for easyness and because some
answers where same

First some people don't understand well my goal. It was just to be able to
create an assignment operator the way Python,C,etc do it :
in Python if i create a variable, simply like that x=7 in a function,
block...the variable can be modified the same way later: x=8 and the
binding have a lexical scope (?),can be see anywhere in block or function
and more if global keyword used .
In scheme it is different ,the binding is made first by definition
let,let*,letrec.... and after if you want to modify it with set! or if you
redo a define or a let in a block or nested code it will become a local
variable to the block .
(which is perhaps not a problem,depending what we want to do)
Note that perhaps it is not clear or not a good idea what i want to do,
testing will be necessary.
What complicate the things when creating macro or code doing this
assignment operator is that in Scheme:
-i got often this error (not really clear for me): example : unknown
file:6:7: definition in expression context, where definitions are not
allowed, in form (define modul (current-module))
-begin act in a dual way: sequencing and slicing (
https://www.gnu.org/software/guile/manual/html_node/begin.html) this is
rarely a problem but here yes ,i often got errors in my macros because of
that.

Now about the solutions:
Taylan give me some hints to answer, i first wrote this macro:

(define-syntax <$
  (syntax-rules ()
    ((_ var expr) (begin
   (define modul (current-module))
   (define exist-var  (module-variable modul (quote var)))
   (if exist-var
(module-set! modul (quote var) expr)
(module-define! modul (quote var) expr))))))

sound good:
scheme@(guile-user)> {xx <$ 47}
scheme@(guile-user)> xx
47
scheme@(guile-user)> {xx <$ 49}
scheme@(guile-user)> xx
49

until i test this:
scheme@(guile-user)> (if #t {xx <$ 50} 'never)
While compiling expression:
Syntax error:
unknown file:6:7: definition in expression context, where definitions
are not allowed, in form (define modul (current-module))


then i wrote this macro:

(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))))))

and it seems good:
scheme@(guile-user)> {yy <§ 49}
scheme@(guile-user)> {yy <§ 50}
scheme@(guile-user)> (if #t {yy <§ 51} 'never)
scheme@(guile-user)> yy
51

i will test it in multiple context and programs

for this example i directly put the macro operator <§ in the main
file,so it was easiest.

I later integrate it in a module and it works too.


.....

i paused writing the mail to think and realise that what i wanted to
do was not clear,

Python and Scheme have to different 'scoping' for variables

those programs behave different:


def foo():
    x=1
    if True:
        x=2
        print(x)
    print(x)


>>> foo()
2
2

and this one:

(define (foo)
  (define x 1)
  (if #t
      (let ()
	(define x 2)
	(display x)
	(newline))
      'never)
  (display x)
  (newline))

(foo)
2
1

it is not like this ones which works like Python's foo version:

;; scheme@(guile-user)> (bar)
;; 2
;; 2
(define (bar)
  (define x 1)
  (if #t
      (let ()
	(set! x 2)
	(display x)
	(newline))
      'never)
  (display x)
  (newline))

and it will not be a good idea for an extended Scheme to behave as
Python, i must allow the two behaviors

and find a way they do not conflict each other using a special syntax.

basically what i need to define is two operators <- and <+ ( + for
adding a variable in environment)

that can act as in the comments below:

;; scheme@(guile-user)> (foo)
;; 2
;; 1
(define (foo)
  (define x 1) ;; x <- 1
  (if #t
      (let ()
	(define x 2) ;; x <+ 2
	(display x)
	(newline))
      'never)
  (display x)
  (newline))

;; scheme@(guile-user)> (bar)
;; 2
;; 2
(define (bar)
  (define x 1) ;; x <- 1
  (if #t
      (let ()
	(set! x 2) ;; x <- 2
	(display x)
	(newline))
      'never)
  (display x)
  (newline))


<+ can be defined as <§ above.

problem is the code of  <§ is not portable ,it is specific to guile.

The solution of Maxime Devos, should works too but is not portable,
because all scheme does not allow this.The two solutions does not use
R6RS .

Every Scheme implementation of my code will be specific for this operator.

I will test the Maxime's solution too. But i realize now is solution
is good but my goal has changed  now!

i need to act still more like Scheme than Python, be able to create
local variables.


Matt Wett suggest to use define-once (also not existing in other
Scheme implementations)

it is  a good solution to write the <- operator using it and set!.


To be tested with define-once and set! if define-once is allowed in
the context the macro is written.

Possible problem of this new operator <§,it creates only  global
(top-level?) variables,not lexically scoped:
scheme@(guile-user)> (if #t (begin {t <§ 57} (+ t 1) ) 'never)
;;; <stdin>:58:27: warning: possibly unbound variable `t'
$7 = 58

worked!


scheme@(guile-user)> t
$8 = 57

but now the nested variable in conditional branch is global (can be
seen at top-level)

i'm still making test...



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
>

[-- Attachment #2: Type: text/html, Size: 13735 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-19 21:38 ` Taylan Kammer
  2021-09-21 12:26   ` Damien Mattei
@ 2021-09-22  8:44   ` Damien Mattei
  2021-09-22  9:06     ` William ML Leslie
  1 sibling, 1 reply; 19+ messages in thread
From: Damien Mattei @ 2021-09-22  8:44 UTC (permalink / raw)
  To: Taylan Kammer; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 8773 bytes --]

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
>

[-- Attachment #2: Type: text/html, Size: 22383 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-22  8:44   ` Damien Mattei
@ 2021-09-22  9:06     ` William ML Leslie
  2021-09-22  9:53       ` Damien Mattei
  0 siblings, 1 reply; 19+ messages in thread
From: William ML Leslie @ 2021-09-22  9:06 UTC (permalink / raw)
  To: Damien Mattei; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 9380 bytes --]

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
>>
>

[-- Attachment #2: Type: text/html, Size: 22984 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-22  9:06     ` William ML Leslie
@ 2021-09-22  9:53       ` Damien Mattei
  2021-09-22 18:51         ` Taylan Kammer
  0 siblings, 1 reply; 19+ messages in thread
From: Damien Mattei @ 2021-09-22  9:53 UTC (permalink / raw)
  To: William ML Leslie; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 10294 bytes --]

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
>>>
>>

[-- Attachment #2: Type: text/html, Size: 24082 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-22  9:53       ` Damien Mattei
@ 2021-09-22 18:51         ` Taylan Kammer
  2021-09-22 21:52           ` William ML Leslie
  2021-09-23 17:27           ` Damien Mattei
  0 siblings, 2 replies; 19+ messages in thread
From: Taylan Kammer @ 2021-09-22 18:51 UTC (permalink / raw)
  To: Damien Mattei, William ML Leslie; +Cc: Jean-Paul Roy, guile-devel

On 22.09.2021 11:53, Damien Mattei wrote:
> 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.

I don't think there's any other way to achieve what you want, especially
using portable Scheme code.  The lexical scoping semantics of Scheme are
a very fundamental part of the language, and cannot be worked around in
portable Scheme code without using a macro that rewrites whole bodies of
lambda expressions.

Even using implementation-specific hacks, you won't get very far.  Any
compiled Scheme implementation, and even most interpreted ones, won't
allow you to modify an outer scope's set of variable definitions from
within an inner scope.

So if you really want to have Python's scoping semantics in Scheme, you
will probably have to write a complex 'def' macro that walks through the
body and "hoists" variable definitions to the outermost scope.

If you're targeting R6RS implementations, you can use syntax-case to
write such a macro, but it won't be easy.

If you're targeting R5RS or R7RS-small implementations, you will have to
rely on syntax-rules, which will probably be extremely difficult for this
kind of complex macro.

Personally I don't even know how I would approach the problem using the
more capable syntax-case, let alone pure syntax-rules.

-- 
Taylan



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-22 18:51         ` Taylan Kammer
@ 2021-09-22 21:52           ` William ML Leslie
  2021-09-23  8:40             ` Damien Mattei
  2021-09-23 19:03             ` Taylan Kammer
  2021-09-23 17:27           ` Damien Mattei
  1 sibling, 2 replies; 19+ messages in thread
From: William ML Leslie @ 2021-09-22 21:52 UTC (permalink / raw)
  To: Taylan Kammer; +Cc: Damien Mattei, guile-devel

[-- Attachment #1: Type: text/plain, Size: 2014 bytes --]

On Thu, 23 Sep 2021, 4:51 am Taylan Kammer, <taylan.kammer@gmail.com> wrote:

> On 22.09.2021 11:53, Damien Mattei wrote:
> > 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.
>
> I don't think there's any other way to achieve what you want, especially
> using portable Scheme code.  The lexical scoping semantics of Scheme are
> a very fundamental part of the language, and cannot be worked around in
> portable Scheme code without using a macro that rewrites whole bodies of
> lambda expressions.
>
> Even using implementation-specific hacks, you won't get very far.  Any
> compiled Scheme implementation, and even most interpreted ones, won't
> allow you to modify an outer scope's set of variable definitions from
> within an inner scope.
>
> So if you really want to have Python's scoping semantics in Scheme, you
> will probably have to write a complex 'def' macro that walks through the
> body and "hoists" variable definitions to the outermost scope.
>

Python is lexically scoped, and the assignment here is supposed to be local.


> If you're targeting R6RS implementations, you can use syntax-case to
> write such a macro, but it won't be easy.
>
> If you're targeting R5RS or R7RS-small implementations, you will have to
> rely on syntax-rules, which will probably be extremely difficult for this
> kind of complex macro.
>
> Personally I don't even know how I would approach the problem using the
> more capable syntax-case, let alone pure syntax-rules.
>
> --
> Taylan
>

[-- Attachment #2: Type: text/html, Size: 2675 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-22 21:52           ` William ML Leslie
@ 2021-09-23  8:40             ` Damien Mattei
  2021-09-23 19:03             ` Taylan Kammer
  1 sibling, 0 replies; 19+ messages in thread
From: Damien Mattei @ 2021-09-23  8:40 UTC (permalink / raw)
  To: William ML Leslie; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 2435 bytes --]

interesting discussion about "scope",
note i'm not saying i want Scheme+ act as Python, i'm still thinking the
best solution...
to be sure about terminology i find this good article about scoping:
https://medium.com/altcampus/scope-local-global-and-lexical-e164f53450b3
Damien

On Wed, Sep 22, 2021 at 11:52 PM William ML Leslie <
william.leslie.ttg@gmail.com> wrote:

> On Thu, 23 Sep 2021, 4:51 am Taylan Kammer, <taylan.kammer@gmail.com>
> wrote:
>
>> On 22.09.2021 11:53, Damien Mattei wrote:
>> > 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.
>>
>> I don't think there's any other way to achieve what you want, especially
>> using portable Scheme code.  The lexical scoping semantics of Scheme are
>> a very fundamental part of the language, and cannot be worked around in
>> portable Scheme code without using a macro that rewrites whole bodies of
>> lambda expressions.
>>
>> Even using implementation-specific hacks, you won't get very far.  Any
>> compiled Scheme implementation, and even most interpreted ones, won't
>> allow you to modify an outer scope's set of variable definitions from
>> within an inner scope.
>>
>> So if you really want to have Python's scoping semantics in Scheme, you
>> will probably have to write a complex 'def' macro that walks through the
>> body and "hoists" variable definitions to the outermost scope.
>>
>
> Python is lexically scoped, and the assignment here is supposed to be
> local.
>
>
>> If you're targeting R6RS implementations, you can use syntax-case to
>> write such a macro, but it won't be easy.
>>
>> If you're targeting R5RS or R7RS-small implementations, you will have to
>> rely on syntax-rules, which will probably be extremely difficult for this
>> kind of complex macro.
>>
>> Personally I don't even know how I would approach the problem using the
>> more capable syntax-case, let alone pure syntax-rules.
>>
>> --
>> Taylan
>>
>

[-- Attachment #2: Type: text/html, Size: 3780 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-22 18:51         ` Taylan Kammer
  2021-09-22 21:52           ` William ML Leslie
@ 2021-09-23 17:27           ` Damien Mattei
  2021-09-23 18:00             ` Maxime Devos
  2021-09-23 20:27             ` Taylan Kammer
  1 sibling, 2 replies; 19+ messages in thread
From: Damien Mattei @ 2021-09-23 17:27 UTC (permalink / raw)
  To: Taylan Kammer; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 5817 bytes --]

yes i know parsing the whole code is the only portable solution, but it is
slow,even on a few dozen of lines the slowing is visible ,so i can even
think of that on one thousand lines...

I finally succeed in Guile with simple piece of code to make my example run
with a single assignment operator <-  , here i define for variable the
assignment operator <$ , <- is working with arrays too:

*Preview:*

(define-syntax <$

  (lambda (s)

    (syntax-case s ()

      ((_ var value)

       (case (syntax-local-binding #'var)
	
         ((lexical) #'(begin
			(display "<$ : lexical scope : ")
			(display (quote var))
			(newline)
			(set! var value)))
	
	 ((displaced-lexical) #'(begin
				  (display "<$ : displaced-lexical scope : ")
				  (display (quote var))
				  (newline)
				  (set! var value)))
	
         ((global) #'(begin
		       (display "<$ : global scope : ")
		       (display (quote var))
		       (newline)
		       (define var value)))
	
         (else #'(begin
		   (display "<$ : unknow variable scope :")
		   (display (quote var))
		   (error "<$ : unknow variable scope : "))))))))



it allows this Scheme+ code to run with a single assignment operator (note
in some case the operator is also a definition of variable,but it is
invisible for the programmer, it has the duality of define and set!):

*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


some people were sceptic about the possibility to make it, but it works, i
do not say it is portable code.

When i run the program with debug i see that:
scheme@(guile-user)> (subset-sum-guile  L-init t-init)
<$ : global scope : ls
<$ : global scope : dyn

<$ : global scope : c
<$ : global scope : R
<$ : global scope : s
<$ : global scope : ls
<$ : global scope : dyn

<$ : global scope : c
.... hundreds of lines.....
#t

all variable are global,but they are just global to the body of the
function,not at toplevel,so there is no risk of breaking the code logic it
is just that if we want to see lexical scope we need a more nested
example,it is strange because i thought that the condx macro creates
nestled code for each conditional clauses...

to see the lexical scope we can use this example:
scheme@(guile-user)>
(condx [exec {k <- 1}]
    [{k = 1} {k <- {k + 1}} {k + 1}]
    [else 'never])
<$ : global scope : k
<$ : lexical scope : k
$3 = 3
here the lexical scope is well visible :-)
but if k had existed at toplevel it is not modified :-( :
scheme@(guile-user)> (define k 0)
scheme@(guile-user)>
(condx [exec {k <- 1}]
           [{k = 1} {k <- {k + 1}} {k + 1}]
           [else 'never])
<$ : global scope : k
<$ : lexical scope : k
$4 = 3
scheme@(guile-user)> k
$5 = 0

:-(
 probably beause *syntax-local-binding* only works in the current lexical
environment ?
https://www.gnu.org/software/guile/docs/master/guile.html/Syntax-Transformer-Helpers.html
but not at toplevel ???
Scheme Procedure: *syntax-local-binding* *id
[#:resolve-syntax-parameters?=#t]*

Resolve the identifer id, a syntax object, within the current lexical
environment
for this reason i still searching a solution that would be a mix of
*syntax-local-binding* and Module System Reflection .

Damien


On Wed, Sep 22, 2021 at 8:51 PM Taylan Kammer <taylan.kammer@gmail.com>
wrote:

> On 22.09.2021 11:53, Damien Mattei wrote:
> > 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.
>
> I don't think there's any other way to achieve what you want, especially
> using portable Scheme code.  The lexical scoping semantics of Scheme are
> a very fundamental part of the language, and cannot be worked around in
> portable Scheme code without using a macro that rewrites whole bodies of
> lambda expressions.
>
> Even using implementation-specific hacks, you won't get very far.  Any
> compiled Scheme implementation, and even most interpreted ones, won't
> allow you to modify an outer scope's set of variable definitions from
> within an inner scope.
>
> So if you really want to have Python's scoping semantics in Scheme, you
> will probably have to write a complex 'def' macro that walks through the
> body and "hoists" variable definitions to the outermost scope.
>
> If you're targeting R6RS implementations, you can use syntax-case to
> write such a macro, but it won't be easy.
>
> If you're targeting R5RS or R7RS-small implementations, you will have to
> rely on syntax-rules, which will probably be extremely difficult for this
> kind of complex macro.
>
> Personally I don't even know how I would approach the problem using the
> more capable syntax-case, let alone pure syntax-rules.
>
> --
> Taylan
>

[-- Attachment #2: Type: text/html, Size: 19186 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-23 17:27           ` Damien Mattei
@ 2021-09-23 18:00             ` Maxime Devos
  2021-09-23 20:27             ` Taylan Kammer
  1 sibling, 0 replies; 19+ messages in thread
From: Maxime Devos @ 2021-09-23 18:00 UTC (permalink / raw)
  To: Damien Mattei, Taylan Kammer; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 5688 bytes --]

Damien Mattei schreef op do 23-09-2021 om 19:27 [+0200]:
> yes i know parsing the whole code is the only portable solution, but it is slow,even on a few dozen of lines the slowing is visible ,so i can even think of that on one thousand lines...
> 
> I finally succeed in Guile with simple piece of code to make my example run with a single assignment operator <-  , here i define for variable the assignment operator <$ , <- is working with arrays too:
> 
> Preview:
> 
> (define-syntax <$
>   
>   (lambda (s)
>     
>     (syntax-case s ()
>       
>       ((_ var value)
>        
>        (case (syntax-local-binding #'var)
> 	 
>          ((lexical) #'(begin
> 			(display "<$ : lexical scope : ")
> 			(display (quote var))
> 			(newline)
> 			(set! var value)))
> 	 
> 	 ((displaced-lexical) #'(begin
> 				  (display "<$ : displaced-lexical scope : ")
> 				  (display (quote var))
> 				  (newline)
> 				  (set! var value)))
> 	 
>          ((global) #'(begin
> 		       (display "<$ : global scope : ")
> 		       (display (quote var))
> 		       (newline)
> 		       (define var value)))
> 	 
>          (else #'(begin
> 		   (display "<$ : unknow variable scope :")
> 		   (display (quote var))
> 		   (error "<$ : unknow variable scope : "))))))))
> 
> 
> it allows this Scheme+ code to run with a single assignment operator (note in some case the operator is also a definition of variable,but it is invisible for the programmer, it has the duality of define and set!):
> 
> 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
> 
>      
> 
> some people were sceptic about the possibility to make it, but it works, i do not say it is portable code.
> 
> When i run the program with debug i see that:
> scheme@(guile-user)> (subset-sum-guile  L-init t-init)
> <$ : global scope : ls
> <$ : global scope : dyn
>  
> <$ : global scope : c
> <$ : global scope : R
> <$ : global scope : s
> <$ : global scope : ls
> <$ : global scope : dyn
>  
> <$ : global scope : c
> .... hundreds of lines.....
> #t
> 
> all variable are global,

No, they are local, even though syntax-local-binding returns 'global'.
'syntax-local-binding' doesn't know we will be defining a local variable
with the same name later, so it says 'global' instead of 'lexical' or
'displaced-lexical'.

There is no such thing as ‘global to the body of the function’, what you are
descrbing is local variables.

The macro <$ you have defined won't work for the "hello world" example I sent
you:

(define (#{hello/won't-work}# language)
  (cond ((equal? language "dutch")
         (<$ message "Hallo wereld"))
        ((equal? language "english")
         (<$ message "Hello world")))
  (display message)
  (newline))
While compiling expression:
Syntax error:
unknown file:70:9: definition in expression context, where definitions are not allowed, in form (define message "Hallo wereld")

The following does, however:

(define (hello language)
  (<$ message #f)
  (cond ((equal? language "dutch")
         (<$ message "Hallo wereld"))
        ((equal? language "english")
         (<$ message "Hello world")))
  (display message)
  (newline))

Possibly this limitation of <$ is acceptable to you though.

> but they are just global to the body of the function,not at toplevel,so there is no risk of breaking the code logic it is just that if we want to see lexical scope we need a more nested example,it is strange because i thought that the condx macro creates nestled code for each conditional clauses...
> 
> to see the lexical scope we can use this example:
> scheme@(guile-user)> 
> (condx [exec {k <- 1}]
>     [{k = 1} {k <- {k + 1}} {k + 1}]
>     [else 'never])
> <$ : global scope : k
> <$ : lexical scope : k
> $3 = 3
> here the lexical scope is well visible :-)
> but if k had existed at toplevel it is not modified :-( :
> scheme@(guile-user)> (define k 0)
> scheme@(guile-user)> 
> (condx [exec {k <- 1}]
>            [{k = 1} {k <- {k + 1}} {k + 1}]
>            [else 'never])
> <$ : global scope : k
> <$ : lexical scope : k
> $4 = 3
> scheme@(guile-user)> k
> $5 = 0
> 
> :-(
>  probably beause syntax-local-binding only works in the current lexical environment ?
> https://www.gnu.org/software/guile/docs/master/guile.html/Syntax-Transformer-Helpers.html
> but not at toplevel ???
> Scheme Procedure: syntax-local-binding id [#:resolve-syntax-parameters?=#t]
> Resolve the identifer id, a syntax object, within the current lexical environment
> 
> for this reason i still searching a solution that would be a mix of syntax-local-binding and Module System Reflection .

Use the second return value of syntax-local-binding.
Or just use set! instead of <$ and <- to modify global variables,
and use <- and <$ for local variables only.

Greetings,
Maxime.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-22 21:52           ` William ML Leslie
  2021-09-23  8:40             ` Damien Mattei
@ 2021-09-23 19:03             ` Taylan Kammer
  1 sibling, 0 replies; 19+ messages in thread
From: Taylan Kammer @ 2021-09-23 19:03 UTC (permalink / raw)
  To: William ML Leslie; +Cc: Damien Mattei, guile-devel

On 22.09.2021 23:52, William ML Leslie wrote:
> On Thu, 23 Sep 2021, 4:51 am Taylan Kammer, <taylan.kammer@gmail.com <mailto:taylan.kammer@gmail.com>> wrote:
> 
>     On 22.09.2021 11:53, Damien Mattei wrote:
>     > 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.
> 
>     I don't think there's any other way to achieve what you want, especially
>     using portable Scheme code.  The lexical scoping semantics of Scheme are
>     a very fundamental part of the language, and cannot be worked around in
>     portable Scheme code without using a macro that rewrites whole bodies of
>     lambda expressions.
> 
>     Even using implementation-specific hacks, you won't get very far.  Any
>     compiled Scheme implementation, and even most interpreted ones, won't
>     allow you to modify an outer scope's set of variable definitions from
>     within an inner scope.
> 
>     So if you really want to have Python's scoping semantics in Scheme, you
>     will probably have to write a complex 'def' macro that walks through the
>     body and "hoists" variable definitions to the outermost scope.
> 
> 
> Python is lexically scoped, and the assignment here is supposed to be local.

Well, yes and no.  It implements variable hoisting, meaning all previously
unset variables that are set within a function are implicitly declared at the
beginning of the function.  It doesn't have sub-scopes in function bodies.

-- 
Taylan



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-23 17:27           ` Damien Mattei
  2021-09-23 18:00             ` Maxime Devos
@ 2021-09-23 20:27             ` Taylan Kammer
  2021-09-23 20:42               ` Damien Mattei
  2021-09-23 20:48               ` Taylan Kammer
  1 sibling, 2 replies; 19+ messages in thread
From: Taylan Kammer @ 2021-09-23 20:27 UTC (permalink / raw)
  To: Damien Mattei; +Cc: Jean-Paul Roy, guile-devel

On 23.09.2021 19:27, Damien Mattei wrote:
> yes i know parsing the whole code is the only portable solution, but it is slow,even on a few dozen of lines the slowing is visible ,so i can even think of that on one thousand lines...
> 
> I finally succeed in Guile with simple piece of code to make my example run with a single assignment operator <-  , here i define for variable the assignment operator <$ , <- is working with arrays too:
> 
> *Preview:*
> 
> (define-syntax <$
>   
>   (lambda (s)
>     
>     (syntax-case s ()
>       
>       ((_ var value)
>        
>        (case (syntax-local-binding #'var)
> 	 
>          ((lexical) #'(begin
> 			(display "<$ : lexical scope : ")
> 			(display (quote var))
> 			(newline)
> 			(set! var value)))
> 	 
> 	 ((displaced-lexical) #'(begin
> 				  (display "<$ : displaced-lexical scope : ")
> 				  (display (quote var))
> 				  (newline)
> 				  (set! var value)))
> 	 
>          ((global) #'(begin
> 		       (display "<$ : global scope : ")
> 		       (display (quote var))
> 		       (newline)
> 		       (define var value)))
> 	 
>          (else #'(begin
> 		   (display "<$ : unknow variable scope :")
> 		   (display (quote var))
> 		   (error "<$ : unknow variable scope : "))))))))
> 

I can't seem to find syntax-local-binding in Guile 2.2 or 3.0.  Did you
have to import some special module, or are you using another version?

Either way, I suspect that the following will not work with your macro:

  (let ()
    (let ()
      (<$ x 1))
    (display x)
    (newline))

If I understand correctly, it will expand to:

  (let ()
    (let ()
      (define x 1))
    (display x)
    (newline))

And that won't work because 'x' is only defined in the inner 'let'.

This is where we see the crucial difference between Scheme and Python:
in Python there is nothing similar to an inner 'let'.  There is only
one function-level scope.  In Scheme, there can be as many nested
scopes as you want, and an inner scope can't affect an outer one.

-- 
Taylan



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-23 20:27             ` Taylan Kammer
@ 2021-09-23 20:42               ` Damien Mattei
  2021-09-23 20:48               ` Taylan Kammer
  1 sibling, 0 replies; 19+ messages in thread
From: Damien Mattei @ 2021-09-23 20:42 UTC (permalink / raw)
  To: Taylan Kammer; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 3307 bytes --]

yes it can reuse an upper and precedent definition but a nested definition
can not be used later at an upper level.

anyway it would not be portable , for all those reason i will use to
separate operator ,basically <- for set! and <+ for define ,so i can even
modify toplevel bindings , i did not want to have all the python behavior
which is not safe and did not allow local nested variables.

even using an exception will not solve the problem:
scheme@(guile-user)> (call-with-current-continuation
   (lambda (exit)
     (with-exception-handler
      (lambda (e)
        (exit "undefined ,you need to define somewhere")) (lambda () (set!
notdefined 7)))))
;;; <stdin>:97:69: warning: possibly unbound variable `notdefined'
$28 = "undefined ,you need to define somewhere"

??? i do not see any solution with a macro with exception

Damien


On Thu, Sep 23, 2021 at 10:27 PM Taylan Kammer <taylan.kammer@gmail.com>
wrote:

> On 23.09.2021 19:27, Damien Mattei wrote:
> > yes i know parsing the whole code is the only portable solution, but it
> is slow,even on a few dozen of lines the slowing is visible ,so i can even
> think of that on one thousand lines...
> >
> > I finally succeed in Guile with simple piece of code to make my example
> run with a single assignment operator <-  , here i define for variable the
> assignment operator <$ , <- is working with arrays too:
> >
> > *Preview:*
> >
> > (define-syntax <$
> >
> >   (lambda (s)
> >
> >     (syntax-case s ()
> >
> >       ((_ var value)
> >
> >        (case (syntax-local-binding #'var)
> >
> >          ((lexical) #'(begin
> >                       (display "<$ : lexical scope : ")
> >                       (display (quote var))
> >                       (newline)
> >                       (set! var value)))
> >
> >        ((displaced-lexical) #'(begin
> >                                 (display "<$ : displaced-lexical scope :
> ")
> >                                 (display (quote var))
> >                                 (newline)
> >                                 (set! var value)))
> >
> >          ((global) #'(begin
> >                      (display "<$ : global scope : ")
> >                      (display (quote var))
> >                      (newline)
> >                      (define var value)))
> >
> >          (else #'(begin
> >                  (display "<$ : unknow variable scope :")
> >                  (display (quote var))
> >                  (error "<$ : unknow variable scope : "))))))))
> >
>
> I can't seem to find syntax-local-binding in Guile 2.2 or 3.0.  Did you
> have to import some special module, or are you using another version?
>
> Either way, I suspect that the following will not work with your macro:
>
>   (let ()
>     (let ()
>       (<$ x 1))
>     (display x)
>     (newline))
>
> If I understand correctly, it will expand to:
>
>   (let ()
>     (let ()
>       (define x 1))
>     (display x)
>     (newline))
>
> And that won't work because 'x' is only defined in the inner 'let'.
>
> This is where we see the crucial difference between Scheme and Python:
> in Python there is nothing similar to an inner 'let'.  There is only
> one function-level scope.  In Scheme, there can be as many nested
> scopes as you want, and an inner scope can't affect an outer one.
>
> --
> Taylan
>

[-- Attachment #2: Type: text/html, Size: 5027 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-23 20:27             ` Taylan Kammer
  2021-09-23 20:42               ` Damien Mattei
@ 2021-09-23 20:48               ` Taylan Kammer
  2021-09-23 21:53                 ` Damien Mattei
  1 sibling, 1 reply; 19+ messages in thread
From: Taylan Kammer @ 2021-09-23 20:48 UTC (permalink / raw)
  To: Damien Mattei; +Cc: Jean-Paul Roy, guile-devel

Responding to myself:

On 23.09.2021 22:27, Taylan Kammer wrote:

> I can't seem to find syntax-local-binding in Guile 2.2 or 3.0.  Did you
> have to import some special module, or are you using another version?

Worked when I imported (system syntax internal).

> Either way, I suspect that the following will not work with your macro:
> 
>   (let ()
>     (let ()
>       (<$ x 1))
>     (display x)
>     (newline))

Indeed it doesn't work, though for a different reason:

  While compiling expression:
  Syntax error:
  unknown file:43:8: body should end with an expression in form (let () (<$ x 1))

That's because indeed the inner let expands into:

  (let ()
    (define x 1))

And there has to be at least one expression after the define.  So I tried:

  (let ()
    (let ()
      (<$ x 1)
      (newline))
    (display x)
    (newline))

And as I expected, it says 'x' is unbound:

  ;;; <stdin>:44:45: warning: possibly unbound variable `x'
  <$ : global scope : x
  
  ice-9/boot-9.scm:1685:16: In procedure raise-exception:
  Unbound variable: x

The only way it will work is if you never use nested scopes, but that will
lead to very strange Scheme code, and there will probably be many cases
where you accidentally use a nested scope without immediately noticing it.

Note also that definitions aren't allowed everywhere.  Consider this:

  (let ()
    (if 'whatever
        (<$ x 1)
        (<$ x 2))
    (display x)
    (newline))

It leads to:

  While compiling expression:
  Syntax error:
  unknown file:49:17: definition in expression context, where definitions are not allowed, in form (define x 1)

Because the arms of 'if' aren't allowed to be definitions.

-- 
Taylan



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-23 20:48               ` Taylan Kammer
@ 2021-09-23 21:53                 ` Damien Mattei
  2021-09-24  4:41                   ` Damien Mattei
  0 siblings, 1 reply; 19+ messages in thread
From: Damien Mattei @ 2021-09-23 21:53 UTC (permalink / raw)
  To: Taylan Kammer; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 2285 bytes --]

yes i'm using GNU Guile 3.0.7,
https://www.gnu.org/software/guile/docs/master/guile.html/Syntax-Transformer-Helpers.html

i have tested a lot , even define-once again and i choose to use to
assignment operators and portable code because the non-portable function do
not bring more, finally it was not a bad idea to ask for a new function
because we can do it with the actual toolbox...
Damien

On Thu, Sep 23, 2021 at 10:48 PM Taylan Kammer <taylan.kammer@gmail.com>
wrote:

> Responding to myself:
>
> On 23.09.2021 22:27, Taylan Kammer wrote:
>
> > I can't seem to find syntax-local-binding in Guile 2.2 or 3.0.  Did you
> > have to import some special module, or are you using another version?
>
> Worked when I imported (system syntax internal).
>
> > Either way, I suspect that the following will not work with your macro:
> >
> >   (let ()
> >     (let ()
> >       (<$ x 1))
> >     (display x)
> >     (newline))
>
> Indeed it doesn't work, though for a different reason:
>
>   While compiling expression:
>   Syntax error:
>   unknown file:43:8: body should end with an expression in form (let ()
> (<$ x 1))
>
> That's because indeed the inner let expands into:
>
>   (let ()
>     (define x 1))
>
> And there has to be at least one expression after the define.  So I tried:
>
>   (let ()
>     (let ()
>       (<$ x 1)
>       (newline))
>     (display x)
>     (newline))
>
> And as I expected, it says 'x' is unbound:
>
>   ;;; <stdin>:44:45: warning: possibly unbound variable `x'
>   <$ : global scope : x
>
>   ice-9/boot-9.scm:1685:16: In procedure raise-exception:
>   Unbound variable: x
>
> The only way it will work is if you never use nested scopes, but that will
> lead to very strange Scheme code, and there will probably be many cases
> where you accidentally use a nested scope without immediately noticing it.
>
> Note also that definitions aren't allowed everywhere.  Consider this:
>
>   (let ()
>     (if 'whatever
>         (<$ x 1)
>         (<$ x 2))
>     (display x)
>     (newline))
>
> It leads to:
>
>   While compiling expression:
>   Syntax error:
>   unknown file:49:17: definition in expression context, where definitions
> are not allowed, in form (define x 1)
>
> Because the arms of 'if' aren't allowed to be definitions.
>
> --
> Taylan
>

[-- Attachment #2: Type: text/html, Size: 3283 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: new function
  2021-09-23 21:53                 ` Damien Mattei
@ 2021-09-24  4:41                   ` Damien Mattei
  0 siblings, 0 replies; 19+ messages in thread
From: Damien Mattei @ 2021-09-24  4:41 UTC (permalink / raw)
  To: Taylan Kammer, Matt Wette, Maxime Devos; +Cc: Jean-Paul Roy, guile-devel

[-- Attachment #1: Type: text/plain, Size: 5996 bytes --]

so i drop off the idea of a single assignment operator, there will be 2 ,<-
for single assignment when the variable has been previously defined (at
upper level), and another <+ that add a variable in the environment using
define.
Other possibility is to have a single assignment operator <- and to declare
the variables not previously defined at upper level.
All this was already done in Scheme+ :

here is what looks like
 the module definition :
(define-module (Scheme+Guile)

  #:export (def $bracket-apply$ <- -> <+ declare $ condx <> )

  )

(include "def.scm")
(include "Scheme+Guile/array-square-brackets.scm")
(include "Scheme+Guile/assignment.scm")
(include "declare.scm")
(include "condx.scm")
(include "block.scm")
(include "not-equal.scm")

and so, the code for the 2 assignment operator :

*Preview:*

(define (subset-sum-guile L t)

  {ls <+ (length L)}
  {dyn <+ dyna[ls t]}

  {cpt <- {cpt + 1}} ;; cpt has been already defined at toplevel

  ;; 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


and the code which use a single operator and a *declare* (it is a define
unspecified):

*Preview:*

(define (subset-sum-guile-dec L t)

  (declare ls dyn c R s)

  {ls <- (length L)}
  {dyn <- dyna[ls t]}

  {cpt <- {cpt + 1}} ;; cpt has been already defined at toplevel

  ;; 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-dec 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-dec R {t - c}) or (subset-sum-guile-dec R t)}}
	       {dyna[ls t] <- (one-two s)}
	       s])) ;; return boolean value


the two syntax can be mixed but i do not think it is a good idea to have 2
coding style in the same project, also the position of 'declare' or '<+' is
depending of the possibility of the used Scheme implementation to have
define placed everywhere more or less, in the worse case the 'declare' or
'<+' have to placed at top of the body of the procedure.
The way python declare them, note that i have no regret to not be able to
define variables nested in a branch of code the way python do it that can
be seen from the whole procedure.I do not think it is a good idea and
useful. But i hoped to be able to avoid a 'declare' at the top or somewhere
but declaration even in Scheme could be necessary with some typed Scheme or
when using object oriented features of some Scheme perheaps that used typed
variables (for overloading function? not sure it exist in Scheme also ,even
in OOP).So this is not a great problem.

Damien


On Thu, Sep 23, 2021 at 11:53 PM Damien Mattei <damien.mattei@gmail.com>
wrote:

> yes i'm using GNU Guile 3.0.7,
> https://www.gnu.org/software/guile/docs/master/guile.html/Syntax-Transformer-Helpers.html
>
> i have tested a lot , even define-once again and i choose to use to
> assignment operators and portable code because the non-portable function do
> not bring more, finally it was not a bad idea to ask for a new function
> because we can do it with the actual toolbox...
> Damien
>
> On Thu, Sep 23, 2021 at 10:48 PM Taylan Kammer <taylan.kammer@gmail.com>
> wrote:
>
>> Responding to myself:
>>
>> On 23.09.2021 22:27, Taylan Kammer wrote:
>>
>> > I can't seem to find syntax-local-binding in Guile 2.2 or 3.0.  Did you
>> > have to import some special module, or are you using another version?
>>
>> Worked when I imported (system syntax internal).
>>
>> > Either way, I suspect that the following will not work with your macro:
>> >
>> >   (let ()
>> >     (let ()
>> >       (<$ x 1))
>> >     (display x)
>> >     (newline))
>>
>> Indeed it doesn't work, though for a different reason:
>>
>>   While compiling expression:
>>   Syntax error:
>>   unknown file:43:8: body should end with an expression in form (let ()
>> (<$ x 1))
>>
>> That's because indeed the inner let expands into:
>>
>>   (let ()
>>     (define x 1))
>>
>> And there has to be at least one expression after the define.  So I tried:
>>
>>   (let ()
>>     (let ()
>>       (<$ x 1)
>>       (newline))
>>     (display x)
>>     (newline))
>>
>> And as I expected, it says 'x' is unbound:
>>
>>   ;;; <stdin>:44:45: warning: possibly unbound variable `x'
>>   <$ : global scope : x
>>
>>   ice-9/boot-9.scm:1685:16: In procedure raise-exception:
>>   Unbound variable: x
>>
>> The only way it will work is if you never use nested scopes, but that will
>> lead to very strange Scheme code, and there will probably be many cases
>> where you accidentally use a nested scope without immediately noticing it.
>>
>> Note also that definitions aren't allowed everywhere.  Consider this:
>>
>>   (let ()
>>     (if 'whatever
>>         (<$ x 1)
>>         (<$ x 2))
>>     (display x)
>>     (newline))
>>
>> It leads to:
>>
>>   While compiling expression:
>>   Syntax error:
>>   unknown file:49:17: definition in expression context, where definitions
>> are not allowed, in form (define x 1)
>>
>> Because the arms of 'if' aren't allowed to be definitions.
>>
>> --
>> Taylan
>>
>

[-- Attachment #2: Type: text/html, Size: 24740 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2021-09-24  4:41 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-19  7:54 new function Damien Mattei
2021-09-19 14:41 ` Matt Wette
2021-09-19 14:43   ` Matt Wette
2021-09-19 21:38 ` Taylan Kammer
2021-09-21 12:26   ` Damien Mattei
2021-09-22  8:44   ` Damien Mattei
2021-09-22  9:06     ` William ML Leslie
2021-09-22  9:53       ` Damien Mattei
2021-09-22 18:51         ` Taylan Kammer
2021-09-22 21:52           ` William ML Leslie
2021-09-23  8:40             ` Damien Mattei
2021-09-23 19:03             ` Taylan Kammer
2021-09-23 17:27           ` Damien Mattei
2021-09-23 18:00             ` Maxime Devos
2021-09-23 20:27             ` Taylan Kammer
2021-09-23 20:42               ` Damien Mattei
2021-09-23 20:48               ` Taylan Kammer
2021-09-23 21:53                 ` Damien Mattei
2021-09-24  4:41                   ` Damien Mattei

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).