On 06/25/2012 09:27 PM, Stevie Strickland wrote:
On Jun 25, 2012, at 11:21 PM, Ryan Culpepper wrote:

On 06/25/2012 09:04 PM, Asumu Takikawa wrote:
On 2012-06-25 20:17:33 -0600, Ryan Culpepper wrote:
IIUC from your later message, you've implemented the generics
analogue of object/c (per-instance contract), whereas
prop:dict/contract is closer to class/c (per-type contract). It's a
little fuzzy because prop:dict/contract hacks in per-instance
contracts too in a kind of ad hoc way.

That's a good point. The better analogy might be interface contracts vs.
class/c. With generics, it is easy to control all points that an
instance is created since constructors are just procedures. With
classes, you can't get away with that since the instantiation forms are
macros.

The difference/advantage you might get with a per-type contract for
generics is that you get a more interface-like blame story, as with
interface contracts. Coverage isn't as much of an issue since you can
just contract all constructors.

Unfortunately, it's also not clear how to implement interface-like
contracts for generics. Since the generics forms don't control the
constructors, it's not obvious how to instantiate the blame at the
construction site.

You don't want to blame the construction site; the relevant party is the 
implementation site, where the generic interface is associated with concrete 
methods within a 'struct' form. See the docs for 'struct-type-property/c' for 
an example.

Well, there are two blame parties, right?

Much like interface contracts mediate between the creator of a class (that 
implements the interface) and the client of that class (that instantiates 
objects from that interface), I would think the contracts for a generic 
interface would be between the creator of a specific instance (the 
implementation site) and the user of that specific instance (the constructor 
site).

Stevie

The analogy to interface contracts doesn't help me, because I don't know anything about them. But I think I disagree.

(module GEN racket
  ....
  (define-generics has-prime
    (get-a-prime has-prime))
  (provide-generics-with-contract
    (has-prime [get-a-prime (-> has-prime? prime?)])))

(module IMPL racket
  ....
  (struct prime-box (val)
    #:methods gen:has-prime
    [(define (get-a-prime self) (prime-box-val self))])
  (provide (struct-out prime-box)))

(module CLIENT racket
  ....
  (define p (prime-box 4))
  (get-a-prime p)) ;; ERROR

I think IMPL should be blamed for violating the contract on gen:has-prime.

As I see it, GEN establishes an obligation on implementors of 'has-prime'. IMPL provides an implementation that turns out to be faulty; it doesn't live up to the obligation imposed by GEN. CLIENT is blameless; I don't see how the location of the constructor call has anything to do with it.

Ryan
_________________________
 Racket Developers list:
 http://lists.racket-lang.org/dev

Reply via email to