From: Vladimir Zhbanov <vzhbanov@gmail.com>
To: guile-user@gnu.org
Subject: Re: Self-evaluating function and closure
Date: Sun, 16 Jun 2019 12:02:20 +0300 [thread overview]
Message-ID: <20190616090220.GA3181@newvzh.lokolhoz> (raw)
In-Reply-To: <87d0je4b82.fsf@netris.org>
Mark,
On Sat, Jun 15, 2019 at 08:36:34PM -0400, Mark H Weaver wrote:
> Hi Vladimir,
>
> Vladimir Zhbanov <vzhbanov@gmail.com> 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 = #<procedure f9f9d0 at <unknown port>:562:25 ()>
> > scheme@(guile-user)> y
> > $21 = #<procedure bf2660 at <unknown port>:562:25 ()>
> > scheme@(guile-user)> (x)
> > $22 = #<procedure a ()>
> > scheme@(guile-user)> (y)
> > $23 = #<procedure a ()>
> > 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 = #<procedure 109aa90 at <unknown port>: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:
<Geiser session starts here>
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 = #<procedure 16949b0 at <unknown port>:108:25 ()>
scheme@(guile-user)> y
$5 = #<procedure 1860200 at <unknown port>:108:25 ()>
scheme@(guile-user)> (x)
$6 = #<procedure b ()>
scheme@(guile-user)> (y)
$7 = #<procedure b ()>
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 <unnamed function> 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) ;; #<procedure function-generator ()>
6 (box-set! 1 0)
7 (make-short-immediate 0 2052) ;; #<unspecified>
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 <unnamed function> 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) ;; #<procedure b ()>
5 (box-set! 1 0) at (unknown file):187:36
6 (make-non-immediate 0 54) ;; #<procedure b ()>
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) ;; #<procedure b ()>
3 (handle-interrupts)
4 (return-values 2) ;; 1 value
Disassembly of <unnamed function> at #x124:
0 (assert-nargs-ee/locals 1 1) ;; 2 slots (0 args) at (unknown file):187:47
1 (static-patch! 37 16)
4 (make-non-immediate 1 33) ;; "function-generator"
6 (string->symbol 1 1)
7 (static-set! 1 34) ;; function-generator
9 (static-patch! 35 -34)
12 (static-patch! 34 -17)
15 (make-short-immediate 0 2052) ;; #<unspecified>
16 (return-values 2) ;; 1 value
<Geiser session ends here>
The same behaviour, though now the procedure name is 'b'.
The line that confuses me here is:
5 (box-set! 1 0) at (unknown file):187:36
I suspect this is a toplevel definition.
To make it clear, why I ask here, this new behaviour in Guile 2.2
broke our schematic frontend actions (that were defined in such a
way I presented above) after moving from Guile 2.0 to it. IIUC,
at least guile versions compiled on Debian and FreeBSD involved.
--
Vladimir
(λ)επτόν EDA — https://github.com/lepton-eda
next prev parent reply other threads:[~2019-06-16 9:02 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-12 20:29 Self-evaluating function and closure Vladimir Zhbanov
2019-06-15 19:35 ` John Cowan
2019-06-16 0:39 ` Mark H Weaver
2019-06-16 0:36 ` Mark H Weaver
2019-06-16 9:02 ` Vladimir Zhbanov [this message]
2019-06-16 10:09 ` Mark H Weaver
2019-06-17 8:03 ` Vladimir Zhbanov
2019-06-16 9:47 ` Mark H Weaver
2019-06-16 10:21 ` Thomas Morley
2019-06-16 10:32 ` Mark H Weaver
2019-06-16 10:42 ` Thomas Morley
2019-06-16 11:29 ` Mark H Weaver
2019-06-17 8:48 ` Vladimir Zhbanov
2019-06-17 14:21 ` Mark H Weaver
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=20190616090220.GA3181@newvzh.lokolhoz \
--to=vzhbanov@gmail.com \
--cc=guile-user@gnu.org \
/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).