fusionlanguage / fut

Fusion programming language. Transpiling to C, C++, C#, D, Java, JavaScript, Python, Swift, TypeScript and OpenCL C.
https://fusion-lang.org
GNU General Public License v3.0
1.75k stars 55 forks source link

Allow delegates / anonymous functions #144

Open caesay opened 7 months ago

caesay commented 7 months ago

I'm not suggesting that Fusion should support people writing anonymous / delegate functions in Fusion, but that our generated code allows people to provide delegates.

It's a very common library practice to provide a method which takes a delegate for user logic: void doAthing(Action<string> onComplete)

Since Fusion is already very similar to C#, supporting the the Action<T1, T2, T3, ..> and Func<T1, T2, T3, ..., TResult> would be both easily understandable and very powerful. This would allow some kind of basic async library code to exist without proper async/promise support existing in Fusion.

This declaration can be very straightforwardly translated into the native delegate types for each language.

pfusik commented 7 months ago

This is a major language feature. Fusion used to have delegates in version zero.

A delegate is not only a code reference (function pointer), but also an object reference. In C# you can make delegates to both static and instance methods. How would you map that to C? How about references to abstract/virtual methods?

caesay commented 7 months ago

I don't know how we'd do it for C because I am not really a C programmer. However I think a lot of your questions don't matter for what I'm proposing.

My suggestion is that we will not allow delegates or lambda's in Fusion itself, but as a means for external code to pass in functionality. All we need to do in Fusion is:

The developer generating and passing in the delegate will be external code written in the native language. So for C, perhaps our Func<> translates to a raw function pointer, and a C developer trying to use this function will know that it must be to a static method only. We don't care about that, because Fusion does not allow writing delegates in Fusion.

The drawback to this approach is that you will not be able to call a Fusion method containing a delegate parameter in Fusion, because we can't instantiate the delegate ourselves. I think this is a small price to pay because it allows us to create more powerful API's that are designed to be called by the native language anyway.

Perhaps creating anonymous functions and calling delegates from within Fusion code could be implemented later as a separate feature?

pfusik commented 7 months ago

C developer trying to use this function will know that it must be to a static method only

That's a very painful restriction.

What you propose is very similar to what I already implemented in version zero. Delegates could be accepted from the outside, but not constructed in Fusion. The C translation was a struct with a function pointer and a void * for the data.

Java actually never had delegates, these are all just interfaces with one method. If Java can get away with no delegates, why not Fusion? Just define abstract methods and subclass in the target language. This works well for my own Fusion projects.

caesay commented 7 months ago

If the goal of Fusion is to provide a "native" library, such that it appears to have been written by an expert in said language, I don't think that's a fair requirement. I started out with abstract class/methods when writing my Fusion code, but when I got around to integrating it into sample apps in the native languages it just got totally out of control. So now I am using string replacement after the Fusion build in my build script to hackily support delegates as it provides a much cleaner API.

The restriction to not allow delegates to be created in Fusion (but can be accepted from outside) I think is a logical first step (hopefully with full delegate support coming later). We can use abstract/derived classes in our Fusion code internally, but our public API needs to be logical and easy to use.

I thought Java did support delegates (is that not what Function<T,Y> is?), but I guess if we are targeting a language that really does not support delegates then we can fall back to emitting a class with an abstract method only for those languages...

pfusik commented 7 months ago

To be clear, I'm not against delegates. I have limited resources and need to assign priorities to various tasks. In my Fusion code so far delegates did not feel that important. Yes, the goal is to have a feeling of native code, but not for one, but 10 different languages. What's your experience with these languages so I can better understand your point? I'd love to have a look at your code to understand the use cases for delegates.

caesay commented 7 months ago

I guess this is where it was added the first time https://github.com/fusionlanguage/fut/commit/a1ed6e12c9560ba9276b10bc4b5e9b3f56ab892e