Sunday, January 4, 2009

Type constraints for method parameters (and return values)

As an add on to type constraints for instance variables (see last post) we think about adding them to method parameters and maybe even method return values. The hard part here is not the implementation but rather to find a nice syntax to declare these constraints. Here are a couple examples of possible definitions for typed method signatures:
    Class("TypedMethodParas", {
methods: {
typed1: [
[Joose.Type.Int, Joose.Type.Date],
function (int, date) {
// ...
}
],

typed2: {
takes: [Joose.Type.Int, Joose.Type.Date],
does: function (int, date) {
// ...
},
returns: Joose.Type.Int
},

typed3: Method(Joose.Type.Int, Joose.Type.Date, function (int, date) {
//
},
Joose.Type.Int)
}
})

Which one do you like best? Do you have better ideas? Is this feature even worthwhile?

Go to Comments

15 comments:

Anonymous said...

I have kind of an evil idea: How about a form of hugarian notation where types are inferred from parameter names and than automatically type checked like. I would use $ as a kind of namespace separator:

function (myVar$int) {}

The system would infer from the $int that this parameter muss be of type Joose.Type.Int. Problem is that you would have to use the long name throughout the procedure.

Anonymous said...

Via twitter from MerlinDE:
1st one is most intuitive - I think, 2nd has overhead, 3rd moves type info far away from method params

fansipans said...

#2, or #1

The logic behind #1 could be "Method definitions can either be a function or an array with a function, object, and array, interpreted as method, return type, and arguments, respectively:

methodName: [
[ Joose.Type.ArgType ],
Joose.Type.ReturnType,
function() { ... }
]

#3 is the worst of both #1 and #2 with the benefits of neither: You get needless verbosity combined with semantics hidden in syntax.

Nickolay said...

How about this syntax?

function (p1,p2) {
...
}.signature(Joose.Type.Int, Joose.Type.Date)

here the "signature" is a function added to Function prototype

I tried this approach with my try on overloading: http://extjs-ux.org/docs/?class=Function

From one side its less "visual", coz the types are in the end of function's definition, but more "atomic" - types are tied to function itself.

Malte said...

@Nickolay
I really like that idea!!!
I would wrap the function in a function call though, so that we dont have to extend Function.prototype (because we dont do that :)

Thanks!

Nickolay said...

he-he, its just more "sugar" this way )

Malte said...

How about this:

Method(function (Int, count, My$Type, foo, My$Joose$Role, bar) {

})

The actual function would receive only the paras count, foo and bar. $ is used as an alternative namespace separator. The good thing about this is that the type definitions are close to the actual paras.
Bad things:
- Implementation would rely on Function.prototype.toSource
- The $ is not really intuitive

fansipans said...

One of the nice things about #1 and #2 is that they're backwards-compatible with the current syntax - are you thinking of not supporting the current syntax?

I really love the simplicity of the current syntax.

Getting into things like:

Method(function (Int, count, My$Type, foo, My$Joose$Role, bar)

seems pretty non-intuitive to me, and is much harder to glance at and know what's going on.

If we were in perl and you could say:

Method(function( count => Int, foo => My.Type, bar => My.Role)) that wouldn't be *so* bad.

I'm of the opinion that the Joose configuration syntax should be made for humans, with usability and intuitiveness the first priorities. However they're stored or represented internally, or how "atomic" the elements of the definition are, seem irrelevant to me.

Malte said...

I dont want to replace the current syntax.

It would still be
methods: {
foo: Method(function () {})
}

There is no Method-function yet. I'm just looking for the most intuitive way to defined name parameters and types. I think it is very important that types and names are defined together, so that they dont diverge accidentily.

The goal is to create an internal DSL that makes the task as usable as possible. Abusing any feature of portable JavaScript would be fine.

Nickolay said...

Is Function.prototype.toSource supported by IE?

Malte said...

It should be safe in all half-way modern browsers (even IE6). If I remember right there used to be problems in Opera. But those are fixed now.

Malte said...

Two more ideas:

Alternative 1:
Matching types to paras using names. Relies on toSource.
http://nopaste.planerd.net/1806

Alternative 2:
Use a "varargs" Method-function that takes n-Types and the actual function as parameters. Does not rely on toSource (But could be used to check para count).
http://nopaste.planerd.net/1805

Nickolay said...

I'll abstain here, still just for comparison:
http://nopaste.planerd.net/1807

Malte said...

@Nickolay: I liked the postfix signature method as first because it is pretty. I think that the distance from the actual parameter definition is to far to make this usable in real world code.

Nickolay said...

Yes - its a drawback.. though other variants gives some extra "brackets verbosity" - drawback also.. May be create a set of samples and then make a poll here + on #catalyst and #moose, possible #jemplate?