On Jan 8, 2008 12:01 PM, SJS <[EMAIL PROTECTED]> wrote:
> I forget, do you allow for polymorphic methods, and would this
> have an effect?

I have virtual methods and method overloading by argument number and
type, like C# and Java. Methods are virtual by default.

> e.g.,
>
>    def addEntityName( entity )
>       require
>         entity responds to ( get name as String )
>       body
>         ...
>
>    def addEntityName( entity )
>       require
>         entity responds to ( get id as Integer )
>       body
>         ...

I don't expect to support overloading by contract, so no. To do this you would:

    def addEntity(entity)
        require
            entity responds to (get name as String) or entity responds
to (get id as int)
        body
            if entity responds to (get name as String)
                ...
            else
                ...

> If not, what's the benefit over
>
>   if ( entity responds to ( get name as String )) error()
>
> ?

Such an if statement would be in the body of the method (which does
not include the "require" part). I'm not expecting that the compiler
will ever analyze the body of a method to give error messages because
(a) that's not conceptually part of the interface to the method and
(b) since most methods end up being virtual in Cobra, it would be
invalid to give an error.

However, contracts *are* considered to be part of the interface of a
method and they are inherited as well. So if you invoke the method
like so:

    repository.addEntity(e)

And 'e' does not respond to (get name as String) then the compiler
should give you an error on that line:

error: Expression "e" violates "addEntity" requirement that "entity
responds to (get name as String)"

You normally would get this at run time, but it should be possible to
detect some contract violations at compile time and save you the wait
and some re-runs. (You'll never get a compile-time error if "e" is
type "dynamic" since all decisions about that type are delayed until
run-time where they either succeed or throw an exception.)

So that's what I was implying when I said:

> > At which point the compiler is empowered to give you some errors when
> > you violate the expectations of a method you're calling.

On a related note, the Spec# research team at Microsoft has a version
of C# with contracts and a compile-time analysis tool that detects
many kinds of contract violations. It's a pretty neat project. They
even separated out the analysis part into a backend so I may be able
to leverage that down the road in Cobra.

> It would be interesting to be able to generate the require block
> by running a tool on the code. Inspect the body, and add the necessary
> requirements to the require block, suitably marked as generated.

I agree. Would be a nice feature in an IDE. Right click on the
argument and choose something like "Generate require responds to" or
something.

> > You can do this to some extent with interfaces, but there are
> > drawbacks. Sometimes the above is much more convenient than creating a
> > new interface and then visiting a dozen classes in your project to
> > make them conform. Also, interfaces in complex projects can get silly
> > where they start to cover just one method like HasName,
> > HasComputeResults, HasFoo, HasBar, etc. And since you cannot specify
> > multiple interfaces for an argument, combination interfaces might then
> > be created.
>
> If you're using a "responds to" approach, can't you just have duplicate
> interfaces?
>
> e.g.,
>
> interface foo
>   void bar ( get name as String )
>
> interface qux
>   void bar ( get name as String )
>
> And something that would accept a "foo" would also accept a "qux"?

Well then message passing would have to use reflection to look up bar,
whereas accessing bar through the foo interface type is much faster in
.NET and I believe also in JVM. I'm not willing to stray too far from
C#/Java level performance as Python's lack of run-time performance and
GIL were bothersome to me.

> How about checking the value's range?
> Or would that make the syntax too strange?

The suggestion I've received for that, which I like, is to support "subtypes":

subtype Score
    inherits int

    invariant
        value >= 0 and value <= 100

    get letterGrade as String
        if value > 90
            return 'A'
        else if value > 80
            ...

Implementation-wise, Cobra would just spit out "int" where Score is
used since neither .NET nor JVM (afaik) support this idea. However,
the Cobra compiler would augment the code with the necessary checks
and allow invocation of the members like:

    g = someScore.letterGrade

which in C# would be something like:

    g = Score.letterGrade(someScore)

Additionally, there could be optional inlining and the ability to turn
invariant checks off at run-time or compile-time. This would make for
some nice, OO, contract-based code that could still be performant[1].

-Chuck


[1] Yeah I know it's not a word, but so wasn't "blog" at some point.
http://www.google.com/search?hl=en&q=performant

-- 
[email protected]
http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-lpsg

Reply via email to