ballerina-platform / ballerina-lang

The Ballerina Programming Language
https://ballerina.io/
Apache License 2.0
3.68k stars 752 forks source link

[Bug]: Compilation Error when Providing Arrow Function to `array.sort` Method #42838

Open ThisaruGuruge opened 5 months ago

ThisaruGuruge commented 5 months ago

Description

Consider the following code:

import ballerina/lang.array;
import ballerina/io;

type Foo record {|
    string s;
    int i;
|};

public function main() returns error? {
    Foo[] fooArray = getFooArray();
    fooArray = fooArray.sort(array:ASCENDING, f => f.i);
    io:println(fooArray);
}

isolated function getFooArray() returns Foo[] {
    return [{s: "hello", i: 1}, {s: "world", i: 2}, {s: "foo", i: 3}];
}

This works without an issue. But one downside of this code is that the user needs to import the lang.array package, just for the arrays:ASCENDING constant, which is the default value for the direction parameter in the sort API. So, we can try to remove that parameter by using named parameters, like below:

import ballerina/io;

type Foo record {|
    string s;
    int i;
|};

public function main() returns error? {
    Foo[] fooArray = getFooArray();
    fooArray = fooArray.sort(key = (f => f.i));
    io:println(fooArray);
}

isolated function getFooArray() returns Foo[] {
    return [{s: "hello", i: 1}, {s: "world", i: 2}, {s: "foo", i: 3}];
}

Despite being the only difference here is that we removed the direction parameter (which is anyway the default value), and passed the key parameter as a named parameter. But in this case, the code throws a compilation error:

invalid operation: type 'ballerina/lang.array:0.0.0:Type' does not support field access

I have tried multiple ways to solve this, but the only way this works is when I provide the full function definition here, like below:

    fooArray = fooArray.sort(key = isolated function(Foo f) returns int {
        return f.i;
    });

Even inferring the isolation property does not work here, i.e., the function must have the isolated keyword, otherwise it wouldn't work.

Steps to Reproduce

No response

Affected Version(s)

No response

OS, DB, other environment details and versions

No response

Related area

-> Compilation

Related issue(s) (optional)

No response

Suggested label(s) (optional)

No response

Suggested assignee(s) (optional)

No response

ravinperera00 commented 3 months ago

Hi, I noticed that we can use the string values "ascending" and "descending" instead of importing the ballerina/lang.array library just to use the constants. For example,

import ballerina/io;

type Foo record {|
    string s;
    int i;
|};

public function main() returns error? {
    Foo[] fooArray = getFooArray();
    fooArray = fooArray.sort("ascending", f => f.i);
    io:println(fooArray);
}

isolated function getFooArray() returns Foo[] {
    return [{s: "hello", i: 1}, {s: "world", i: 2}, {s: "foo", i: 3}];
}

The above code runs as expected. I'm not sure whether this is the expected behaviour or whether this is also a bug. Also, this does not address the issue of named parameters, but hope this helps.