* question about values @ 2020-03-17 23:50 Massimiliano Gubinelli 2020-03-18 6:12 ` Taylan Kammer 0 siblings, 1 reply; 11+ messages in thread From: Massimiliano Gubinelli @ 2020-03-17 23:50 UTC (permalink / raw) To: guile-user Hi all, I do not understand what happens here: mgubi@Ulrike guile3-usr % guile guile> (version) "1.8.8" guile> (call-with-values (lambda () (let ((a (values "a" "b" "c"))) a)) (lambda body body)) ("a" "b" "c") mgubi@Ulrike guile3-usr % bin/guile GNU Guile 3.0.1 Copyright (C) 1995-2020 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user)> (version) $1 = "3.0.1" scheme@(guile-user)> (call-with-values (lambda () (let ((a (values "a" "b" "c"))) a)) (lambda body body)) $2 = ("a") Why the two versions of Guile behave differently? Which is the "correct" behaviour, and in case: how to propagate multiple results safely? Thanks! Massimiliano ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-17 23:50 question about values Massimiliano Gubinelli @ 2020-03-18 6:12 ` Taylan Kammer 2020-03-18 9:55 ` Massimiliano Gubinelli 0 siblings, 1 reply; 11+ messages in thread From: Taylan Kammer @ 2020-03-18 6:12 UTC (permalink / raw) To: Massimiliano Gubinelli, guile-user On 18.03.2020 00:50, Massimiliano Gubinelli wrote: > (let ((a (values "a" "b" "c"))) a) The result of (values x y z) is not a kind of object that contains three values (like a list or vector). It's three separate values that would need to be put into three separate variables. But you're only naming one variable (a). So strictly speaking the code is "wrong". In Guile 1.8, multiple values were actually put into some special kind of object (which was not very efficient) so code like that still somehow worked even thought it's technically wrong. Starting from Guile 2.0, providing multiple values in a context where only one is expected causes the extra values to be ignored. Happy to answer further questions about this. Multiple-values can be a tricky concept to grasp because most other programming languages don't have it. - Taylan ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 6:12 ` Taylan Kammer @ 2020-03-18 9:55 ` Massimiliano Gubinelli 2020-03-18 11:06 ` Massimiliano Gubinelli 2020-03-18 12:39 ` Matt Wette 0 siblings, 2 replies; 11+ messages in thread From: Massimiliano Gubinelli @ 2020-03-18 9:55 UTC (permalink / raw) To: Taylan Kammer; +Cc: guile-user Thanks Taylan, > On 18. Mar 2020, at 07:12, Taylan Kammer <taylan.kammer@gmail.com> wrote: > > On 18.03.2020 00:50, Massimiliano Gubinelli wrote: >> (let ((a (values "a" "b" "c"))) a) > > The result of (values x y z) is not a kind of object that contains three values (like a list or vector). It's three separate values that would need to be put into three separate variables. But you're only naming one variable (a). So strictly speaking the code is "wrong". > > In Guile 1.8, multiple values were actually put into some special kind of object (which was not very efficient) so code like that still somehow worked even thought it's technically wrong. > > Starting from Guile 2.0, providing multiple values in a context where only one is expected causes the extra values to be ignored. > > I understand the point but then it comes to the problem how to handle this in macros. For example if bar is a proceduce which returns multiple values and I have a macro "my-macro" which wraps the call with some initialization and finalization code and I write (my-macro (bar)) how to write this macro without knowing if bar is returning multiple values or not? For example I would like the code above to expand into (begin (initialization-code) (let ((ret (bar))) (finalization-code) ret)) But this does not work as shown by the example above. How to implement this macro correctly? best Max > Happy to answer further questions about this. Multiple-values can be a tricky concept to grasp because most other programming languages don't have it. > > - Taylan ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 9:55 ` Massimiliano Gubinelli @ 2020-03-18 11:06 ` Massimiliano Gubinelli 2020-03-18 12:39 ` Matt Wette 1 sibling, 0 replies; 11+ messages in thread From: Massimiliano Gubinelli @ 2020-03-18 11:06 UTC (permalink / raw) To: Taylan Kammer; +Cc: guile-user Let me precise my concerns. I know I can do (begin (initialization-code) (let ((vals (call-with-values (lambda () (bar)) (lambda vals vals)))) (finalization) (apply values vals))) this is the hack I'm using now in my code. But my question is: does it incur performance penalties (it will be a macro, so used also in many other context where bar returns only a single value) Is there no better way to have multiple values interact in a composable way with macros??? Max > On 18. Mar 2020, at 10:55, Massimiliano Gubinelli <m.gubinelli@gmail.com> wrote: > > Thanks Taylan, > >> On 18. Mar 2020, at 07:12, Taylan Kammer <taylan.kammer@gmail.com> wrote: >> >> On 18.03.2020 00:50, Massimiliano Gubinelli wrote: >>> (let ((a (values "a" "b" "c"))) a) >> >> The result of (values x y z) is not a kind of object that contains three values (like a list or vector). It's three separate values that would need to be put into three separate variables. But you're only naming one variable (a). So strictly speaking the code is "wrong". >> >> In Guile 1.8, multiple values were actually put into some special kind of object (which was not very efficient) so code like that still somehow worked even thought it's technically wrong. >> >> Starting from Guile 2.0, providing multiple values in a context where only one is expected causes the extra values to be ignored. >> >> > > I understand the point but then it comes to the problem how to handle this in macros. For example if bar is a proceduce which returns multiple values and I have a macro "my-macro" which wraps the call with some initialization and finalization code and I write > > (my-macro (bar)) > > how to write this macro without knowing if bar is returning multiple values or not? For example I would like the code above to expand into > > (begin > (initialization-code) > (let ((ret (bar))) > (finalization-code) > ret)) > > > But this does not work as shown by the example above. How to implement this macro correctly? > > best > Max > > >> Happy to answer further questions about this. Multiple-values can be a tricky concept to grasp because most other programming languages don't have it. >> >> - Taylan ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 9:55 ` Massimiliano Gubinelli 2020-03-18 11:06 ` Massimiliano Gubinelli @ 2020-03-18 12:39 ` Matt Wette 2020-03-18 13:11 ` Massimiliano Gubinelli 1 sibling, 1 reply; 11+ messages in thread From: Matt Wette @ 2020-03-18 12:39 UTC (permalink / raw) To: guile-user On 3/18/20 2:55 AM, Massimiliano Gubinelli wrote: > I understand the point but then it comes to the problem how to handle this in macros. For example if bar is a proceduce which returns multiple values and I have a macro "my-macro" which wraps the call with some initialization and finalization code and I write > > (my-macro (bar)) > > how to write this macro without knowing if bar is returning multiple values or not? For example I would like the code above to expand into > > (begin > (initialization-code) > (let ((ret (bar))) > (finalization-code) > ret)) > > > But this does not work as shown by the example above. How to implement this macro correctly? > > How about calling (my-macro/values bar) where my-macro/values expands to (call-with-values (lambda () (bar)) (lambda args (finalization-code) (apply values args)) Matt ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 12:39 ` Matt Wette @ 2020-03-18 13:11 ` Massimiliano Gubinelli 2020-03-18 14:06 ` John Cowan 0 siblings, 1 reply; 11+ messages in thread From: Massimiliano Gubinelli @ 2020-03-18 13:11 UTC (permalink / raw) To: Matt Wette; +Cc: guile-user > On 18. Mar 2020, at 13:39, Matt Wette <matt.wette@gmail.com> wrote: > > > How about calling (my-macro/values bar) where my-macro/values expands to > > (call-with-values (lambda () (bar)) > (lambda args (finalization-code) (apply values args)) > > Matt > > Yeah! I like this better. But still wraps and unwraps the result. Is there any performance penalty in that? Apart from my specific user case I wonder how and why in general multiple values are used. Seems they are not well integrated in the current Guile implementation. In my naive opinion the behaviour of Guile 1.8 was more consistent. Max ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 13:11 ` Massimiliano Gubinelli @ 2020-03-18 14:06 ` John Cowan 2020-03-18 14:40 ` Massimiliano Gubinelli 0 siblings, 1 reply; 11+ messages in thread From: John Cowan @ 2020-03-18 14:06 UTC (permalink / raw) To: Massimiliano Gubinelli; +Cc: guile-user, Matt Wette There is going to be a performance penalty, because you are taking multiple values (which is not a value) and making it into a value by creating a list. There is no getting away from that except to exclude multiple values. Note also that if the procedure throws an exception, your finalizer will never be run. Consider using dynamic-wind, whose whole purpose is to make sure that an initializer and a finalizer are always run. On Wed, Mar 18, 2020 at 9:11 AM Massimiliano Gubinelli < m.gubinelli@gmail.com> wrote: > > > On 18. Mar 2020, at 13:39, Matt Wette <matt.wette@gmail.com> wrote: > > > > > > How about calling (my-macro/values bar) where my-macro/values expands to > > > > (call-with-values (lambda () (bar)) > > (lambda args (finalization-code) (apply values args)) > > > > Matt > > > > > > Yeah! I like this better. But still wraps and unwraps the result. > > Is there any performance penalty in that? > > Apart from my specific user case I wonder how and why in general multiple > values are used. Seems they are not well integrated in the current Guile > implementation. In my naive opinion the behaviour of Guile 1.8 was more > consistent. > > Max > > > > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 14:06 ` John Cowan @ 2020-03-18 14:40 ` Massimiliano Gubinelli 2020-03-18 14:48 ` Massimiliano Gubinelli 0 siblings, 1 reply; 11+ messages in thread From: Massimiliano Gubinelli @ 2020-03-18 14:40 UTC (permalink / raw) To: John Cowan; +Cc: guile-user, Matt Wette Good point with dynamic-wind. Does it pass along also multiple values or has the same problem? m > On 18. Mar 2020, at 15:06, John Cowan <cowan@ccil.org> wrote: > > There is going to be a performance penalty, because you are taking multiple values (which is not a value) and making it into a value by creating a list. There is no getting away from that except to exclude multiple values. > > Note also that if the procedure throws an exception, your finalizer will never be run. Consider using dynamic-wind, whose whole purpose is to make sure that an initializer and a finalizer are always run. > > On Wed, Mar 18, 2020 at 9:11 AM Massimiliano Gubinelli <m.gubinelli@gmail.com <mailto:m.gubinelli@gmail.com>> wrote: > > > On 18. Mar 2020, at 13:39, Matt Wette <matt.wette@gmail.com <mailto:matt.wette@gmail.com>> wrote: > > > > > > How about calling (my-macro/values bar) where my-macro/values expands to > > > > (call-with-values (lambda () (bar)) > > (lambda args (finalization-code) (apply values args)) > > > > Matt > > > > > > Yeah! I like this better. But still wraps and unwraps the result. > > Is there any performance penalty in that? > > Apart from my specific user case I wonder how and why in general multiple values are used. Seems they are not well integrated in the current Guile implementation. In my naive opinion the behaviour of Guile 1.8 was more consistent. > > Max > > > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 14:40 ` Massimiliano Gubinelli @ 2020-03-18 14:48 ` Massimiliano Gubinelli 2020-03-18 15:08 ` tomas 0 siblings, 1 reply; 11+ messages in thread From: Massimiliano Gubinelli @ 2020-03-18 14:48 UTC (permalink / raw) To: John Cowan; +Cc: guile-user, Matt Wette > On 18. Mar 2020, at 15:40, Massimiliano Gubinelli <m.gubinelli@gmail.com> wrote: > > Good point with dynamic-wind. Does it pass along also multiple values or has the same problem? > Does not work... mgubi@Ulrike guile3-usr % bin/guile GNU Guile 3.0.1 Copyright (C) 1995-2020 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user)> (call-with-values (lambda () (dynamic-wind (lambda () (display "initialize\n")) (lambda () (let ((a (values "a" "b" "c"))) a)) (lambda () (display "finalize\n")))) (lambda body body)) initialize finalize $1 = ("a") scheme@(guile-user)> Isn't this a bug??? In my view it breaks composability of scheme code. Best, Max > m > > >> On 18. Mar 2020, at 15:06, John Cowan <cowan@ccil.org> wrote: >> >> There is going to be a performance penalty, because you are taking multiple values (which is not a value) and making it into a value by creating a list. There is no getting away from that except to exclude multiple values. >> >> Note also that if the procedure throws an exception, your finalizer will never be run. Consider using dynamic-wind, whose whole purpose is to make sure that an initializer and a finalizer are always run. >> >> On Wed, Mar 18, 2020 at 9:11 AM Massimiliano Gubinelli <m.gubinelli@gmail.com> wrote: >> >> > On 18. Mar 2020, at 13:39, Matt Wette <matt.wette@gmail.com> wrote: >> > >> > >> > How about calling (my-macro/values bar) where my-macro/values expands to >> > >> > (call-with-values (lambda () (bar)) >> > (lambda args (finalization-code) (apply values args)) >> > >> > Matt >> > >> > >> >> Yeah! I like this better. But still wraps and unwraps the result. >> >> Is there any performance penalty in that? >> >> Apart from my specific user case I wonder how and why in general multiple values are used. Seems they are not well integrated in the current Guile implementation. In my naive opinion the behaviour of Guile 1.8 was more consistent. >> >> Max >> >> >> > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 14:48 ` Massimiliano Gubinelli @ 2020-03-18 15:08 ` tomas 2020-03-18 15:34 ` Massimiliano Gubinelli 0 siblings, 1 reply; 11+ messages in thread From: tomas @ 2020-03-18 15:08 UTC (permalink / raw) To: Massimiliano Gubinelli; +Cc: guile-user, Matt Wette [-- Attachment #1: Type: text/plain, Size: 1335 bytes --] On Wed, Mar 18, 2020 at 03:48:03PM +0100, Massimiliano Gubinelli wrote: > > > On 18. Mar 2020, at 15:40, Massimiliano Gubinelli <m.gubinelli@gmail.com> wrote: > > > > Good point with dynamic-wind. Does it pass along also multiple values or has the same problem? > > > > Does not work... > > mgubi@Ulrike guile3-usr % bin/guile > GNU Guile 3.0.1 > Copyright (C) 1995-2020 Free Software Foundation, Inc. > > Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. > This program is free software, and you are welcome to redistribute it > under certain conditions; type `,show c' for details. > > Enter `,help' for help. > scheme@(guile-user)> (call-with-values (lambda () > (dynamic-wind (lambda () (display "initialize\n")) > (lambda () (let ((a (values "a" "b" "c"))) a)) ^^^^^^ HERE > (lambda () (display "finalize\n")))) > (lambda body body)) > initialize > finalize > $1 = ("a") > scheme@(guile-user)> > > Isn't this a bug??? In my view it breaks composability of scheme code. Above, marked with HERE is the crocodile eating your other values. If you instead do, in that line (lambda () (values "a" "b" "c")) then you get ("a" "b" "c"). The let binding construct only binds one value. There's a "let-values" for that. Cheers -- tomás [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: question about values 2020-03-18 15:08 ` tomas @ 2020-03-18 15:34 ` Massimiliano Gubinelli 0 siblings, 0 replies; 11+ messages in thread From: Massimiliano Gubinelli @ 2020-03-18 15:34 UTC (permalink / raw) To: tomas; +Cc: guile-user, Matt Wette Yes. Sorry. My bad, I had coded by copy&paste my previous example and is obviously not going to work. Indeed dynamic-wind works as it should: mgubi@Ulrike guile3-usr % bin/guile GNU Guile 3.0.1 Copyright (C) 1995-2020 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user)> (call-with-values (lambda () (dynamic-wind (lambda () (display "initialize\n")) (lambda () (values "a" "b" "c")) (lambda () (display "finalize\n")))) (lambda body body)) initialize finalize $2 = ("a" "b" "c") It seems to me a very good solution to my problem. Thanks a lot to all! Max > On 18. Mar 2020, at 16:08, tomas@tuxteam.de wrote: > > On Wed, Mar 18, 2020 at 03:48:03PM +0100, Massimiliano Gubinelli wrote: >> >>> On 18. Mar 2020, at 15:40, Massimiliano Gubinelli <m.gubinelli@gmail.com> wrote: >>> >>> Good point with dynamic-wind. Does it pass along also multiple values or has the same problem? >>> >> >> Does not work... >> >> mgubi@Ulrike guile3-usr % bin/guile >> GNU Guile 3.0.1 >> Copyright (C) 1995-2020 Free Software Foundation, Inc. >> >> Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. >> This program is free software, and you are welcome to redistribute it >> under certain conditions; type `,show c' for details. >> >> Enter `,help' for help. >> scheme@(guile-user)> (call-with-values (lambda () >> (dynamic-wind (lambda () (display "initialize\n")) >> (lambda () (let ((a (values "a" "b" "c"))) a)) > ^^^^^^ HERE >> (lambda () (display "finalize\n")))) >> (lambda body body)) >> initialize >> finalize >> $1 = ("a") >> scheme@(guile-user)> >> >> Isn't this a bug??? In my view it breaks composability of scheme code. > > Above, marked with HERE is the crocodile eating > your other values. > > If you instead do, in that line > > (lambda () (values "a" "b" "c")) > > then you get ("a" "b" "c"). > > The let binding construct only binds one value. There's a > "let-values" for that. > > Cheers > -- tomás ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2020-03-18 15:34 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-03-17 23:50 question about values Massimiliano Gubinelli 2020-03-18 6:12 ` Taylan Kammer 2020-03-18 9:55 ` Massimiliano Gubinelli 2020-03-18 11:06 ` Massimiliano Gubinelli 2020-03-18 12:39 ` Matt Wette 2020-03-18 13:11 ` Massimiliano Gubinelli 2020-03-18 14:06 ` John Cowan 2020-03-18 14:40 ` Massimiliano Gubinelli 2020-03-18 14:48 ` Massimiliano Gubinelli 2020-03-18 15:08 ` tomas 2020-03-18 15:34 ` Massimiliano Gubinelli
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).