unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Damien Mattei <damien.mattei@gmail.com>
To: Taylan Kammer <taylan.kammer@gmail.com>
Cc: Jean-Paul Roy <jean-paul.roy@unice.fr>, guile-devel@gnu.org
Subject: Re: new function
Date: Tue, 21 Sep 2021 14:26:43 +0200	[thread overview]
Message-ID: <CADEOaddb4Eq7ABzQD1BmfvaXbg6nXgDx_rRyK12PqG-qV8QxdA@mail.gmail.com> (raw)
In-Reply-To: <147c2fb4-75d6-7cf6-4f4a-4edd996b0a4a@gmail.com>

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

  reply	other threads:[~2021-09-21 12:26 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CADEOaddb4Eq7ABzQD1BmfvaXbg6nXgDx_rRyK12PqG-qV8QxdA@mail.gmail.com \
    --to=damien.mattei@gmail.com \
    --cc=guile-devel@gnu.org \
    --cc=jean-paul.roy@unice.fr \
    --cc=taylan.kammer@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).