Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support For The rust Package #2431

Open
mcmah309 opened this issue Dec 2, 2024 · 6 comments
Open

Add Support For The rust Package #2431

mcmah309 opened this issue Dec 2, 2024 · 6 comments
Labels
awaiting Waiting for responses, PR, further discussions, upstream release, etc enhancement New feature or request

Comments

@mcmah309
Copy link
Contributor

mcmah309 commented Dec 2, 2024

rust implements many of Rust's types in Dart. It would be nice if a return type of Result in Rust generated a Result in Dart. Possibly for Option as well, since Option is just an extension type of T?. Path is also just an extension type of String, opening the door for supporting returning Path. Note that there is also the anyhow package built off rust as well. Meaning anyhow::Result can also be supported.

@mcmah309 mcmah309 added the enhancement New feature or request label Dec 2, 2024
@fzyzcjy
Copy link
Owner

fzyzcjy commented Dec 2, 2024

Looks interesting! I am not very sure whether e.g. Option<T> vs T? which is better though, so I may not personally have enough time to add support for this. However, feel free to PR! I guess we can add some feature to allow users to customize the generated types, and then the rust package can be easily integrated by doing simple configurations.

@fzyzcjy fzyzcjy added the awaiting Waiting for responses, PR, further discussions, upstream release, etc label Dec 2, 2024
@mcmah309
Copy link
Contributor Author

mcmah309 commented Dec 2, 2024

Yeah supporting Option<T> may not be worth it, but since Option<T> is just and extension type of T?, all the current null logic can be kept. All that would be needed is to change the return type to Option<T> and add add a zero cost wrapper Option.from(nullable).

@fzyzcjy
Copy link
Owner

fzyzcjy commented Dec 3, 2024

all the current null logic can be kept

T? is quite convenient for e.g.

int? a = f();
if (a==null) return;
print(a); // now a is `int`, not `int?` and can be used

So I wonder whether Option will still allow this?

@mcmah309
Copy link
Contributor Author

mcmah309 commented Dec 3, 2024

all the current null logic can be kept

I was referring more towards the logic in this package used to generate Dart code.

But for your example, with Option<T> you'd have to do

Option<T> aOpt = f();
int a;
switch(aOpt) {
    Some(:final v)
        a = v;
    default:
        return;
}
print(a);

Which is less desirable and this drawback is outline in the docs https://mcmah309.github.io/rust/libs/option/option.html#drawbacks

Luckily Option<T> can be converted to T? at zero cost due to extension-type type eraser at compile time.

int? a = f().value; // `f` returns an `Option<T>`
if (a==null) return;
print(a); // now a is `int`, not `int?` and can be used

The main advantage of Option is chaining operations and early return https://mcmah309.github.io/rust/libs/option/option.html#early-return-key-notation

@fzyzcjy
Copy link
Owner

fzyzcjy commented Dec 3, 2024

I see, thanks for the explanation! Then some brainstorms:

  • what about directly adding some extension methods to the T?. For example, map can be done like that.
  • what about making a normal function for the early return thing. for example,
int? intNone() => null;
double? earlyReturn(int val) => functionThatSupportsEarlyReturn(($) { // Early Return Key
  // Returns here
  double x = intNone()[$].toDouble();
  return val + x;
});
expect(earlyReturn(2), None);

T? functionThatSupportsEarlyReturn<T>(callback) { ... }
extension<T> on T? {
  operator[]() { ... }
}

Btw curious how is [$] implemented - if it is done by throw and catch then I am a bit worried about performance...

@mcmah309
Copy link
Contributor Author

mcmah309 commented Dec 3, 2024

  • It's possible, but unfortunately you can't add null specific extensions, so any extension on type T? also applies to T. You could define another extension on T to override it, but you can't get ride of it. Also you will have conflicts, e.g. map on type T? would conflict with other types map implementation like List<T>/List<T>? - map would be Iterable<T> map<T>(T toElement(E e)).
  • I like the idea! I believe that would be possible with nullable types. Might be worth looking into. Maybe - nullEarlyReturn(($) {}) or just earlyReturn(($) {}).

It is try catch, but no StackTraces, so performace really depends on darts implementation. Theoretically the Dart compiler could compile throw in a similar way to Rust Result. I haven't seen any performance issues with it. And as Err is usually rare, for most cases even if throw was costly, it shouldn't be an issue. (Explanation of how it works here mcmah309/rust#3 (comment))

But using early return is also completely up to the developer. You are never forced into it. I use it sometimes because, as you can imagine, it greatly reduces the need for map/mapErr, switch statements, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting Waiting for responses, PR, further discussions, upstream release, etc enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants