[racket] procedure, contract, assoc, and REPL
Yes, that's not quite precise enough about eq?. It really just means
"at the low level are these two objects stored in the same place in
memory". Nothing more, nothing less. In general, for procedures it
does not come with any guarantees and lots of things in the system can
change how it works. (There are guarantees for other kinds of objects
wrt to eq?.)
The way the contract system creates the wrappers is a bit subtle. In
general, it needs to create at least one wrapper object per module
that uses the procedure so it tries to create at most one as well, but
in the REPL it cannot do that, so it creates one wrapper per use of
the variable. (The reason it needs at least one per module that uses
the procedure is for proper blame assignment. If two modules, say A
and B, both use the contracted function, then either module might be
blamed, so one wrapper function has an "A" somewhere inside the other
has a "B".)
hth,
Robby
On Wed, Jul 21, 2010 at 11:48 PM, YC <yinso.chen at gmail.com> wrote:
> Hi Robby -
> What I am trying to do is to look up a key/value pair where the key happens
> to be the procedure. The struct idea will work only if I can serialize/hash
> the procedure into a unique key, which means I will still have to rely on a
> procedure matching itself (otherwise it's too much work for the client).
> The scenario really boils down to - why does a contracted procedure not eq
> itself?
> The same script above shows that a contracted procedure returns #f with eq?,
> but a plain procedure returns #t in REPL (both returns #t in module).
>> (eq? test? test?) ;; test? is contracted.
> #f
>> (eq? test2? test2?) ;; test2? is not contracted
> #t
> Looking at the definition of eq? shows that eq? is for determining whether
> two objects are the same. And since both test? and test2? are exposed via a
> module, i.e. they are "fixed" once exposed outside of module, whether
> contracted or not - I would have expected eq? would return #t for both cases
> in REPL.
> Am I misunderstand what eq? is all about? Thanks.
> yc
> On Wed, Jul 21, 2010 at 5:40 PM, Robby Findler <robby at eecs.northwestern.edu>
> wrote:
>>
>> You seem to be relying on identity of procedures (which is a bad
>> idea). Contracts on functions are implemented with wrappers which
>> breaks that by making fewer things equal but compiler optimizations
>> can take things the other direction making more things equal than you
>> might expect.
>>
>> Overall I think you should just avoid relying on the identity of
>> procedures. One way to do that (without knowing more about your code)
>> would be to use struct procedures and put an extra field on the struct
>> that gives you the key for a comparison.
>>
>> Hth,
>> Robby
>>
>> On Wednesday, July 21, 2010, YC <yinso.chen at gmail.com> wrote:
>> > Hi all -
>> >
>> > I am running into an interesting issue where an alist of procedures in
>> > REPL, the ones without a contract works with assoc, but the ones with
>> > contract do not work with assoc.
>> >
>> > What I have is an alist where the keys are procedures. Some of these
>> > procedures have contracts attached to them, and some do not. Then I tried
>> > to use assoc to match the procedures. If the code are run within the module
>> > itself - both types match, but within REPL only the ones without contract
>> > matches.
>> >
>> > Here's an simplified example, where foo.ss defines the procedures, and
>> > the test.ss uses foo.ss to construct the alist.
>> >
>> > ;; foo.ss
>> > #lang scheme
>> > (define (test? v) #t) ;; provided with contract
>> >
>> > (define (test2? v) #t) ;; provided without contract
>> >
>> > (provide/contract
>> > (test? (-> any/c boolean?))
>> > )
>> >
>> > (provide test2?)
>> >
>> > ;; test.ss
>> > #lang scheme
>> > (require "foo.ss")
>> >
>> > (define table `((,test2? . 1) (,test? . 2)))
>> >
>> > (assoc test? table) ;; works in module setting but not in REPL
>> >
>> > (assoc test2? table) ;; works in module setting AND in REPL
>> >
>> > Both the assoc test above returns the correct result. But if I try to
>> > copy and run (assoc test? table) in REPL again, it will not match, whereas
>> > (assoc test2? table) continues to match.
>> >
>> > Is there any particular reason for the divergence of the behaviors? I
>> > verified the behavior in both v4.2.5 and v5.0. Thanks.
>> >
>> > yc
>> >
>> >
>> >
>> >
>> >
>
>
>
> --
> Cheers,
> yc
>
> Taming the software dragon - http://dragonmaestro.com
>
>