Uh oh!
There was an error while loading. Please reload this page.
Allow empty structs with braces. - #147
Conversation
bstrie
commented
Jun 30, 2014
What is the advantage of saying |
mahkoh
commented
Jun 30, 2014
@bstrie: You currently have to write structX;structY{y:int}And you cannot write structX{}I think this is very annoying. I agree that you might want to keep the version with the |
sinistersnare
commented
Jun 30, 2014
+1 Whenever i see
I definitely like the second better. But am fine with both in the end I guess. |
sfackler
commented
Jun 30, 2014
+1 The current behavior is pretty weird. When I'm working on something, I'll frequently start out with an empty struct and add fields as I need them. |
lilyball
commented
Jun 30, 2014
👎 we explicitly removed the ability to say I also see no benefit to |
mahkoh
commented
Jun 30, 2014
@kballard: Can you link to the discussion where you decided to disallow |
nrc
commented
Jun 30, 2014
+1 to this proposal, I found this weird when I was learning Rust. @kballard to clarify, you mean the values are indistinguishable at runtime? Two different, empty, struct values of different types (say |
lilyball
commented
Jun 30, 2014
@mahkoh Where I decided it? I didn't decide it. And I don't have the link offhand, but I encourage you to Obviously without a citation I don't have proof, but my recollection is that |
lilyball
commented
Jun 30, 2014
@nick29581 Two values of type |
mahkoh
commented
Jun 30, 2014
By "you" I meant to group of people you referred to here:
Isn't it this issue? rust-lang/rust#5167 |
emberian
commented
Jun 30, 2014
That is only struct literals in expression position. There was never an ambiguity with items. |
bstrie
commented
Jul 1, 2014
I'm a bit confused by this proposal. Let's talk about struct literals first. I would find it very strange to see anyone prefer this: let x = Foo{};...over this: let x = Foo;As though Rust code isn't noisy enough! In the interest of having Only One Way To Do It, we forbade the useless brackets on struct literals a long time ago. This used to be a syntax ambiguity, true, but that was just galvanizing the existing urge to "bless" the form that everyone was using anyway. Finally, in an effort to further simplify, we then forced the declaration of field-less structs to adopt the same form, by forbidding empty brackets. This was not motivated by ambiguity at all, just consistency. However, this latter restriction is definitely capable of raising eyebrows when paired with the empty trait definitions, empty impl blocks, and empty functions, all of which just use empty brackets. I would ask the author to please clarify what is being proposed here. Do you want to allow the brackets in declarations, and also forbid the bracket-less form? As a separate concern, do you want to allow the brackets in literals, and also forbid the bracket-less form? |
liigo
commented
Jul 1, 2014
+1 for
|
gsingh93
commented
Jul 1, 2014
+1. @bstrie I definitely prefer the first. As soon as I see it, I know we're initializing a struct with no members. I've associated the |
bstrie
commented
Jul 1, 2014
@gsingh93, your perception appears to be mistaken. It is impossible to initialize a struct with no members, because a struct with no members has zero size at runtime. It is an illusion, it does not exist! |
gsingh93
commented
Jul 1, 2014
@bstrie It's an illusion that makes things easier to read. Not having |
lilyball
commented
Jul 1, 2014
@gsingh93 What do you mean, more familiar? With a nullary struct definition In fact, I can't think of any way in which structFoo;is different than enumFoo{Foo}and yet nobody is clamoring for enum values to require |
gsingh93
commented
Jul 1, 2014
@kballard You have a point, but if I define something as a struct, I would like to use it with the same syntax as I use for other structs. That includes structs that have no members and structs that have some members. I don't care about the size of the struct or what the compiler considers the struct to be. To me, the programmer, I declared a struct. Thus, I would like to use struct syntax. |
gsingh93
commented
Jul 1, 2014
Does it actually matter whether the programmer thinks there is some sort of initialization or construction going on here? If not, then I'm fine with sending the message that there is (even if that is false) and having the consistent |
lilyball
commented
Jul 1, 2014
@gsingh93 But Similarly, if you turn on the Your insistence on thinking of FWIW, |
nrc
commented
Jul 1, 2014
@kballard The RFC is proposing One could also argue for In the end, the choice here comes down to trading off consistency - either you want a struct with 0 fields to be consistent with a struct with n fields where n > 0 (and also consistent with C/C++) or you want consistency with enum variants. You've expressed your opinion on which kind of consistency you prefer and @gsingh93 and others have expressed a different opinion, I don't think either opinion is more correct than the other. @bstrie (and @mahkoh) my understanding of the RFC (which should be clarified in the RFC itself) is that both the declaration and the literal forms should use |
nrc
commented
Jul 1, 2014
And a clarification, if regular structs were the only data structure in Rust, then I think this RFC would be a clear win for consistency. However, they aren't, and we want consistency with tuple-structs and enum variants. We also strive to only have one way to express a concept in Rust code, which seems to preclude having both ways, so we have to make a choice of which kind of consistency is most important. My personal thought is that the common case here is structs with n fields and we should try to be consistent between n=0 and n>0. But I can see the point of view, that reducing the number of ways to do something or reducing noise or having consistency with enum variants (which are semantically equivalent) is more important. |
bstrie
commented
Jul 1, 2014
The consistency argument is a wash. Either way you're going to be inconsistent with something. In light of that, I prefer the form that will result in less noise. -1 to this. |
glaebhoerl
commented
Jul 1, 2014
I was going to say the same thing @bstrie said. |
mahkoh
commented
Jul 1, 2014
I'm mostly interested in the point mentioned by @sfackler above: Being able to write Consider a math library which contains operators and points with up to 3 coordinates. traitBinaryOperator{fnapply(&self,a:int,b:int) -> int;}structPlus;implBinaryOperatorforPlus{fnapply(&self,a:int,b:int) -> int{
a + b
}}traitPoint{}structPoint0D();structPoint1D(f64);structPoint2D(f64,f64);structPoint3D(f64,f64,f64);implPoint3D{fnproject(self,n:uint) -> Box<Point>{letPoint3D(x, y, _) = self;match n {0 => box Point0D()asBox<Point>,1 => box Point1D(x)asBox<Point>,2 => box Point2D(x, y)asBox<Point>,
_ => box selfasBox<Point>,}}}
I do agree that "instantiation-should-follow-declaration", that is, structs declared |
glaebhoerl
commented
Jul 1, 2014
If the idea is not to force empty structs to be declared and used with |
bstrie
commented
Jul 1, 2014
I am opposed to TIMTOWTDI. Adding in new syntaxes for the same operation can be done backward-compatibly later. |
lilyball
commented
Jul 1, 2014
That sounds very confusing. 3 different types of unit structs? And you have to remember which variant of unit struct it was in order to initialize it? |
mahkoh
commented
Jul 1, 2014
Not more confusing than having to remember the names of the fields of non-empty structs. |
sinistersnare
commented
Jul 1, 2014
Oh i get it, we can not currently do structFoo{}obviously, it just wooshed over me, i was blindly thinking instantiation only. OK i understand your position more. I still think that allowing |
mahkoh
commented
Jul 1, 2014
@cmr: You are denying that "instantiation-should-follow-declaration" played a role in the decision to disallow |
emberian
commented
Jul 1, 2014
Consistency was the only consideration. On Tue, Jul 1, 2014 at 1:10 PM, mahkoh notifications@github.com wrote:
|
mahkoh
commented
Jul 1, 2014
@cmr: That issue doesn't even talk about forbidding
On the same day @sfackler comments:
When was this forbidden? For what reasons was ; chosen over { }? The issue sheds no light on these questions. The comment is followed up by:
So unless this was done on the very same day, this issue, if not completely unrelated to the removal of Indeed, on September 19th @alexcrichton writes
It appears to me that @alexcrichton realized that the choice ; over { } was driven by wanting one consistent way to declare and instantiate structs and the ambiguity. |
pnkfelix
commented
Jul 2, 2014
One advantage of making the zero-field struct syntax consistent with the non-zero one (for both the struct item as well as the construction expression forms) is that A concrete example: #![feature(macro_rules)]macro_rules! twos {( $S:ident $($x: ident),*) => { $S { $( $x:2i ),*}}}#[deriving(Show)]structA{x:int,y:int}#[deriving(Show)]structB;pubfnmain(){let a = twos!(A x, y);// The below does not work, since it expands into illegal syntax `B { }`.// let b = twos!(B);println!("Hello World: {}", a);}(caveat: the above example is an easy strawman to tear apart; i.e. "why would you ever write So, if we care about that (I know I do; not sure about other people), then we should consider making the change proposed here. |
glaebhoerl
commented
Jul 2, 2014
@pnkfelix That's a reasonable justification, but I wouldn't want to force the noisier syntax on all "normal" code just to make macros work better. I'd be fine with having it optional, kind of like trailing commas. Also, couldn't you construct a similar example for tuple structs? |
lilyball
commented
Jul 2, 2014
@pnkfelix Macros can handle the case anyway, by using #![feature(macro_rules)]macro_rules! twos {( $S:ident $($x: ident),+ ) => { $S { $( $x:2i ),*}};( $S:ident ) => { $S };}#[deriving(Show)]structA{x:int,y:int}#[deriving(Show)]structB;pubfnmain(){let a = twos!(A x, y);// The below works just finelet b = twos!(B);println!("Hello World: {}", a);println!("It works: {}", b);} |
pnkfelix
commented
Jul 2, 2014
@kballard that sort of workaround is what I meant when I said "without special case code" in my summary. But yes, that is a way to get around the problem, and maybe it is acceptable to macro developers. |
pnkfelix
commented
Jul 3, 2014
@glaebhoerl I suppose one could construct a similar argument for tuple structs ... for some reason I differentiate between unit and tuples, so that in my head zero-tuples just do not exist, and thus I find it easier to accept that likewise zero-tuple structs do not exist, and thus a macro that expands into a tuple struct is simply going to need to take >= 1 argument. But that is really just roundabout post-hoc justification for my position above. |
pnkfelix
commented
Jul 3, 2014
(and in fact, I just remembered a case where I do mentally equate unit and zero-tuples, so just ignore what I said above.) |
o11c
commented
Jul 4, 2014
I would like to only use |
lilyball
commented
Jul 4, 2014
Note that an opaque struct is one where the only way you can use it is via a pointer. This is why any type with values is not an opaque struct, as you can use those values directly. The only way we have to express a type with no inhabiting values is to use an enum with no variants, e.g. |
pnkfelix
commented
Aug 4, 2014
By the way, with regards to @sfackler 's point that:
my current approach to dealing with this is to write such prototype structs this way: structFoo{_dummy_placeholder:()}This way it is super-clear that I intend to put more fields in later, that this code is just still under-development. So I am not super-convinced that the "let me write braces so I have a place to put things later" holds all that much water. |
nikomatsakis
commented
Aug 4, 2014
@mahkoh can you collect what you view as the best arguments from this thread and update the rfc? |
rkjnsn
commented
Aug 5, 2014
+1 for allowing braces on both declarations and literals. |
mahkoh
commented
Aug 5, 2014
updated |
lilyball
commented
Aug 5, 2014
Well that's certainly not true. You're providing an extremely biased view here. |
liigo
commented
Aug 6, 2014
What's that if any? None Well that's certainly not true. You're providing an extremely biased view here. —Reply to this email directly or view it on GitHub. |
lilyball
commented
Aug 6, 2014
@liigo There has been a lot of discussion in this PR on this topic. |
pnkfelix
commented
Aug 6, 2014
This RFC is not all that well fleshed out to begin with.
The above observations lead me to believe that this particular RFC is not going to yield a usable document for people to refer back to in the future. If we accepted such a document, it would represent a failure in the RFC process, regardless of how the core team may feel about the spirit of this suggested change. The core team was already going to close this RFC (see meeting minutes). I just wanted to write down explicitly that I would argue in favor of closing this particular RFC pull request based on the observations above. |
There was a problem hiding this comment.
I am guessing that this is meant to denote "There Is Only One Way To Do It." (But in that case, why is it in the "Unresolved Questions" section rather than "Drawbacks" section? And really, the point needs to be explicitly elaborated.)
Acronyms like this are appropriate for SMS messages and twitter; not for a documents like this, especially since some of the core team members did not know what this meant (and I didn't figure out a guess for it until well after seeing their conversation).
mahkoh
commented
Aug 6, 2014
@kballard: I read @nikomatsakis request so that I should provide the best arguments for the change, not against. If it's not going to be accepted then that it doesn't matter anyway. It's nothing more than bikeshedding and @pnkfelix: People used such acronyms in this thread and nobody complained about them.
Because the RFC say "Allow {}", not "Allow only {}". |
huonw
commented
Aug 6, 2014
The actual RFC text needs to be more formal and more detailed than just general discussion. |
pnkfelix
commented
Aug 6, 2014
I do not attempt to go through and edit everyone's comments in the dialogue on an RFC; where the expectation is that one has read the preceding dialogue before a given comment (and thus an ad-hoc acronym can at least be understandable). But I cannot afford to take that attitude on an RFC, where the document is meant to live on independently from the comment thread here.
The expansion of "TIOOWTDI" into "There is only one way to do it" is not a question. (It is also not a drawback, unless you apply a healthy amount of context to one's interpretation, which is what I was trying to do when I wrote my comment above.) I do not know your background, in terms of whether english is your native language, etc, so please do not take offense at the following bullet points. I just want to set the record straight in terms of what sorts of phrases are actually sensible for each part of an RFC:
|
mahkoh
commented
Aug 6, 2014
Please don't waste more time on this bikeshedding. |
liigo
commented
Aug 7, 2014
You are right. But why we have two ways now? On function call, we allow empty-parenthesis: |
huonw
commented
Aug 7, 2014
@liigo this whole RFC is about changing the empty struct declaration syntax, and is now closed (without being merged), i.e. please read the RFC and rest of the discussion. (Also, note that @pnkfelix was just rephrasing text as an example of how an RFC should be written, not adding any new content about the proposed changes.)
@pnkfelix was trying to constructively offer assistance on what an RFC should include and how it should be written (since it is designed to be a reference document for posterity); not wasting time on bikeshedding. |
Tweak weakmap template.
No description provided.