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

Proposal for Syntaxes - Function return type and Generics #1691

Closed
dsriniv opened this issue Jul 25, 2022 · 12 comments
Closed

Proposal for Syntaxes - Function return type and Generics #1691

dsriniv opened this issue Jul 25, 2022 · 12 comments
Labels
leads question A question for the leads team

Comments

@dsriniv
Copy link

dsriniv commented Jul 25, 2022

Firstly I want to say the presentation at CPPNorth was outstanding. Great work guys.

I had a couple of suggestions - I am not sure how open you are to changing the syntax styling.

  1. The arrow for runType seems very PHP. I like the fact carbon derives inspiration from Typescript and Kotlin.

Current

fn functionName() -> SomeReturnType {
return SomeReturnType();
}

Proposed

// With colon just like typescript
fn functionName() : SomeReturnType {
return  SomeReturnType();
}

// or when single line.
fn functionName() = SomeReturnType();
  1. Square bracket for generics is not intuitive. Instead, could we use angle brackets (<T: SomeType>)? Square brackets are more intuitive for Arrays...
@emlai
Copy link

emlai commented Jul 25, 2022

The : return type syntax is a popular request, and has the majority of upvotes in #1520 (comment).
Given also that two existing successful successor languages (Kotlin and TypeScript) use it, there is considerable precedent.

The argument for -> is that function types look weird with the colon syntax: var func: (i32): i32, and so the arrow should be used in both places for consistency with var func: (i32) -> i32. But this is optimizing for the rarer case.
Return type annotations and variable/parameter type annotations are way more common than function types, so it would make sense to optimize for a consistent syntax for them.

@dsriniv
Copy link
Author

dsriniv commented Jul 25, 2022

@emlai - Thank you for the explanation. I upvoted the comment as well.

@geoffromer
Copy link
Contributor

We've been trying to avoid angle brackets because they create very serious parsing problems. For example, a correct C++ parser has to implement substantial parts of C++'s name lookup and type checking rules, because in order to parse x<y, it has to figure out whether x is a template, in order to decide whether the < is a less-than operator or an open angle bracket.

@WarEagle451
Copy link

WarEagle451 commented Jul 26, 2022

I like this, it's a lot cleaner and ':' is consistent with variable declarations

@dsriniv
Copy link
Author

dsriniv commented Jul 26, 2022

We've been trying to avoid angle brackets because they create very serious parsing problems. For example, a correct C++ parser has to implement substantial parts of C++'s name lookup and type checking rules, because in order to parse x<y, it has to figure out whether x is a template, in order to decide whether the < is a less-than operator or an open angle bracket.

That does make sense thank you for the explanation. Lexical parsing is a bit complicated. When working with golang, that was one of the things that threw me off. I am already starting to see based on the dislikes I got... there are more developers who don't like this idea.

The question is who is going to be your target users. People who come from typescript, kotlin, java, dart. Would want to use angle brackets whereas people who come from rust or go, might want to use square brackets. I'll leave it up to the discretion of the implementor.

@emlai
Copy link

emlai commented Jul 26, 2022

We've been trying to avoid angle brackets because they create very serious parsing problems. For example, a correct C++ parser has to implement substantial parts of C++'s name lookup and type checking rules, because in order to parse x<y, it has to figure out whether x is a template, in order to decide whether the < is a less-than operator or an open angle bracket.

Existing successful successor languages, TypeScript, Kotlin, and Swift (even Rust) all use <> for generics. Their design teams have considered the options carefully, and settled on <>. And they all handle it just fine. So calling it a very serious parsing problem is exaggeration. Also this is not C++ so we are not bound to handle <> as bad as C++.

Carbon should learn from existing design and implementation work of languages with the same goal.

@josh11b
Copy link
Contributor

josh11b commented Jul 26, 2022

Carbon has a goal of being easy to parse for tooling, which has meant that we have considered and rejected angle brackets <...>, due to experience with the difficulties parsing them in C++.

The generics syntax is :!, meaning "passed at compile time", not square brackets [...], as described in #565 . Generic parameters passed explicitly, as in Slice(T) or Vector(T) are in round parens (...). The square brackets mark parameters whose value is deduced from the types of other parameters.

@ghost
Copy link

ghost commented Jul 27, 2022

2. Square brackets are more intuitive for Arrays...

All syntaxes are ugly: round brackets are more intuitive for calls. The issue with the square brackets is that if Carbon aims metaprogming, at some point there are chances that square brackets become completly ambiguous with indexing on a compile time list (let's say), so if you select type N in list A, it's not visually clear if it's an instantiation or a list extraction.

What should be discussed then becomes is more obvious, round or square is not the problem, the problem is to have an instantiation operator, like the bang in D, before the brackets, whatever is their shape.

@chandlerc
Copy link
Contributor

FWIW, I agree with what @josh11b has written here:

Carbon has a goal of being easy to parse for tooling, which has meant that we have considered and rejected angle brackets <...>, due to experience with the difficulties parsing them in C++.

The generics syntax is :!, meaning "passed at compile time", not square brackets [...], as described in #565 . Generic parameters passed explicitly, as in Slice(T) or Vector(T) are in round parens (...). The square brackets mark parameters whose value is deduced from the types of other parameters.

On the issue of using -> for function returns vs. : or something else, I think it is good to match C++ here which uses the same core symbol for its trailing return syntax.

Marking this as an issue for leads however as it is a concrete and specific question to use two alternative syntaxes.

@DevNoteHQ
Copy link

The : return type syntax is a popular request, and has the majority of upvotes in #1520 (comment). Given also that two existing successful successor languages (Kotlin and TypeScript) use it, there is considerable precedent.

The argument for -> is that function types look weird with the colon syntax: var func: (i32): i32, and so the arrow should be used in both places for consistency with var func: (i32) -> i32. But this is optimizing for the rarer case. Return type annotations and variable/parameter type annotations are way more common than function types, so it would make sense to optimize for a consistent syntax for them.

Well TypeScript actually uses func(): number { ... } for normal function definition and let func: (value: number) => number; for function types, so that would maybe also be an option? Just split it?

So fn func(): i32 { ... } for function definitions and I would suggest var func: (i32) -> i32; for function types? To probably be consistent with the future lambdas list.map { value -> value.x + value.y } if Kotlin-Style Lambdas are preferred...

@zygoloid
Copy link
Contributor

zygoloid commented Aug 9, 2022

On the issue of using -> for function returns vs. : or something else, I think it is good to match C++ here which uses the same core symbol for its trailing return syntax.

I think there is some chance that we will want the same selection of options for function returns that we have for : -- in particular, for functions returning a generic / symbolic type we might want a ->! analogous to a :! binding, and for constexpr functions we might want something analogous to a template :! binding. I think we should wait until we're designing those facilities and then reconsider this question, and leave -> as-is for now.

@chandlerc
Copy link
Contributor

Marking this as decided with "not now" based on the discussion with leads and the explanation from @zygoloid and @josh11b above.

@chandlerc chandlerc closed this as not planned Won't fix, can't repro, duplicate, stale Aug 10, 2022
@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

9 participants