Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAllow empty structs with braces. #147
Conversation
This comment has been minimized.
This comment has been minimized.
|
What is the advantage of saying |
This comment has been minimized.
This comment has been minimized.
|
@bstrie: You currently have to write struct X;
struct Y {
y: int
}And you cannot write struct X {
}I think this is very annoying. I agree that you might want to keep the version with the |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
|
+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. |
This comment has been minimized.
This comment has been minimized.
|
I also see no benefit to |
This comment has been minimized.
This comment has been minimized.
|
@kballard: Can you link to the discussion where you decided to disallow |
This comment has been minimized.
This comment has been minimized.
|
+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 |
This comment has been minimized.
This comment has been minimized.
|
@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 |
This comment has been minimized.
This comment has been minimized.
|
@nick29581 Two values of type |
This comment has been minimized.
This comment has been minimized.
By "you" I meant to group of people you referred to here:
Isn't it this issue? rust-lang/rust#5167 |
This comment has been minimized.
This comment has been minimized.
|
That is only struct literals in expression position. There was never an ambiguity with items. |
This comment has been minimized.
This comment has been minimized.
|
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? |
This comment has been minimized.
This comment has been minimized.
|
+1 for
|
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
|
@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! |
This comment has been minimized.
This comment has been minimized.
gsingh93
commented
Jul 1, 2014
|
@bstrie It's an illusion that makes things easier to read. Not having |
This comment has been minimized.
This comment has been minimized.
|
@gsingh93 What do you mean, more familiar? With a nullary struct definition In fact, I can't think of any way in which struct Foo;is different than enum Foo {
Foo
}and yet nobody is clamoring for enum values to require |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
|
@gsingh93 But Similarly, if you turn on the Your insistence on thinking of FWIW, |
This comment has been minimized.
This comment has been minimized.
|
@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 |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
I was going to say the same thing @bstrie said. |
This comment has been minimized.
This comment has been minimized.
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. trait BinaryOperator {
fn apply(&self, a: int, b: int) -> int;
}
struct Plus;
impl BinaryOperator for Plus {
fn apply(&self, a: int, b: int) -> int {
a + b
}
}
trait Point { }
struct Point0D();
struct Point1D(f64);
struct Point2D(f64, f64);
struct Point3D(f64, f64, f64);
impl Point3D {
fn project(self, n: uint) -> Box<Point> {
let Point3D(x, y, _) = self;
match n {
0 => box Point0D() as Box<Point>,
1 => box Point1D(x) as Box<Point>,
2 => box Point2D(x, y) as Box<Point>,
_ => box self as Box<Point>,
}
}
}
I do agree that "instantiation-should-follow-declaration", that is, structs declared |
This comment has been minimized.
This comment has been minimized.
|
If the idea is not to force empty structs to be declared and used with |
This comment has been minimized.
This comment has been minimized.
|
I am opposed to TIMTOWTDI. Adding in new syntaxes for the same operation can be done backward-compatibly later. |
This comment has been minimized.
This comment has been minimized.
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? |
This comment has been minimized.
This comment has been minimized.
Not more confusing than having to remember the names of the fields of non-empty structs. |
This comment has been minimized.
This comment has been minimized.
|
@cmr: You are denying that "instantiation-should-follow-declaration" played a role in the decision to disallow |
This comment has been minimized.
This comment has been minimized.
|
Consistency was the only consideration. On Tue, Jul 1, 2014 at 1:10 PM, mahkoh notifications@github.com wrote:
|
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
|
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)] struct A { x: int, y: int }
#[deriving(Show)] struct B;
pub fn main() {
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. |
This comment has been minimized.
This comment has been minimized.
|
@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? |
This comment has been minimized.
This comment has been minimized.
|
@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)] struct A { x: int, y: int }
#[deriving(Show)] struct B;
pub fn main() {
let a = twos!(A x, y);
// The below works just fine
let b = twos!(B);
println!("Hello World: {}", a);
println!("It works: {}", b);
} |
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
|
(and in fact, I just remembered a case where I do mentally equate unit and zero-tuples, so just ignore what I said above.) |
This comment has been minimized.
This comment has been minimized.
|
I would like to only use |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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: struct Foo {
_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. |
This comment has been minimized.
This comment has been minimized.
|
@mahkoh can you collect what you view as the best arguments from this thread and update the rfc? |
This comment has been minimized.
This comment has been minimized.
|
+1 for allowing braces on both declarations and literals. |
This comment has been minimized.
This comment has been minimized.
|
updated |
This comment has been minimized.
This comment has been minimized.
Well that's certainly not true. You're providing an extremely biased view here. |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
@liigo There has been a lot of discussion in this PR on this topic. |
This comment has been minimized.
This comment has been minimized.
|
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. |
pnkfelix
reviewed
Aug 6, 2014
|
|
||
| # Unresolved questions | ||
|
|
||
| TIOOWTDI (with a majority in favor) |
This comment has been minimized.
This comment has been minimized.
pnkfelix
Aug 6, 2014
Member
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).
This comment has been minimized.
This comment has been minimized.
|
@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 {}". |
mahkoh
closed this
Aug 6, 2014
This comment has been minimized.
This comment has been minimized.
The actual RFC text needs to be more formal and more detailed than just general discussion. |
This comment has been minimized.
This comment has been minimized.
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:
|
This comment has been minimized.
This comment has been minimized.
|
Please don't waste more time on this bikeshedding. |
This comment has been minimized.
This comment has been minimized.
You are right. But why we have two ways now? On function call, we allow empty-parenthesis: |
This comment has been minimized.
This comment has been minimized.
|
@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. |
mahkoh commentedJun 30, 2014
No description provided.