Re: Self-evaluating function and closure
Mark, On Sat, Jun 15, 2019 at 08:36:34PM -0400, Mark H Weaver wrote: > Hi Vladimir, > > Vladimir Zhbanov writes: > > > Greetings, > > > > I have tried almost a textbook example with Guile 2.2.4: > > > > scheme@(guile-user)> (define (function-generator) > >(let ((func #f)) > > (lambda () (set! func (let a () a)) func))) > > > > scheme@(guile-user)> (define x (function-generator)) > > scheme@(guile-user)> (define y (function-generator)) > > scheme@(guile-user)> x > > $20 = #:562:25 ()> > > scheme@(guile-user)> y > > $21 = #:562:25 ()> > > scheme@(guile-user)> (x) > > $22 = # > > scheme@(guile-user)> (y) > > $23 = # > > scheme@(guile-user)> (eq? (x) (y)) > > $24 = #t > > > > The result is unexpected for me, I expected a new self-evaluating > > procedure every time I run the function-generator procedure (and > > it works differently with Guile 2.0, IIUC, cannot check just now). > > Why would you expect 'eq?' to return #false here? Do you know of any > text in Guile's manual, or in any of the relevant Scheme standards, that > would lead you to expect this? > > Since (let a () a) contains no free variable references, every procedure > returned by (let a () a) is operationally equivalent to every other > procedure returned by it. Therefore, as I understand it, a conforming > Scheme implementation is permitted (but not required) to return the same > procedure object every time. If the procedure is defined inside a closure, should it be available at toplevel (especially with the same name it was defined inside a function)? > > I just refreshed my memory of the requirements of the R5RS, R6RS, and > R7RS on 'eq?' when applied to procedures. Conforming implementations > are required to return #true if the procedures have the same "location > tags", and are required to return #false if the procedures would behave > differently (return different value(s) or have different side effects) > for some arguments. > > > AFAICS, Guile creates a toplevel procedure "a" while it should not do > >so. > > > > scheme@(guile-user)> a > > $25 = #:422:25 ()> > > If this were the case, it would certainly be a bug. However, I cannot > reproduce it, and I strongly suspect that you had defined 'a' as a > toplevel variable earlier in your Guile session and forgot about it. No, I'haven't defined anything before. OK, let's start with a fresh session and use another name: GNU Guile 2.2.4 Copyright (C) 1995-2017 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)> (define (function-generator) (let ((func #f)) (lambda () (set! func (let b () b)) func))) scheme@(guile-user)> (define x (function-generator)) scheme@(guile-user)> (define y (function-generator)) scheme@(guile-user)> x $4 = #:108:25 ()> scheme@(guile-user)> y $5 = #:108:25 ()> scheme@(guile-user)> (x) $6 = # scheme@(guile-user)> (y) $7 = # scheme@(guile-user)> (eq? (x) (y)) $8 = #t scheme@(guile-user)> ,compile (define (function-generator) (let ((func #f)) (lambda () (set! func (let b () b)) func))) Disassembly of at #x98: 0(assert-nargs-ee/locals 1 1);; 2 slots (0 args) at (unknown file):185:9 1(static-ref 1 75) ;; function-generator 3(define! 1 1) 4(make-non-immediate 0 74) ;; # 6(box-set! 1 0) 7(make-short-immediate 0 2052) ;; # 8(handle-interrupts) 9(return-values 2) ;; 1 value Disassembly of function-generator at #xc0: 0(assert-nargs-ee/locals 1 1);; 2 slots (0 args) at (unknown file):185:9 1(make-short-immediate 1 4) ;; #f 2(box 1 1) 3(make-closure 0 7 1);; anonymous procedure at #xb2c0aac8 (1 free var) at (unknown file):187:25 6(free-set! 0 1 0) ;; free var 0 8(handle-interrupts) 9(return-values 2) ;; 1 value Disassembly of at #xe8: 0(assert-nargs-ee/locals 1 1);; 2 slots (0 args) at (unknown file):187:25 1(free-ref 1 1 0);; free var 0 3(make-non-immediate 0 57) ;; # 5(box-set! 1 0)at (unknown file):187:36 6(make-non-immediate 0 54) ;; # 8(handle-interrupts) 9(return-values 2) ;; 1 value Disassembly of b at #x110: 0(assert-nargs-ee/locals 1 1);; 2 slots (0 args) at (unknown file):187:47 1(make-non-immediate 0 49) ;; # 3(handle-interrupts) 4(return-values 2) ;; 1 value
Re: Self-evaluating function and closure
Hello again Vladimir, Vladimir Zhbanov writes: > - Is there a way to work around this (either using the above 'let' > construct or anything else)? I'm not quite sure how to answer this question because I don't know what your requirements are. If you need to generate unique tags, any mutable object will do, e.g. a vector, list or string with at least one element that is not a literal. For example, (list #f), (vector #f), and (string #\a) must allocate a fresh object every time, but (list), (vector), (string), '(#f), #(#f), and "foo" may return the same object every time. If you need to generate a unique _procedure_, there's only one future-proof way to do it: the new procedure must behave differently than every other procedure, for some input. It's a mistake to expect procedures with equivalent behavior to be distinguishable in Scheme. If you feel that you need this, I would like to understand why. Note that 'eq?' is the same as 'eqv?' when applied to procedures (and most other types), and that Scheme 'eqv?' historically implements an approximation of "operational equivalence". That language was explicit in the R3RS, which defined 'eqv?' this way: The eqv? procedure implements an approximation to the relation of operational equivalence. It returns #t if it can prove that obj1 and obj2 are operationally equivalent. If it can't, it always errs on the conservative side and returns #f. with "operational equivalence" defined as follows: Two objects are operationally equivalent if and only if there is no way that they can be distinguished, using Scheme primitives other than eqv? or eq? or those like memq and assv whose meaning is defined explicitly in terms of eqv? or eq?. It is guaranteed that objects maintain their operational identity despite being named by variables or fetched from or stored into data structures. More recent Scheme standards have dropped this language, because the Scheme authors were not entirely satisfied with this definition and were unable to formulate a better one, but nonetheless "operational equivalence" remains the closest thing I've seen to a unifying principle of the meaning of Scheme 'eqv?'. Regards, Mark
Re: Self-evaluating function and closure
Am So., 16. Juni 2019 um 11:49 Uhr schrieb Mark H Weaver : > > Hello again Vladimir, > > Vladimir Zhbanov writes: > > - Is there a way to work around this (either using the above 'let' > > construct or anything else)? > > I'm not quite sure how to answer this question because I don't know what > your requirements are. > > If you need to generate unique tags, any mutable object will do, e.g. a > vector, list or string with at least one element that is not a literal. > For example, (list #f), (vector #f), and (string #\a) must allocate a > fresh object every time, but (list), (vector), (string), '(#f), #(#f), > and "foo" may return the same object every time. > > If you need to generate a unique _procedure_, there's only one > future-proof way to do it: the new procedure must behave differently > than every other procedure, for some input. > > It's a mistake to expect procedures with equivalent behavior to be > distinguishable in Scheme. If you feel that you need this, I would like > to understand why. > > Note that 'eq?' is the same as 'eqv?' when applied to procedures (and > most other types), and that Scheme 'eqv?' historically implements an > approximation of "operational equivalence". That language was explicit > in the R3RS, which defined 'eqv?' this way: > > The eqv? procedure implements an approximation to the relation of > operational equivalence. It returns #t if it can prove that obj1 and > obj2 are operationally equivalent. If it can't, it always errs on the > conservative side and returns #f. > > with "operational equivalence" defined as follows: > > Two objects are operationally equivalent if and only if there is no > way that they can be distinguished, using Scheme primitives other than > eqv? or eq? or those like memq and assv whose meaning is defined > explicitly in terms of eqv? or eq?. It is guaranteed that objects > maintain their operational identity despite being named by variables > or fetched from or stored into data structures. > > More recent Scheme standards have dropped this language, because the > Scheme authors were not entirely satisfied with this definition and were > unable to formulate a better one, but nonetheless "operational > equivalence" remains the closest thing I've seen to a unifying principle > of the meaning of Scheme 'eqv?'. > > Regards, > Mark > Hi Mark, always interested in guile developments with regard to lilypond I noticed some inconsistence with my local lilypond-using-guile-2.9.2 installation. I think I could break it down to pure guile (no lilypond) (1) The already stated behaviour: ~$ guile GNU Guile 2.9.2 Copyright (C) 1995-2019 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)> (define (function-generator) (let ((func #f)) (lambda () (set! func (let a () a)) func))) scheme@(guile-user)> (define x (function-generator)) scheme@(guile-user)> (define y (function-generator)) scheme@(guile-user)> (write (version)) "2.9.2" scheme@(guile-user)> (format #t "\nTEST: ~a" (eq? (x) (y))) TEST: #t $1 = #t (2) Doing it in a .scm-file (attached) ~$ guile --no-auto-compile eq-tst.scm "2.9.2" TEST: #f Did I something wrong or is it a bug? Cheers, Harm (define (function-generator) (let ((func #f)) (lambda () (set! func (let a () a)) func))) (define x (function-generator)) (define y (function-generator)) (write (version)) (format #t "\nTEST: ~a" (eq? (x) (y)))
Re: Self-evaluating function and closure
Hi Vladimir, Vladimir Zhbanov writes: > On Sat, Jun 15, 2019 at 08:36:34PM -0400, Mark H Weaver wrote: >> Vladimir Zhbanov writes: >> >> > I have tried almost a textbook example with Guile 2.2.4: >> > >> > scheme@(guile-user)> (define (function-generator) >> >(let ((func #f)) >> > (lambda () (set! func (let a () a)) func))) >> > >> > scheme@(guile-user)> (define x (function-generator)) >> > scheme@(guile-user)> (define y (function-generator)) >> > scheme@(guile-user)> x >> > $20 = #:562:25 ()> >> > scheme@(guile-user)> y >> > $21 = #:562:25 ()> >> > scheme@(guile-user)> (x) >> > $22 = # >> > scheme@(guile-user)> (y) >> > $23 = # >> > scheme@(guile-user)> (eq? (x) (y)) >> > $24 = #t >> > >> > The result is unexpected for me, I expected a new self-evaluating >> > procedure every time I run the function-generator procedure (and >> > it works differently with Guile 2.0, IIUC, cannot check just now). >> >> Why would you expect 'eq?' to return #false here? Do you know of any >> text in Guile's manual, or in any of the relevant Scheme standards, that >> would lead you to expect this? >> >> Since (let a () a) contains no free variable references, every procedure >> returned by (let a () a) is operationally equivalent to every other >> procedure returned by it. Therefore, as I understand it, a conforming >> Scheme implementation is permitted (but not required) to return the same >> procedure object every time. > > If the procedure is defined inside a closure, should it be > available at toplevel (especially with the same name it was > defined inside a function)? A variable bound within a local lexical environment certainly should not be visible at toplevel. In particular, the transcript that you provided above should *not* result in 'a' being bound in the toplevel environment. When I type those precise commands into Guile 2.2.4 on my system, 'a' is *not* bound at toplevel. Here's what I see: mhw@jojen ~$ guile GNU Guile 2.2.4 Copyright (C) 1995-2017 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)> (define (function-generator) (let ((func #f)) (lambda () (set! func (let a () a)) func))) scheme@(guile-user)> (define x (function-generator)) scheme@(guile-user)> (define y (function-generator)) scheme@(guile-user)> x $1 = #:3:26 ()> scheme@(guile-user)> y $2 = #:3:26 ()> scheme@(guile-user)> (x) $3 = # scheme@(guile-user)> (y) $4 = # scheme@(guile-user)> (eq? (x) (y)) $5 = #t scheme@(guile-user)> a ;;; : warning: possibly unbound variable `a' ERROR: In procedure module-lookup: Unbound variable: a Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. scheme@(guile-user) [1]> >> If this were the case, it would certainly be a bug. However, I cannot >> reproduce it, and I strongly suspect that you had defined 'a' as a >> toplevel variable earlier in your Guile session and forgot about it. > > No, I'haven't defined anything before. > > OK, let's start with a fresh session and use another name: > > > > GNU Guile 2.2.4 > Copyright (C) 1995-2017 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)> (define (function-generator) >(let ((func #f)) > (lambda () (set! func (let b () b)) func))) > scheme@(guile-user)> (define x (function-generator)) > scheme@(guile-user)> (define y (function-generator)) > scheme@(guile-user)> x > $4 = #:108:25 ()> > scheme@(guile-user)> y > $5 = #:108:25 ()> > scheme@(guile-user)> (x) > $6 = # > scheme@(guile-user)> (y) > $7 = # > scheme@(guile-user)> (eq? (x) (y)) > $8 = #t This new transcript does not include an evaluation of 'b' at toplevel. Can you show me a complete transcript that demonstrates this behavior? > scheme@(guile-user)> ,compile (define (function-generator) >(let ((func #f)) > (lambda () (set! func (let b () b)) func))) > Disassembly of at #x98: > >0(assert-nargs-ee/locals 1 1);; 2 slots (0 args) at (unknown > file):185:9 >1(static-ref 1 75) ;; function-generator >3(define! 1 1) >4(make-non-immediate 0 74) ;; # >6(box-set! 1 0) >7(make-short-immediate 0 2052) ;; # >8(handle-interrupts) >9(return-values 2) ;; 1 value > > > Disassembly of function-g
Re: Self-evaluating function and closure
Hi Thomas, Thomas Morley writes: > always interested in guile developments with regard to lilypond I > noticed some inconsistence with my local lilypond-using-guile-2.9.2 > installation. > I think I could break it down to pure guile (no lilypond) > > (1) The already stated behaviour: > ~$ guile > GNU Guile 2.9.2 > Copyright (C) 1995-2019 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)> (define (function-generator) > (let ((func #f)) > (lambda () (set! func (let a () a)) func))) > scheme@(guile-user)> (define x (function-generator)) > scheme@(guile-user)> (define y (function-generator)) > scheme@(guile-user)> (write (version)) > "2.9.2" > scheme@(guile-user)> (format #t "\nTEST: ~a" (eq? (x) (y))) > > TEST: #t > $1 = #t > > (2) Doing it in a .scm-file (attached) > ~$ guile --no-auto-compile eq-tst.scm > "2.9.2" > TEST: #f > > Did I something wrong or is it a bug? Neither. This is a case of unspecified behavior, and the behavior of our compiler differs from that of our interpreter. You will notice similar discrepancies when comparing two literal lists or strings, where our compiler will aggressively unify literals within a compilation unit, and our interpreter does not: --8<---cut here---start->8--- GNU Guile 2.2.4 Copyright (C) 1995-2017 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)> (eqv? "hello" "hello") $1 = #t scheme@(guile-user)> ,o interp #t scheme@(guile-user)> (eqv? "hello" "hello") $2 = #f scheme@(guile-user)> --8<---cut here---end--->8--- Regards, Mark
Re: Self-evaluating function and closure
Hi Mark, Am So., 16. Juni 2019 um 12:35 Uhr schrieb Mark H Weaver : > > Did I something wrong or is it a bug? > > Neither. This is a case of unspecified behavior, and the behavior of > our compiler differs from that of our interpreter. You will notice > similar discrepancies when comparing two literal lists or strings, where > our compiler will aggressively unify literals within a compilation unit, > and our interpreter does not: [...] ah, ok, thanks for the explanation. Cheers, Harm
Re: Self-evaluating function and closure
Hello again, Vladimir Zhbanov writes: > scheme@(guile-user)> (define (function-generator) >(let ((func #f)) > (lambda () (set! func (let a () a)) func))) [...] > - Is there a way to work around this (either using the above 'let' > construct or anything else)? Ideally, the code would be reworked to not expect equivalent procedures to be distinguishable. However, I should probably offer a hacky but expedient workaround. Here's one way to make otherwise equivalent procedures distinguishable: Allocate a fresh tag using (list #f), and arrange for the procedure to return that tag if it's called with a special input that's outside of the normal domain. Note that for Scheme procedures, the "input" is in general a list of arguments of arbitrary length. You could use 'case-lambda', which creates procedures that evaluate different body expressions depending on how many arguments are passed to it. Just add a case for an arity that you will never use, which returns the unique tag. In the example you gave, (let a () a) is equivalent to: ((letrec ((a (lambda () a))) a)) The procedure returned by (let a () a) expects 0 arguments. It will raise an error otherwise. We can repurpose the previously erroneous arity-1 case to return the unique tag, as follows: (let ((unique-tag (list #f))) ((letrec ((a (case-lambda (() a) ((x) unique-tag a))) Every time the above expression is evaluated, it will necessarily return a unique procedure, which, if passed 0 arguments, behaves the same as the procedure returned by (let a () a). Mark
Re: Srfi-159/166 - monadic formatting for guile
On Sun, Jun 16, 2019 at 2:47 AM Mark H Weaver wrote: > How do you implement 'written-shared', 'pretty-shared', and > 'trimmed/lazy'? In particular, how do you avoid non-termination when > asked to print cyclic data, when the cycle includes a non-standard data > type printed using a custom printer? For example, what if you print a > list that includes an object whose custom printer will print output that > includes the same list that you started with? > Of course it can't cope with that. But consider an object whose custom printer outputs its instance variables where one of those instance variables has been assigned to the object itself. No procedure other than the object printer itself is going to be able to break *that* loop. John Cowan http://vrici.lojban.org/~cowanco...@ccil.org Yes, chili in the eye is bad, but so is your ear. However, I would suggest you wash your hands thoroughly before going to the toilet. --gadicath
[ANN] guile-gi 0.0.2 released
Hello. I am announcing guile-gi v0.0.2. guile-gi is a library that autogenerates GNU Guile bindings for GObject libraries that provide typelib files. GNU Guile is an implementation of Scheme, a Lisp-like language. GObject is a standard way of writing C-language libraries with headers and introspection information that are intended to allow them to be used from other languages. Typelib files are GObject's standard way to provide that introspection information. Among the GObject libraries are GTK3 and WebKitGTK2, two popular GUI libraries. In short, this library hopes to make GTK3 and WebKit2 available to Guile. This particular library is one of several different attempts and solving the interface between GTK+3 and Guile. Its differentiating (mis)feature is that its bindings are created dynamically at runtime by parsing typelib files. This is pre-alpha code. Use at your own risk. The NEWS for this release is - Improvements in C-to-SCM procedure argument conversions - Guix skeleton (thanks Jan) - More versatile GObject construction (thanks LordYuuma) - More tests and demos The git repo is at https://github.com/spk121/guile-gi.git The code can be browsed at https://github.com/spk121/guile-gi The almost non-existent documentation can be read at https://spk121.github.io/guile-gi/ A tarball can be downloaded from http://lonelycactus.com/tarball/guile-gi-0.0.2.tar.gz To read about what this library is supposed to do, check out https://spk121.github.io/guile-gi/Getting-Started.html Regards, Mike Gran
Re: Srfi-159/166 - monadic formatting for guile
Hi John, John Cowan writes: > On Sun, Jun 16, 2019 at 2:47 AM Mark H Weaver wrote: > > >> How do you implement 'written-shared', 'pretty-shared', and >> 'trimmed/lazy'? In particular, how do you avoid non-termination when >> asked to print cyclic data, when the cycle includes a non-standard data >> type printed using a custom printer? For example, what if you print a >> list that includes an object whose custom printer will print output that >> includes the same list that you started with? >> > > Of course it can't cope with that. But consider an object whose custom > printer outputs its instance variables where one of those instance variables > has been assigned to the object itself. No procedure other than the object > printer itself is going to be able to break *that* loop. The built-in 'write' and 'display' procedures can break the loop, which is the approach that I chose when I last looked at this. Regards, Mark
Re: guile-gi: scancode->keyval?
On Fri, Jun 14, 2019 at 01:14:29PM +0200, Jan Nieuwenhuizen wrote: > Mike Gran writes: > > > ...and I found another one, trying to load text in the test/editor.scm example > > (let ((buffer (send editor (get-buffer > (warn 'buffer buffer) ; => ;; WARNING (buffer #< > 22bcc30>) > ;; BOOM: => free(): invalid pointer > (send buffer (set-text "Hello, world!"))) I pushed a new release with an updated test/editor.scm that works, I think. Thanks, Mike Gran
Re: [ANN] guile-gi 0.0.2 released
On Sun, 16 Jun 2019 14:20:27 -0500 Mike Gran wrote > Hello. I am announcing guile-gi v0.0.2. > > guile-gi is a library that autogenerates GNU Guile bindings for > GObject libraries that provide typelib files. GNU Guile is an > implementation of Scheme, a Lisp-like language. GObject is a standard > way of writing C-language libraries with headers and introspection > information that are intended to allow them to be used from other > languages. Typelib files are GObject's standard way to provide that > introspection information. Among the GObject libraries are GTK3 and > WebKitGTK2, two popular GUI libraries. > > In short, this library hopes to make GTK3 and WebKit2 available to > Guile. > > This particular library is one of several different attempts and > solving the interface between GTK+3 and Guile. Its differentiating > (mis)feature is that its bindings are created dynamically at runtime > by parsing typelib files. > > This is pre-alpha code. Use at your own risk. > > The NEWS for this release is > - Improvements in C-to-SCM procedure argument conversions > - Guix skeleton (thanks Jan) > - More versatile GObject construction (thanks LordYuuma) > - More tests and demos > > The git repo is at > https://github.com/spk121/guile-gi.git > The code can be browsed at > https://github.com/spk121/guile-gi > The almost non-existent documentation can be read at > https://spk121.github.io/guile-gi/ > A tarball can be downloaded from > http://lonelycactus.com/tarball/guile-gi-0.0.2.tar.gz > > To read about what this library is supposed to do, check out > https://spk121.github.io/guile-gi/Getting-Started.html > > Regards, > Mike Gran > > I want to use guile-gi in the future. Thanks for working on this :)
Re: Srfi-159/166 - monadic formatting for guile
Well, in the written-shared/pretty-shared case, Alex Shinn (I just ported his reference implementation) relies on display/write for everything except lists and vectors, and those are, from what I can tell, exhaustively checked for cycles. trimmed/lazy I have to have a read through in some other way than black-on-white text on my 3.5" phone. Best regards Linus -- Linus Björnstam On Sun, 16 Jun 2019, at 08:37, Mark H Weaver wrote: > Hi Linus, > > Linus Björnstam writes: > > > I am not sure I understand what you mean, but i suspect it is already > > solved, since for simple cases show will use display/write. So unless > > you try to do advanced formatting of circular lists it will do > > whatever display or write does. The same thing goes for custom > > printers. > > How do you implement 'written-shared', 'pretty-shared', and > 'trimmed/lazy'? In particular, how do you avoid non-termination when > asked to print cyclic data, when the cycle includes a non-standard data > type printed using a custom printer? For example, what if you print a > list that includes an object whose custom printer will print output that > includes the same list that you started with? > > Regards, >Mark >
Re: [ANN] guile-gi 0.0.2 released
Mike Gran writes: > In short, this library hopes to make GTK3 and WebKit2 available to > Guile. > > This particular library is one of several different attempts and > solving the interface between GTK+3 and Guile. Its differentiating > (mis)feature is that its bindings are created dynamically at runtime > by parsing typelib files. This is very important work. Thank you! Mark