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

Named Arguments in Callable Invocation #16

Closed
ozra opened this issue Feb 21, 2016 · 5 comments
Closed

Named Arguments in Callable Invocation #16

ozra opened this issue Feb 21, 2016 · 5 comments

Comments

@ozra
Copy link
Owner

ozra commented Feb 21, 2016

Named Arguments in Callable Invocation

Alternatives

1: Current: Use Tag-literal to denote arg-name assignment. foo #named-arg = 47, #other-arg = "Ok!", same with parenthesis: foo(#named-arg = 47, #other-arg = "Ok!")

Shining light on the complications requiring some thought as to syntax:

foo(x = 47, y = 42, color = 0xffaa00) ->
   say "x = {x}, y = {y}, color = {color}"

foo 100, #color = 0xff0000
foo #color = tmp = 0x00ff00   -- Set a named arg, and assign a variable(!)
if v = some-obj.foo           -- assign variable in condition
   foo 100, v, 0xcccccc

2: Use = with the names without Tag-literal notation, require a more explicit notation for assigning variables in the contexts of args of calls, say :=. This would not be a "first assign" designator - just means: "assign is actually intended in this context". In the case of when "explicit first assigns" is demanded, it could perhaps double for that role in these contexts - so that you don't have to whip out something like my-call(and-assign ':= 47).

For this case, the assignment syntax should also apply to control structures like if, which also would make things a bit clearer (especially since it's a common pattern in Onyx because of Nil-elimination branching.

foo(x = 47, y = 42, color = 0xffaa00) ->
   say "x = {x}, y = {y}, color = {color}"

foo 100, color = 0xff0000
foo color = tmp := 0x00ff00   -- Set a named arg, and assign a variable
if v := some-obj.foo          -- assign variable in condition
   foo 100, v, 0xcccccc

3: Use colons, like in map notation. This however clashes with "python-style" nesting control symbol :. So, requires a core syntax overhaul: if some-foo x: 13, y: 56, verify: true then do-shit. The then here could have been a : which mess things up, unless using parentheses call, which would be an inconsistent requirement.

@ozra ozra added the RFC label Feb 21, 2016
@ozra ozra changed the title [RFC] Named Arguments in Callable Invocation Named Arguments in Callable Invocation Feb 21, 2016
@stugol
Copy link
Contributor

stugol commented Feb 21, 2016

I see no problem with the first alternative. Further, I think it's important to be able to designate one or more function parameters that must be keyword-invoked. I suggest # be used in the definition for this purpose:

the-function(a, #b, #c = nil) ->

the-function                -- error, no value for #b
the-function 1, 2           -- error, #b must be assigned by name
the-function 1, #b=2        -- no problem
the-function 1, #b=2, #c=3  -- no problem

I assume a ? suffix on function parameter types is implemented?

the-function(a Int?, #b Int?) ->

the-function        -- a is nil, #b is nil
the-function 1      -- a is 1, #b is nil
the-function #b=2   -- a is nil, #b is 2
the-function 1, 2   -- error, #b must be assigned by name

@ozra
Copy link
Owner Author

ozra commented Feb 24, 2016

  1. I totally agree on the ability to force named parameters per need - in "very high" safety situations this is a very strong guarantee.

  2. Yes, the "maybe-nil-sugar" is a given.

  3. Just because param a is Int|Nil doesn't mean you're allowed to omit that arg. If you want it to be nil by default and thereby allow omission, you have to state it the-function(a Int? = nil, #b Int? = nil) -> (assuming the proposed syntax)

@stugol
Copy link
Contributor

stugol commented Feb 24, 2016

  1. Awesome.
  2. Good.
  3. Agreed.

@ozra
Copy link
Owner Author

ozra commented Mar 27, 2016

After some months of using, I'm not satisfied with the named-arg syntax. The tag literal is... disturbing. Tags should stick to be values and not double as arg-identifiers - it was a bad call plain and simple!

Number (3) in the issue-OP - same as Crystal, is clearly to prefer.

The colon shaves one space (in "natural lang style syntax"), and one further by ditching the Tag-prefix, thereby also making the arg-name cleaner (primary importance). Two spaces sounds micro-optish, but given 4 args, that's 8 chars, and that's 10% of avail width if sticking to 80 col (which is good still to this day!)

The reason for trying to find an alternative is that : is a control character - it signifies the beginning of an expression-block (python-style). The reason was however moot. Just because you can write unclear code with that doesn't mean we should make all other code unclear (with the "Tag signifies named arg"-syntax).

Example:

foo(x = 47, y = 42, color = 0xffaa00) ->
   say "x = {x}, y = {y}, color = {color}"
   x is 47

-- let's get warmed up

foo 100, color: 0xff0000
foo x: 1, y: 2, color: tmp = 0x00ff00   -- Set a named arg, and assign a variable

-- the following line was the culprit leading to the sorry decision:

if foo x: 47, y: 13: say "looks confusing, but of course it's parseable!"

-- and some better ways of writing it, take your pick:

if foo(x: 47, y: 13) : say "better way of putting it!"

if foo x: 47, y: 13
   say "better way too"

if foo x: 47, y: 13 => say "also better choice"

if foo x: 47, y: 13 then say "actually, anything's better!"

This is already implemented as of today (breaking change).

Important Note

Space after the name: is mandatory!
my-call name: value

If you omit the space - it's a different construct: shorthand-subscript with string as key:

name:value == name["value"]
name:value? == name["value"]?

-- also, as a kind little reminder:
name#value == name[#value]
name#value? == name[#value]?

-- and:
name.1 == name[1]
name.1? == name[1]?

A small price to pay, and a big fat deluxe shorthand notation to gain.

The name:key syntax is up to debate too - and if changed, colon doesn't have to be mandatory - but having a space after the name: is much better style anyway imo.

@stugol
Copy link
Contributor

stugol commented Mar 27, 2016

Personally I don't see the problem with #, but the new way looks alright.

@ozra ozra closed this as completed Mar 27, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants