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

Make tuple structs just constructors, not functions as well. #10216

Closed
pythonesque opened this issue Nov 1, 2013 · 4 comments
Closed

Make tuple structs just constructors, not functions as well. #10216

pythonesque opened this issue Nov 1, 2013 · 4 comments

Comments

@pythonesque
Copy link
Contributor

Since as @alexcrichton pointed out this is a different bug from #10200, I'll file this one, though I think that issue is a good illustration of why tuple structs can't "just" be functions.

I think this would resolve a bunch of issues, especially if we use a different syntax (namely: Foo {x,y} instead of Foo (x,y)). Then nobody, including the reader of the program and the compiler, would think Foo was an ordinary function, though we usually get away with this because the convention is to not give functions uppercase names. Based on what I've seen and heard the fact that tuple structs are functions is minimally used right now, so the weak version of this (not changing the syntax, but just making tuple structs not functions) would probably not break a whole lot of code, and every such instance can be easily converted to a closure.

Pedagogically, it is strange to have an item that creates both a type and a value (which is what struct Foo(x, y) is doing--it creates a new type Foo, and also a new value Foo of type (x, y) -> Foo). And as @cmr pointed out, when we create a regular struct we can't call it like a function--why can we do the same with tuple structs?

@nikomatsakis
Copy link
Contributor

There is a certain clarity to this idea, it can be confusing how some types also introduce values. But it'd involve changing quite a bit of code, and I'm not sure I'd actually like using the end result better. Also, for nullary variants like None you'd have to (presumably) write None {}? It seems like one of the main end results from this change would be a deriving mode to create the functions-and-statics we make automatically today.

The major downside seems to be that in patterns you would just have to write None {} and Some {}, presumably. Maybe if you defined a static for None you could write None (I forget if we allow static constants in patterns yet) but it'd bypass the exhaustiveness checker unless we made some pretty ad-hoc rules.

I've also thought about going the other way: making a constructor function for regular structs, because it seems like it'd frequently be handy -- and in particular I often wish I could write something like Point(x, y) in matches where I now have to write Point {x: ..., y: ...}.

In the end, I'm probably not motivated to do either change, particularly due to the effects on patterns.

@pythonesque
Copy link
Contributor Author

I think nullary variants can remain constants, since they are pure values anyway, subject to generics (though I do agree that pedagogically None {} would be nicer, but I think there's a limited amount of damage you can do with constants from a readability perspective :)--also, in enums, you never have the value-and-type problem in the first place). SML/NJ, which goes to the other extreme you mention (though that's more a product of how their functions work than anything else) still lets you write constants without any parameters.

As far as parameters in matches go, do you feel that Some{} is harder to read than Some()? They are an identical number of keystrokes. We already do it for record matching so maybe we need to fix record matching to use parentheses too, if that's the case. Additionally (while I'm not sure if I like this) we could allow patterns arguments to appear with no curly braces for variants that accept zero or one anonymous argument--I don't think it would conflict with syntax, in context it's always identifiable, and based on my experiences elsewhere it's quite readable (None | Some x rather than Some {x} | None {}, unless you like being exhaustive). We could also just special case nullary arguments and it would effectively turn into what we have today.

As far as the work goes, I'd be willing to put in the work if I was pretty sure it was actually going to get accepted :)

@nikomatsakis
Copy link
Contributor

I don't see how nullary variants can remain constants -- then they still infect the value space. If the goal of this proposal is to make a clean separation then you must have a sol'n for nullary variants. TBH, making nullary variants not be constants would be helpful in some respects, there is a bug or two related to their current "dual status" where they act as sort-of-rvalues-sort-of-lvalues, but it's definitely a usability setback. (I've in the past argued for None() on similar grounds but been shot down, probably rightly so)

I don't feel that Some {v} is necessarily harder to read than Some(v) -- it's just different from the patterns I know and love from e.g. ML (typical conventions would put an extra space before the {, but we could not do that). It is true that today the distinguish between "field" patterns and "positional" patterns is recognized in the parser, and hence Foo {f} is expanded to Foo {f:f} but that's resolvable.

@pythonesque
Copy link
Contributor Author

Yeah... maybe you're right that we can't get away with special-casing nullary values (though I still think it is justifiable in the context of a pattern match simply because it's unambiguous what you mean there). Sounds like you've been down this road before, so I'll defer to your judgment here :)

flip1995 pushed a commit to flip1995/rust that referenced this issue Jan 27, 2023
Fix spelling inconsistence of `mdBook`

I was reading both [mdBook Documentation](https://rust-lang.github.io/mdBook/) and  [The Clippy Book](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/book.html#the-clippy-book) and felt that it's easier to read to unify the notation of `mdBook`.

- \[ ] Followed [lint naming conventions][lint_naming]
- \[ ] Added passing UI tests (including committed `.stderr` file)
- \[x] `cargo test` passes locally
- \[ ] Executed `cargo dev update_lints`
- \[ ] Added lint documentation
- \[x] Run `cargo dev fmt`

----

changelog: none
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants