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

Unified syntax for function call with captured variables #10458

Closed
1 task done
iacore opened this issue Dec 30, 2021 · 6 comments
Closed
1 task done

Unified syntax for function call with captured variables #10458

iacore opened this issue Dec 30, 2021 · 6 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.

Comments

@iacore
Copy link
Contributor

iacore commented Dec 30, 2021

Please do not file a proposal to change the language

  • I understand, thank you. But this is still a language change proposal. Sorry.
@iacore iacore added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Dec 30, 2021
@iacore
Copy link
Contributor Author

iacore commented Dec 30, 2021

The current syntax calling function on a struct with its instance as first variable is very weird.

Current "method call" usage:

const V = struct {
    i: i32,
    u: i32,

    pub fn foo(this: *@This()) void {
        this.i = 5;
    }
};
pub fn main() !void {
    var v = V{.i=42, .u=35};
    const a = v.foo;
    a();
}

What's the type of a? v.foo() here is syntax sugar for @TypeOf(v).foo(v), and I don't feel good about this.

Also, there is the issue of name shadowing:

const V = struct {
    i: i32,
    foo: i32,

    pub fn foo(this: *@This()) void {
        this.i = 5;
    }
};

pub fn main() !void {
    var v = V{.i=42, .foo=35};
    const a = V.foo; // v.foo will reference its field without compile-time warning or error
    a(&v);
}

This was mentioned in #6966 (comment).

@SpexGuy
Copy link
Contributor

SpexGuy commented Dec 30, 2021

const a = v.foo; is a compile error in stage 2, as is @TypeOf(v.foo). We are removing bound functions from the language.

@iacore
Copy link
Contributor Author

iacore commented Dec 30, 2021

Lua's solution for this is simple: v:foo() has v as foo's first argument, and v.foo() do not. I'd like to see a new syntax sugar for creating bound function and bound function call. This will enable my comments on #4170 about syntax-enabled refactoring.

What I propose is related to "anonymous function" in #4170. Why don't we have syntax sugar for creating anonymous "bound" functions?

Current syntax:

v.foo();

Desugared current syntax:

@TypeOf(v).foo(v);

Proposed desugared syntax:

std.xxx.partial(@TypeOf(v).foo, .{v})();

partial here acts the same as the one in Python. It can be implemented with current language features.

Proposed sugared syntax:

(.{v} .| @TypeOf(v).foo)();

.| like the pipe operator, except it only compose the function without calling it.

Proposed syntax (special case for "bound method" call):

v.|.foo();

OK, .|. maybe too hard to type, but it can be something simpler.

Proposed syntax for restrictive anonymous block:

.{v} .| {
// this block only have access to `v`
}

Proposed syntax for arbitrary bound function:

const boundf: fn () void = .{v} .| fn (v: V) void {};

@iacore
Copy link
Contributor Author

iacore commented Dec 30, 2021

@SpexGuy then what is the syntax for calling function in namespace of a type with a term of that type as the first variable? Still v.foo()? I don't like this edge case.

@mrakh
Copy link
Contributor

mrakh commented Dec 30, 2021

@SpexGuy then what is the syntax for calling function in namespace of a type with a term of that type as the first variable? Still v.foo()? I don't like this edge case.

You can manually and explicitly construct the closure by creating a struct that contains the instance variable and function pointer. Then invoking it would just be my_closure.closure_fn(my_closure.closure_param, …)

@iacore
Copy link
Contributor Author

iacore commented Dec 30, 2021

@SpexGuy then what is the syntax for calling function in namespace of a type with a term of that type as the first variable? Still v.foo()? I don't like this edge case.

You can manually and explicitly construct the closure by creating a struct that contains the instance variable and function pointer. Then invoking it would just be my_closure.closure_fn(my_closure.closure_param, …)

That's too much text to enter on keyboard just to create a new function (if I don't need a closure) that only has access to memory where it's defined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

4 participants