move-language / move

Apache License 2.0
2.25k stars 679 forks source link

[Feature Request] Support Pythonic parameter hints #965

Open alnoki opened 1 year ago

alnoki commented 1 year ago

@wrwg @chen-robert @davidiw @movekevin @PaulFidika

Presently Move does not allow parameter hints in function calls, which is not a problem for straightforward invocations:

...
let sum = add_integers(integer_1, integer_2);
...

More complex function calls, however, can be confusing without sufficient context, and developers may have to refer to the original function definition signature to "cognitively prepare" during code review:

...
let (result_1, result_2) = a_complex_function(
    a_struct_ref_mut,
    a_struct_ref,
    4,
    b"indexing",
);
...

Hence it is proposed that Move support (optional) Pythonic parameter hints (AKA keyword arguments in Python) of the following form:

...
let (result_1, result_2) = a_complex_function(
    to_mutate = a_struct_ref_mut,
    to_read = a_struct_ref,
    iterations = 4,
    operation_description = b"indexing",
);
...

Type hints would also be helpful:

...
let (result_1: u64, result_2: address) = a_complex_function(
    to_mutate: &mut CustomStruct = a_struct_ref_mut,
    to_read: &CustomStruct = a_struct_ref,
    iterations: u8 = 4,
    operation_description: vector<u8> = b"indexing",
);
...

Here, the compiler should throw an error if type or parameter hints do not match the original function signature definition.

wrwg commented 1 year ago

One initial thought: there is nothing "optional" in a good programming language. In a good language and framework, its clear to everybody that this is the way how you do it.

Let us say we define a linter for Move. Now we would have the option to name parameters. What would be the rules for the linter?

alnoki commented 1 year ago

One initial thought: there is nothing "optional" in a good programming language. In a good language and framework, its clear to everybody that this is the way how you do it.

Let us say we define a linter for Move. Now we would have the option to name parameters. What would be the rules for the linter?

@wrwg as for rules, I would start with the following:

  1. If an argument has a parameter hint, then all arguments after it must also have parameter hints. This is an approximation of Python's positional/keyword argument schema, and encourages programmers to put the most easily inferred parameters first in their calls:

    do_something_complex(account, struct_to_mutate = &mut my_struct, convergence_iterations = 4);
  2. The same for type hints:

    let (result_1, result_2: address) = a_complex_function(
        a_struct_ref_mut,
        to_read = a_struct_ref,
        iterations: u8 = 4,
        operation_description: vector<u8> = b"indexing",
    );
PaulFidika commented 1 year ago

I think it's an interesting idea; I personally wouldn't ever use it, but I'm sure some Move developers would like it. Interestingly, function calls in Cadence work almost exactly like this:

https://developers.flow.com/cadence/language/functions

mkurnikov commented 1 year ago

Can't you just use the IDE for those? image

movekevin commented 1 year ago

I can attest that the CLION Move plugin is godly. Parameter name highlighting is one of the many amazing features!

alnoki commented 1 year ago

Can't you just use the IDE for those? image

This solution requires developers to use JetBrains software, correct?

sblackshear commented 1 year ago

I think named arguments would be very useful for writing safer and more readable code--have definitely seen cases where folks swap two u64 inputs in a function with a lot of parameters.

It would be cool to do this in a way that allows punning (which is very useful for writing concise packs and unpacks elsewhere in Move). I think OCaml's approach of using ~ prefixes to distinguish named arguments from non-named ones is a nice syntactic trick https://v2.ocaml.org/manual/lablexamples.html