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) {

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

Go to 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

Mike 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 ],
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.

Samurai Jack 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:

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.

Unknown said...

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 :)


Samurai Jack said...

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

Unknown 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

Mike 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.

Unknown 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.

Samurai Jack said...

Is Function.prototype.toSource supported by IE?

Unknown 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.

Unknown said...

Two more ideas:

Alternative 1:
Matching types to paras using names. Relies on toSource.

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).

Samurai Jack said...

I'll abstain here, still just for comparison:

Unknown 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.

Samurai Jack 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?