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

Optional argument names (unused arguments) #476

Closed
jonmeow opened this issue Apr 19, 2021 · 9 comments
Closed

Optional argument names (unused arguments) #476

jonmeow opened this issue Apr 19, 2021 · 9 comments
Labels
leads question A question for the leads team

Comments

@jonmeow
Copy link
Contributor

jonmeow commented Apr 19, 2021

For functions, should names be optional? If so, what is the syntax for that?

In C++, both of the following are allowed:

int Foo(int) { ... }
int Foo(int /*unused*/) { ... }

In Carbon, we're not doing /* comments, so that's out.

Things we discussed are:

Int _unused
Int [unused]
Int []
Int <>
Int <unused>

I've also suggested making unused a keyword, as in unused int i.

@geoffromer
Copy link
Contributor

Is there a reason to treat function parameter lists differently from other pattern-matching contexts in this respect? If not, it seems like the syntax should be Int _, as it is in other kinds of patterns.

@jonmeow
Copy link
Contributor Author

jonmeow commented Apr 20, 2021

Presumably function parameters have names in other contexts. For example, if you're implementing an interface with an API:

fn Sum(List(Int) x, Int size) -> Int;

And you have an implementation that doesn't use size, then seeing a standalone implementation like:

fn Sum(List(Int) x, Int _) -> Int;

May raise the question of what the unused parameter was.

@jonmeow
Copy link
Contributor Author

jonmeow commented Apr 20, 2021

In Google C++ style, the equivalent comment is:

Unused parameters that are obvious from context may be omitted:

class Foo {
 public:
  Foo(const Foo&) = delete;
  Foo& operator=(const Foo&) = delete;
};

Unused parameters that might not be obvious should comment out the variable name in the function definition:

class Shape {
 public:
  virtual void Rotate(double radians) = 0;
};

class Circle : public Shape {
 public:
  void Rotate(double radians) override;
};

void Circle::Rotate(double /*radians*/) {}

// Bad - if someone wants to implement later, it's not clear what the
// variable means.
void Circle::Rotate(double) {}

@chandlerc
Copy link
Contributor

My high-level thoughts here:

  • We should have some syntax for discarding a value in a pattern.
  • We should have some syntax for documenting the discarded value for function patterns if no-where else, but it seems reasonable for the syntax to be general and supported broadly.
  • Documenting the discarded value should be optional. I think there are cases even in functions where it adds no value, and so I am reluctant to require it.

I had originally been fond of just prefixing identifiers with _ and making those be discarded. It works and is general.

But I can see that being viewed as excessively clever.

I don't think this pattern is common enough to merit burning punctuation (already a precious commodity) in the lexical space except for _ which already is widely recognized as a discarding syntax for patterns.

I think the most promising structure then is: Type <sigil>[ <identifier>] where there is a sigil indicating a discarded name, and then an optional identifier that only servers as documentation. The <sigil> could be either a keyword or _.

So Int _ length or Int unused length where unused becomes a keyword.

I think I prefer _ for this. It gives us the unsurprising syntax in the common case for non-functions of discarding, but remains consistent with functions where we need to routinely include an identifier.

@jonmeow
Copy link
Contributor Author

jonmeow commented Apr 24, 2021

Assuming I understand correctly, we end up with:

  • Int length -- named
  • Int _ -- anonymous
  • Int _ length -- anonymous, with "length" identifier as comment

I think this offers a nice structure.

@jonmeow
Copy link
Contributor Author

jonmeow commented Apr 28, 2021

Noting here too, _ is being proposed as an indicator for arguments which cannot be specified by label (opt-out) on #478. Using _ for both argument label opt-out (mirroring Swift) and as an anonymous identifier could lead to confusion and syntax ambiguity.

@chandlerc
Copy link
Contributor

The leads chatted about the options presented here a while back and I wrote up the candidate resolution that I think we all were happy with, although to be honest it was some time ago so sorry if I've misremembered this.

Basically, we were actually pretty happy with just have distinct syntax between unused-but-named patterns vs. unnamed-and discarded patterns.

The result would be:

  • _: Int -> discarded (and unnamed)

  • For cases where we actually want to carefully preserve a name even though it is unused, we would use a separate and much more explicit syntax with a leading keyword for the name binding:

    fn OnClick(handle: UIElementHandle,
               unused coordinates: Point)
    

    Worth calling out that this unused would tightly bind to the name coordinates -- it couldn't be used to introduce any kind of sub-pattern.

What do folks think? Also, did I recall this right @KateGregory and @zygoloid?

@chandlerc
Copy link
Contributor

Not hearing any concerns, let's call this decided.

@jonmeow jonmeow added the leads question A question for the leads team label Aug 10, 2022
@jonmeow
Copy link
Contributor Author

jonmeow commented Aug 11, 2022

Filed #1996 to track the need for a proposal here, as part of switching to labels for leads question tracking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
leads question A question for the leads team
Projects
None yet
Development

No branches or pull requests

3 participants