How dynamic do you want your dynamic language to be?

Started by
3 comments, last by Wyrframe 19 years, 1 month ago
Suppose you have the following piece of code in an arbitrary language X:

plus(1, 2);
This code calls a function "plus" with parameters 1 and 2, which adds the two parameters and returns a result (3). If the language has dynamic properties and lets you write code like this:

plus(a, b) = { return a + b; }
you have two options when compiling the code. The first one is to use a static symbol table and resolve a symbol "plus" like any other language would: simply look for a prior definition of "plus" and use that. The second option is to do a runtime lookup into a symbol table to find out what the value of symbol "plus" is at the point of execution. This has a benefit of being able to redefine symbols at runtime but with an obvious downside: every time a symbol is encountered a runtime lookup must be performed. Assuming we're not dealing with extraordinary JITting technologies that will go back and rewire all calls to "plus" every time "plus" is modified at runtime, which method would you prefer? Why? I'm currently in the process of making a decision and I'd like to see some discussion on the topic.
Advertisement
Well, depends, as long as the language ends up in a semi compiled state, then doing a runtime lookup wouldn't be all that costly, and would add a very interesting to play with feature. Although, I doubt I would be redefining plus :P

So, I would guess that my vote is for the later.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

I think it should do both, depending on when it's appropriate. Perhaps specifiying it like you specify a virtual function, indicating that the actual function is to be determined at run-time. Or perhaps, having default to static as long as so situation is setup where it's impossible, then do it run-time. Although the latter method is much more difficult, if not impossible, and probably prone to side-effects. Personally, I think the language should always let the programmer decide.
[s] [/s]
I can see the fnords.
Quote:Original post by DudeMiester
I think it should do both, depending on when it's appropriate. Perhaps specifiying it like you specify a virtual function, indicating that the actual function is to be determined at run-time. Or perhaps, having default to static as long as so situation is setup where it's impossible, then do it run-time. Although the latter method is much more difficult, if not impossible, and probably prone to side-effects. Personally, I think the language should always let the programmer decide.
why not default to having mutable functions, and declare immutable functions as const? That way it's pretty much all treated from a conceptual standpoint as if functions are function pointers, so it's just that const functions have pointers that can't be changed to point to a new function. Doing it this way means that the table lookup just has to be an associative container of symbol/function pointer pairs. A function call is really a lookup with the symbol into the table and then a call, and you could even have a second call mechanism to deal with const functions (and possibly caching lookups).

Washu: wouldn't the speed of a lookup be even less of a problem if the language wasn't compiled at all? (since the VM's speed is going to be reduced heaps anyway)

[Edited by - lucky_monkey on March 9, 2005 12:47:21 AM]
Well, let me put it this way. Ever since learning Caml, I've found it quite annoying to write in any language that didn't have closures (never mind that it has a positively beautiful standard library).

Sure, you could implement a lookup table that lets you remap global function names to specific calls. In C, it would not be that hard. But it would be very lightly troublesome because of typecasting issues. A macro could be constructed, however, to half-wrap this.

// Generic function typetypedef void (*TBENT)( void );typedef char *FNNAME;// Implement a name->TBENT map of some sort.void   setFunction( FNNAME, TBENT );TBENT  getFunction( FNNAME );// Define a "foo"int foo_0 ( int a, float b ) {    return (int)( (float)(a * a) / b );}// Register "foo"setFunction("foo", foo_0);// To call a function "foo" which takes an int and a float, returns an int...int myRet0 = (int (*)(int, float))getFunction("foo")(9, 18);// myRet0 is now 4int foo_1 ( int a, float b ) {    return a * (int)b;}// Register "foo"setFunction("foo", foo_0);// Call again.int myRet1 = (int (*)(int, float))getFunction("foo")(9, 18);// myRet1 is now 162.


Now, would you want to? Not really, for any purpose other than virtual machines, interactive-parsed languages, and scripting. There are cleaner solutions for everything else.
RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.

This topic is closed to new replies.

Advertisement