Sign in to follow this  

How dynamic do you want your dynamic language to be?

This topic is 4664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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 type
typedef 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 4


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

Share this post


Link to post
Share on other sites

This topic is 4664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this