unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference)
@ 2024-09-19  2:36 Nala Ginrut
  2024-09-19  6:56 ` Dr. Arne Babenhauserheide
  0 siblings, 1 reply; 7+ messages in thread
From: Nala Ginrut @ 2024-09-19  2:36 UTC (permalink / raw)
  To: Guile User

I realized the #:declarative? can only be applied in the downstream modules
of the module holding global vars.
So the #:declarative? will affect the whole module and I have to put it
everywhere that references the global vas.

Maybe it'd be better if there's finer granularity control for each, like
define-non-dclarative or else.

BTW. In my case, I want to implement the global var mutation. For such a
case, if users don't want to put #:declarative? to affect the whole
downstream modules, maybe the best way is to implement getter and setter
inside the global var module.

Comments are welcome.
Thanks!
Best regards.


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

* Re: global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference)
  2024-09-19  2:36 global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference) Nala Ginrut
@ 2024-09-19  6:56 ` Dr. Arne Babenhauserheide
  2024-09-19 12:30   ` Nala Ginrut
  0 siblings, 1 reply; 7+ messages in thread
From: Dr. Arne Babenhauserheide @ 2024-09-19  6:56 UTC (permalink / raw)
  To: Nala Ginrut; +Cc: Guile User

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

Nala Ginrut <nalaginrut@gmail.com> writes:

> I realized the #:declarative? can only be applied in the downstream modules
> of the module holding global vars.

This easy to hit complexity was the topic of my thread
"Making code compatible with different versions of Guile — #:declarative?"

How declarative currently works is a very painful gotcha that affects
one of the most elegant way of building Guile applications:
getting a live REPL and improving your code iteratively.

Chickadee uses that beautifully:
https://files.dthompson.us/docs/chickadee/latest/Live-Coding.html

Here’s an example of that:
https://www.draketo.de/software/chickadee-wisp.webm
https://www.draketo.de/software/wisp#chickadee-2022-10-08

But once this gets a bit more complex, you must litter your modules with
#:declarative? #f
otherwise your changes in the REPL have no effect at all.

For example entering a module with ,m to fix a bug there won’t be seen
by the actual running code.

And this is a breaking change in behavior (it actually broke working
code for me).

So I think that the default for user-modules should be non-declarative.
To improve performance nontheless, we could manually mark all modules
shipped with Guile as #:declarative? #t but change the default to #f.

> So the #:declarative? will affect the whole module and I have to put it
> everywhere that references the global vas.
>
> Maybe it'd be better if there's finer granularity control for each, like
> define-non-dclarative or else.

In the thread I mentioned, Maxime wrote that

(define (foo ...) ...)
(set! foo foo)

should have the effect of making foo non-declarative. I did not test
that yet, though.

> BTW. In my case, I want to implement the global var mutation. For such a
> case, if users don't want to put #:declarative? to affect the whole
> downstream modules, maybe the best way is to implement getter and setter
> inside the global var module.

I think that when we have to implement getters and setters for this,
that’s an indication of a design problem.

Best wishes,
Arne
-- 
Unpolitisch sein
heißt politisch sein,
ohne es zu merken.
draketo.de

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 1125 bytes --]

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

* Re: global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference)
  2024-09-19  6:56 ` Dr. Arne Babenhauserheide
@ 2024-09-19 12:30   ` Nala Ginrut
  2024-09-19 15:33     ` Taylan Kammer
  0 siblings, 1 reply; 7+ messages in thread
From: Nala Ginrut @ 2024-09-19 12:30 UTC (permalink / raw)
  To: Dr. Arne Babenhauserheide; +Cc: Guile User

hi Arne!
Thanks for your reply!

>
>
> > BTW. In my case, I want to implement the global var mutation. For such a
> > case, if users don't want to put #:declarative? to affect the whole
> > downstream modules, maybe the best way is to implement getter and setter
> > inside the global var module.
>
> I think that when we have to implement getters and setters for this,
> that’s an indication of a design problem.
>

"design problem" is an easy word. ;-)

Although I mostly put global var like global parameters in such a module, I
think there's always something that needs a globally setter.
The parameter works when you could get the state first in the runtime,
then you can bind it with pameterize. But for the case that you have to
call another function first, then check the state change or not, the easier
way is to take advantage of side-effects.

Best regards.


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

