One of the next big issues needing to be addressed is the syntax for [[function pointers|function and method pointers]]. The syntax I’m thinking of is close to that used in C and C++ (see e.g. here and here). My initial idea results in something like this:
define MyComparator as { int compareTo(MyRecord,MyRecord) }
This is defining a record type, MyComparator
, which contains a single field, compareTo
. This field is, of course, a function pointer accept two MyRecord
‘s and returning an int
. We can invoke it like so:
int f(MyComparator comp, MyRecord r1, MyRecord r2): return comp.compareTo(r1,r2)
Similarly, we can “take the address” of a function using the &
operator like so:
int comp(MyRecord r1, MyRecord r2): ... return 1 // positive case void System::main([string] args): r1 = ... r2 = ... x = f(&comp,r1,r2)
At this point, the syntax seems a little inconsistent. I’m using &
from C/C++, but not requring a *
and/or allowing ->
. Following C/C++ syntax properly would require something like this:
define MyComparator as { int (*compareTo)(MyRecord,MyRecord) } int f(MyComparator comp, MyRecord r1, MyRecord r2): return *(comp.compareTo)(r1,r2)
To me, this is ugly and unnecessary. On the other hand, perhaps I should consider dropping the &
so everything is consistent. E.g. by permitting this
void System::main([string] args): r1 = ... r2 = ... x = f(comp,r1,r2)
This could work, for sure … But, somehow I’m not a great fan.
Processes
Processes and methods present their own problem. Consider this example:
define Writer as process { int Writer::write([byte] bytes) }
This declares a process type, Writer
, which has one field, write
. In this case, write
is a method pointer, as indicated by the ::
in the above. It seems redundant to require Writer::write
, but it’s necessary since write
could be a method pointer to some other kind of process. This can be slightly improved by allowing a short-hand like this:
define Writer as process { int ::write([byte] bytes) }
And, in fact, I want to go further a permit this equivalent short-hand notation:
process Writer { int ::write([byte] bytes) }
But, somehow, this doesn’t sit quite right for me. I suppose I need to ponder some other options …
Of course, JavaScript (among others) doesn’t use an & for getting the “address” of a function.
Heh. We’ve been looking at this for Grace, and looking at what Scala does.
Functional languages (and C) have a simple rule:
the naked function name => the value of the function
name() or name(…, ) => calls function
OO languages (say C++) could do the same thing.
BUT if you want the same syntax for message sends and variable accesses –
then you need to use just a name to call the function (or read a variable).
So then you need something like “&” to get the function as a value.
Scala writes “m _” – part of its gratuitous overloading of underscore
(what ever did it do to merit such abuse). We may write something like
“fn m” – or (like Smalltalk) just require people to write out the lambda
explicitly. Smalltalk’s keyword syntax helps here – it’s not clear how
something like & would work. Requiring an explicit lambda also resolves
issues about the “receiver” in OO terms: the difference, say, between
more traditional anonymous functions and C# delegates…
OK back to reading students work
btw – calling ’em “function pointers” – really…
Hey James!
Yeah, it’s a good point you make about having identical syntax for variable accesses and message sends. So far, I think I’d given up on trying to do that, but I do think it is a really neat idea!
Not sure what you meant here: “it’s not clear how
something like & would work”
And, yeah, again you’re right about the term “function pointers” … it’s a bit misleading shall we say …
Hmmmm, decisions decisions ….
Hmm, so it turns out that that only works if you’re statically typed (I think).
We wll have to work out what we do…