Functional programming features

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

Recommended Posts

Angelscript looks great. Nice work! I was curious if there are any plans to add closures to Angelscript and to make functions first-class objects?

Share on other sites
Give me an example of how you would use this, please.

I know that Lua and other scripting languages have these features, but I'm not sure I'll do something like this in AngelScript. If you show me some examples that cannot be solved in another way, then perhaps I may reconsider these features.

One thing that I will add though is the possibility to use function pointers, so that callback functions can be implemented in AngelScript. I'm not sure when this will be done though.

Regards,
Andreas

Share on other sites
Quote:
 Original post by WitchLordGive me an example of how you would use this, please.I know that Lua and other scripting languages have these features, but I'm not sure I'll do something like this in AngelScript. If you show me some examples that cannot be solved in another way, then perhaps I may reconsider these features. One thing that I will add though is the possibility to use function pointers, so that callback functions can be implemented in AngelScript. I'm not sure when this will be done though.Regards,Andreas

I can't think of a single case where a function pointer can't eventually solve any problem that using a closure or a function object can. In fact function pointers are never really necessary either if you have classes, as one could simply define an interface and any callbacks are really just objects which implement that interface.

For example:

class IQsortCallback{    bool Invoke(int arg1, int arg2) = 0;}class MyCallback : IQsortCallback{    bool Invoke(int arg1, int arg2) { return arg1 > arg2; }}void qsort(List list, IQsortCallback callback) { ... }void myFunction(){    List list = { ... }    qsort(list, new MyCallback())    }

But that's so much more verbose than what could be accomplished when functions are first-class objects
void qsort(List, Function callback) { ... }void myFunction(){    List l = { ... }    Function callback = new Function(int arg1, int arg2) { return arg1 > arg2 }    qsort(list, callback);}

Share on other sites
I think this code:

List l = { ... }
Function callback = new Function(int arg1, int arg2) { return arg1 > arg2 }
qsort(list, callback);

Is awesome.

Share on other sites
I'm pleased that you showed how to solve the problem without functions as first-class objects or even function pointers. :)

Using a function pointer you would have something like this:

typedef bool qsort_callback(int arg1, int arg2);void qsort(List, qsort_callback callback) { ... }bool myCompare(int arg1, int arg2) { return arg1 > arg2; }void myFunction(){    List l = { ... }    qsort(l, myCompare);}

Potentially the function myCompare() could be allowed to be defined inside myFunction() which would improve the readability, but this would be a separate issue.

Thinking about it, there is really not much difference between using function pointers and functions as first-class objects.

For your example, function pointers is enough. Do you have other examples showing how closures or functions as first-class objects are better? I'm just looking for ideas to improve AngelScript, and while I know of closures and functions as first-class objects I do not have any experience with them, thus I do not know where they are needed.

Regards,
Andreas

Share on other sites
Are you being facetious ??? :D

Like I said, I don't think that there are any problems which a function pointer cannot solve that closures or first-class object functions could, but the first-class paradigm is much friendlier I think (to the programmer at least... probably not so much to you). I did not think however of the possibility of the typedef statement against a function. My C is pretty rusty, and never was really that great anyway. Using the typedef is pretty clean too.

At this point I'm having a hard time thinking of a practical reason why closures would be necessary. They're convenient since they share lexical scope with the function they're defined in, but the same effect can be had by passing the necessary variables by reference into a standard function.

Also if you allow a function to be defined within another, you almost have a closure. If a variable is used which isn't in its own locals table it tries to find it in the containing function's. I'm sure it's easier said than done though.

BTW: I love that generators are supported.

Share on other sites
facetious? That's a word I haven't seen before. ;)

The typedef is only necessary because AngelScript is a statically typed language and the compiler needs to be able to validate the types at compile time. Languages that are dynamically typed (e.g. Lua) doesn't need the typedef.