* Re: global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference)
  2024-09-19 12:30   ` Nala Ginrut
@ 2024-09-19 15:33     ` Taylan Kammer
  2024-09-20  4:40       ` Linus Björnstam
  0 siblings, 1 reply; 7+ messages in thread
From: Taylan Kammer @ 2024-09-19 15:33 UTC (permalink / raw)
  To: guile-user

On 19.09.2024 14:30, Nala Ginrut wrote:
> Although I mostly put global var like global parameters in such a module, I
> think there's always something that needs a globally setter.
> The parameter works when you could get the state first in the runtime,
> then you can bind it with pameterize. But for the case that you have to
> call another function first, then check the state change or not, the easier
> way is to take advantage of side-effects.

Parameter objects can also be set permanently by calling them on a value:

scheme@(guile-user)> (define x (make-parameter 1))
scheme@(guile-user)> (x 2)
$1 = 1
scheme@(guile-user)> (x)
$2 = 2

(Note that, when calling it to change the value, it returns the previous value.)

I'm not sure if there's ever a really good reason to use mutable global variables instead of parameters.

Perhaps reading a variable is more efficient than reading a parameter's value. Usually, that's going to be an unnecessary micro-optimization. But even if such an optimization were needed, one could just bind the value of a parameter to a local variable where needed:

(let ((value (my-parameter)))
  (loop-a-million-times
    (lambda () (do-something-with value))))

If I'm not mistaken: Using a local variable is often more efficient than using a global variable, so if you needed to micro-optimize code for maximum efficiency, you would want to do this anyway.

There's one potential issue with using parameters like this: Their value is thread-local. If you change a parameter's value from one thread, with the setting syntax above (calling it on a value), it will never become visible to other threads that are currently executing. However, setting it before spawning a new thread will ensure that the new thread sees the new value:

scheme@(guile-user)> (x 3)
$5 = 2
scheme@(guile-user)> (join-thread (begin-thread (x)))
$6 = 3
scheme@(guile-user)> (join-thread (begin-thread (x 4) (x)))
$7 = 4
scheme@(guile-user)> (x)
$8 = 3

Hope that helps!

- Taylan


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

* Re: global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference)
  2024-09-19 15:33     ` Taylan Kammer
@ 2024-09-20  4:40       ` Linus Björnstam
  2024-09-22  2:34         ` Nala Ginrut
  0 siblings, 1 reply; 7+ messages in thread
From: Linus Björnstam @ 2024-09-20  4:40 UTC (permalink / raw)
  To: Taylan Kammer, guile-user


On Thu, 19 Sep 2024, at 17:33, Taylan Kammer wrote:
> On 
> If I'm not mistaken: Using a local variable is often more efficient 
> than using a global variable, so if you needed to micro-optimize code 
> for maximum efficiency, you would want to do this
> There's one potential issue with using parameters like this: Their 
> value is thread-local. If you change a parameter's value from one 
> thread, with the setting syntax above (calling it on a value), it will 
> never become visible to other threads that are currently executing. 

You could implement a macro with boxes and identifier macros that lets you define "non-declarative" variables that hides the box operations from the users.  That should be simple, but might make some issues downstream if they start doing macro voodoo.



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

* Re: global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference)
  2024-09-20  4:40       ` Linus Björnstam
@ 2024-09-22  2:34         ` Nala Ginrut
  2024-09-22 18:57           ` Linus Björnstam
  0 siblings, 1 reply; 7+ messages in thread
From: Nala Ginrut @ 2024-09-22  2:34 UTC (permalink / raw)
  To: Linus Björnstam; +Cc: Taylan Kammer, guile-user

@Linus!
I think it's similar to a getter/setter, but I think making it a function
will be safer.

@Tayland Thanks for the hint! I didn't know this trick of parameter!


On Fri, Sep 20, 2024 at 1:41 PM Linus Björnstam <linus.internet@fastmail.se>
wrote:

>
> On Thu, 19 Sep 2024, at 17:33, Taylan Kammer wrote:
> > On
> > If I'm not mistaken: Using a local variable is often more efficient
> > than using a global variable, so if you needed to micro-optimize code
> > for maximum efficiency, you would want to do this
> > There's one potential issue with using parameters like this: Their
> > value is thread-local. If you change a parameter's value from one
> > thread, with the setting syntax above (calling it on a value), it will
> > never become visible to other threads that are currently executing.
>
> You could implement a macro with boxes and identifier macros that lets you
> define "non-declarative" variables that hides the box operations from the
> users.  That should be simple, but might make some issues downstream if
> they start doing macro voodoo.
>
>


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

* Re: global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference)
  2024-09-22  2:34         ` Nala Ginrut
@ 2024-09-22 18:57           ` Linus Björnstam
  0 siblings, 0 replies; 7+ messages in thread
From: Linus Björnstam @ 2024-09-22 18:57 UTC (permalink / raw)
  To: Nala Ginrut, Linus Björnstam; +Cc: Taylan Kammer, guile-user


Den 2024-09-22 kl. 04:34, skrev Nala Ginrut:
> @Linus!
> I think it's similar to a getter/setter, but I think making it a 
> function will be safer.


I think a box is a good idea, since that is more or less what happens 
behind the scenes when you start mutating values outside contexts where 
automatic unboxing occurs. You will also not have to deal with the 
performance penalty of the dynamic environment, nor any unexpected 
thread things (apart from threads being able to mutate the value at the 
same time). It is what you would have gotten if guile had not introduced 
declarative modules.

Guile has both regular boxes (srfi 111?) and atomic boxes.

My suggestion about identifier macros means you can make the boxing 
primitives invisible to the user. Ie using (+ the-var 5) turns into (+ 
(unbox the-var) 5) and (set! the-var 12)=> (set-box! the-var 12). I have 
done some voodoo using make-variable-transformer, but I believe the 
shorthand _identifier-syntax_ could be what you are looking for.

Best regards
Linus




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

end of thread, other threads:[~2024-09-22 18:57 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-19  2:36 global vars and #:declarative? (was [critical bug] The set! doesn't work in indirect reference) Nala Ginrut
2024-09-19  6:56 ` Dr. Arne Babenhauserheide
2024-09-19 12:30   ` Nala Ginrut
2024-09-19 15:33     ` Taylan Kammer
2024-09-20  4:40       ` Linus Björnstam
2024-09-22  2:34         ` Nala Ginrut
2024-09-22 18:57           ` Linus Björnstam

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