[racket-dev] Blame and re-provided bindings

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Sat Jan 15 08:56:50 EST 2011

On Sat, Jan 15, 2011 at 7:21 AM, Carl Eastlund <cce at ccs.neu.edu> wrote:
> On Sat, Jan 15, 2011 at 6:53 AM, Robby Findler
> <robby at eecs.northwestern.edu> wrote:
>> On Fri, Jan 14, 2011 at 9:13 PM, Carl Eastlund <cce at ccs.neu.edu> wrote:
>>>> I think that most of the time that you re-provide something you really
>>>> wanted to put the same contract on it, so it seems like we should make
>>>> that easy.
>>>
>>> On the other hand, that means the number of requires and provides can
>>> seriously impact a program's performance if a function has a
>>> computationally intensive contract.  I don't think we really want to
>>> put hidden "gotchas" into the module system.
>>
>> The contract system should be able to be smart enough to avoid putting
>> the redundant contracts on. After all, they are eq? to each other
>> (altho I agree some care will have to be taken to make sure this
>> happens).
>
> I don't think that's possible in general.  For instance, the listof
> contract has to traverse the entire list, recursively applying the
> element contract to each part.  There's no way to avoid rewrapping
> there.  Granted, providing a list of functions is not common, but any
> contract can be implemented that way.  The whole contract need not be
> preserved after the projection has been applied.  Our contract system
> is too flexible to make hard guarantees about the effects of applying
> the same contract twice.

If the contract is a first-order contract then we cannot do it (altho
a listof functions will only check the listof part twice), yes. But I
think we can deal with this problem if we decide to go this route.

>>> Also, I occasionally make use of the fact that re-provides are
>>> considered "the same binding" by the module system.  So if A exports
>>> X, and B re-exports that X, C can require both A and B.  The duplicate
>>> import of X doesn't cause an error because it's the same X.  Changing
>>> module exports is a little bit easier because of this -- for instance,
>>> more than once I have used this property to keep (planet cce/scheme)
>>> compatible with changes to the core that added overlapping bindings.
>>> Adding a new contract means you suddenly have a different binding,
>>> which can be less convenient.
>>
>> Wait a sec: I don't see how 'the same binding' can be on the table for
>> one option and not the other? It seems like 'the same binding' in the
>> current world can do two different things (specifically either include
>> the 'via' message or not when there is an error).
>>
>> I tried this out with racket/load and the bindings were the same, but
>> there was no via message. Maybe that is just part of the bug we're
>> dealing with, tho?
>
> I'm not talking about "via" messages in contract errors.  I'm talking
> about syntax errors.  The following program compiles and runs:
>
> #lang racket/load
> (module A racket (define x 5) (provide x))
> (module B racket (require 'A) (provide x))
> (module C racket (require 'A) (require 'B))
>
> But this program does not:
>
> #lang racket/load
> (module A racket (define x 5) (provide/contract [x any/c]))
> (module B racket (require 'A) (provide/contract [x any/c]))
> (module C racket (require 'A) (require 'B))
>
> The resulting error message:
>
> module: identifier already imported from a different source in:
>  x
>  (quote B)
>  (quote A)


Oh I wasn't thinking carefully. Sorry about that.

Robby


Posted on the dev mailing list.