Actually, when I implement the function pointers, the functions in AngelScript may actually have to be treated a bit like first-class objects. Especially since it would be possible to store a function pointer in an external variable, and the function must be kept available for as long as the variable references it.

It would be theoretically possible for a script to dynamically implement a function by putting it in a string, and then ask the application to compile it and return its address. This would of course require the application to register functions to support it, but opens up for new possibilities. Self-modifying programs are cool. ;)

Regards,
Andreas

Share on other sites
Hi,
I personally would prefer the C-like function pointers. Since AngleScript is very C/C++ like I wouldn't mix it up with to many different scripting languages. Function pointers should do the job quite well.
I'm eagerly awaiting function pointer to use qsort in Angelscript :)

Just my 50 cent.

Bye,
Martin

Share on other sites
It's worth mentioning that, from the perspective of the C++ host code, an angelscript function is a first class object. I was able to get angelscript code calling other angelscript functions with the name of the function as a string variable. I have just the small gotcha of having to have to a specific return type. Had to pipe it through a C++ function that prepared a new context and performed the call.

Share on other sites
Quote:
 Original post by DeyjaIt's worth mentioning that, from the perspective of the C++ host code, an angelscript function is a first class object. I was able to get angelscript code calling other angelscript functions with the name of the function as a string variable. I have just the small gotcha of having to have to a specific return type. Had to pipe it through a C++ function that prepared a new context and performed the call.

Yeah, the return type would be the gotcha when it comes to functions as objects in angelscript. Since it's statically typed, you must specify a return type, but where do you do it? You could make it a parameter to the constructor I guess... but I don't like it. Angelscript function pointers FTW.

Share on other sites
yeah, even if i like function class objects, i don't think they will be in "scope" with the angelscript language. from a scripter point of view, that should help lazy coders that don't understand pointers math, but from my point would turn angelscript in something too similar to how ecmascript behave. the same thing can be achieved in a lot of ways, also with single inheritance:

// this could be even hidden to the script by registering// it on the c++ sideinterface SortClass{  bool compareBasic (int a, int b);}void qsort(List, SortClass sort) { ... }// now this is what u would write in the scriptclass MySort : SortClass{  bool compareBasic (int a, int b) { ... }}void myFunction(){    List l = { ... };    qsort(l, MySort());}

Share on other sites
Quote:
 Yeah, the return type would be the gotcha when it comes to functions as objects in angelscript.

I'm working on fixing that. The calling code will still have to receive the return value in an Any, but the called function should be able to return anything (except types declared in the script...)

Share on other sites
Why not specify the return type and all as you do in C++0x (the next version of C++, should be out in a year or two)?

#import <stdio>#import <function>#import <bind>using namespace std;int someFunc(float f):{	return (int)f;}int anotherFunc(float f):{	return (int)(f*2);}struct someStruct{	int i;	someStruct(void) {i=5;}	int structFunc(float f) { return (int)(f*i); }	int operator()(float f) { return (int)(f*(i+2)); }; }int outerStructFunc(someStruct *s, float f) { return (int)(f*(s->i)+1); }int main(int argc, char *argv[]){	function<int(float)> myFunc;	myFunc = &someFunc;	cout << myFunc(2.4) << endl; // prints "2\n"	myFunc = &anotherFunc;	cout << myFunc(2.4) << endl; // prints "4\n"	function<int(someStruct*,float)> sFunc;	someStruct s();	sFunc = &someStruct::structFunc;	cout << sFunc(&s,2.4) << endl; // prints "12\n"	sFunc = &outerStructFunc;	cout << sFunc(&s,2.4) << endl; // prints "14\n"	myFunc = s; // function object / functor	cout << myFunc(2.4) << endl; // prints "16\n"	myFunc = bind(&someStruct::structFunc, &s, _1);	cout << myFunc(2.4) << endl; // prints "12\n"}// can also typedef it an all as usualtypedef function<int(float)> myFunc_td;

etc...