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

Same introducer for anonymous vs. nominal types? #653

Closed
josh11b opened this issue Jul 14, 2021 · 4 comments
Closed

Same introducer for anonymous vs. nominal types? #653

josh11b opened this issue Jul 14, 2021 · 4 comments
Labels
leads question A question for the leads team

Comments

@josh11b
Copy link
Contributor

josh11b commented Jul 14, 2021

Context for this question is the struct proposal #561 .

We expect nominal types to support a number of features: methods, interface implementations, next pointers, etc. The anonymous type syntax is instead designed to only support data fields (with possible defaults) so they can be very concise and declared inline in contexts like a return type. The question is, is it better to use the same introducer to emphasize "these are all examples of record types and I don't want to say 'or' all the time when talking about them" or better to use different introducers so that the different syntax is less surprising?

As a concrete example, here is what we are currently looking at anonymous types like this:

fn GetPoint() -> struct {.x: Int, .y: Int};

and nominal types like:

struct Point {
  var x: Int;
  var y: Int;
}
fn GetPoint() -> Point;

where the compiler knows which to syntax to use based on whether the word struct is followed by an identifier or an {.

Note that there is some interaction with question-for-leads issue #651 , but I've tried to frame this as an independent question.

@zygoloid
Copy link
Contributor

zygoloid commented Jul 21, 2021

Per #651 (comment), I think that using a different name ("struct" vs "class") for simple anonymous structure types versus for full-fledged named structure types would be useful, though that doesn't directly answer the syntactic question of what introducer to use.

#561 mentions that we could do without an introducer for anonymous struct types, and I think this is an option we should consider a bit more. I think this could be OK:

  • {} is both an empty struct literal and an empty struct type, just like ()
  • {.a: b} is a type
  • {.a = b} is a struct literal
  • {.a: b = c} is a type (with a default value for field .a)

This would be problematic if we wanted to also use the same syntax {.a: b = c} as a way of writing a struct literal with an explicitly specified type for the field .a, but that doesn't seem to be part of the structs proposal for now at least. (I think we could still make that work if we wanted, by saying that you can use such a value as either a struct literal or as a struct type, sort-of mirroring how (Int) can be used as either a tuple value or as a tuple type, but that might be surprising in practice.)

I would prefer either a struct introducer or no introducer over a class introducer; I'd like to see more analysis of the no-introducer option before forming an opinion on whether I'd prefer a struct or no introducer.

@chandlerc
Copy link
Contributor

This would be problematic if we wanted to also use the same syntax {.a: b = c} as a way of writing a struct literal with an explicitly specified type for the field .a, but that doesn't seem to be part of the structs proposal for now at least.

I wouldn't find the syntax {.a: b = c} desirable for achieving that effect though... I think we already have syntax for that construct which I prefer: {.a = c as b}

@josh11b
Copy link
Contributor Author

josh11b commented Jul 30, 2021

Based on discussions yesterday, I think I heard that we were converging on ​the "no introducer" for anonymous struct types approach described in @zygoloid 's last comment.

  • This creates a consistency: introducers are used when introducing new names, this doesn't introduce a new name so it doesn't have an introducer.
  • It avoids having a different introducer for things that are still treated as classes for many purposes.
  • We don't think the parsing difficulties will be too bad.
  • We do want to use these type expressions in contexts that will benefit from being more concise.
  • It is consistent with our approach to tuples and tuple types.

For both this and tuples, we are taking a risky approach as an experiment with the understanding that it may not work out, but if it does, we are happier.

@zygoloid
Copy link
Contributor

zygoloid commented Jul 31, 2021

Decision: As per @josh11b's most recent comment: structural data class types ("struct types" for short) have no introducer. {.x: T, .y: U} is a struct type, and {.x = 5, .y = 7} is a struct value. Just like () (and ((), ()), etc), {} is both a value and the type of that value (and by extension, so are ((), {}) etc).

There is a risk of future parsing problems here: we will want to avoid the syntax of a field initializer from ever overlapping with the syntax of a field declaration. But that doesn't seem like a significant problem given the information we currently have.

[Edit 2021-08-06: changed struct type syntax from {x: T, y: U} to {.x: T, .y: U}.]

josh11b added a commit that referenced this issue Aug 9, 2021
…ork (#561)

This proposal defines the very basics of `class` types, primarily focused on:

-   use cases including: data classes, encapsulated types, inheritance with and without `virtual`, interfaces as base classes, and mixins for code reuse;
-   anonymous data types for called _structural data classes_ or _struct types_. Struct literals are used to initialize class values and ad-hoc parameter and return types with named components; and
-   future work, including the provisional syntax already in use for features that have not been decided.

The intent is to both make some small incremental progress and get agreement on direction. As such it doesn't include things like nominal types, methods, access control, inheritance, etc.

It proposes this struct type and literal syntax:
```
var p: {.x: Int, .y: Int} = {.x = 0, .y = 1};
```
Note that it uses commas (`,`) between fields instead of semicolons (`;`), and no introducer for types or literal values.

Incorporates decisions from #665 , #653 , #651


Co-authored-by: Geoff Romer <[email protected]>
Co-authored-by: Chandler Carruth <[email protected]>
zygoloid added a commit that referenced this issue Aug 28, 2021
… (#699)

This supports both struct type literals, `{.x: i32, .y: i32}`, and struct
value literals, `{.x = 3, .y = 4}`. The degenerate case of `{}` is
treated as a struct value literal, with the expectation that an empty
struct value has the same type/value duality as an empty tuple value.
chandlerc added a commit that referenced this issue Jun 28, 2022
…ork (#561)

This proposal defines the very basics of `class` types, primarily focused on:

-   use cases including: data classes, encapsulated types, inheritance with and without `virtual`, interfaces as base classes, and mixins for code reuse;
-   anonymous data types for called _structural data classes_ or _struct types_. Struct literals are used to initialize class values and ad-hoc parameter and return types with named components; and
-   future work, including the provisional syntax already in use for features that have not been decided.

The intent is to both make some small incremental progress and get agreement on direction. As such it doesn't include things like nominal types, methods, access control, inheritance, etc.

It proposes this struct type and literal syntax:
```
var p: {.x: Int, .y: Int} = {.x = 0, .y = 1};
```
Note that it uses commas (`,`) between fields instead of semicolons (`;`), and no introducer for types or literal values.

Incorporates decisions from #665 , #653 , #651


Co-authored-by: Geoff Romer <[email protected]>
Co-authored-by: Chandler Carruth <[email protected]>
chandlerc pushed a commit that referenced this issue Jun 28, 2022
… (#699)

This supports both struct type literals, `{.x: i32, .y: i32}`, and struct
value literals, `{.x = 3, .y = 4}`. The degenerate case of `{}` is
treated as a struct value literal, with the expectation that an empty
struct value has the same type/value duality as an empty tuple value.
@jonmeow jonmeow added the leads question A question for the leads team label Aug 10, 2022
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

4 participants