News for hackers. Stuff that matters.
Re:What’s New in C# 7.0 by int_19h on Thursday August 25, 2016 @12:02AM (#12356912)
Did you guys look into alternative syntax for return types? It really is a huge eyesore, and impediment to reading, when you have more than just a typename and a couple of modifiers like * and [] attached to it.

With tuples especially, it's even worse, because the method name gets squished between two very similarly looking ()s, which is very different from how methods have historically looked in code. If I were scanning code fast, I'm not sure I would even read it as a function declaration.

C++ adopted its "auto ... -> ..." syntax a while ago - granted, they had a forcing function in form of decltype(), but many people also use it for readability reasons with complex return types. I hope C# follows suit; or, better yet, comes up with a unified type-after-name syntax a la ES6, that can be used everywhere in the language, while retaining existing syntax for back-compat purposes.

Re:What’s New in C# 7.0 by macca321 on Thursday August 25, 2016 @08:39AM (#12358522)
What would you suggest?

public TResult SomeMethod() where TResult : (string name, int id)

Re:What’s New in C# 7.0 by int_19h on Thursday August 25, 2016 @03:52PM (#12361949)
The most obvious approach would be to repurpose C++ syntax, since it's already been around for a while, and C# syntax is generally pretty close to C++ in many respects. So:

  public SomeMethod(bool b) -> (string name, int id) { ... }
However, this may be undesirable due to confusion with => for lambdas and expression-bodied methods, especially in:

  public SomeMethod(bool b) -> (string name, int id) => ...
: is the next obvious candidate, and would unify the syntax with TypeScript and many other languages. But given that it's already used for labels and named arguments, I'm not sure there's enough room there to reuse it also for types.

:: is another decent choice in terms of familiarity coming from other languages (Fortran, Haskell etc). But, unfortunately, it's already taken for extern alias, and I don't think this could be easily disambiguated in many contexts.

Now, if this is narrowly scoped to method return type only (i.e. we're not trying to invent a syntax that could later be used in a similar way to swap the type and the name in other places, like arguments and variables), and only as a fallback for when the usual "Type Name" arrangement has poor readability, perhaps take a hint from Ada and reuse "return"?

  public SomeMethod(bool b) return (string name, int id) { ... }
A tad verbose, but if it's intended to be used sparingly, primarily with tuple-returning methods and deeply nested generics, I think that's okay - tuples themselves are pretty verbose when components are named.

Or maybe borrow "as" from VB? It looks like it could be extended to other kinds of declarations in the future in a straightforward manner, without conflicting with its existing use for casts:

  // Just for method return types
  public SomeMethod(bool b) as (string name, int id) { ... }

  // For everything
  public SomeMethod(b as bool) as (name as string, id as int) {
    var x as float;
    TryFoo(out var y as bool);
    ...
    switch (obj) {
      case foo as Foo:
        ...
    }
  }
Re:What’s New in C# 7.0 by flukus on Thursday August 25, 2016 @07:59PM (#12363394)
I like the as syntax, it may conflict with casting though when used on variables.

    public SomeMethod(bool b) -> (string name, int id) { ... }
When was this added to c++? I think I need to brush up on my lower level skills.
Re:What’s New in C# 7.0 by int_19h on Thursday August 25, 2016 @08:53PM (#12363595)
With regards to "as" conflicting, I think it shouldn't be a problem because the cast operator is binary. So if you already know that something is a declaration, the current token is the identifier that's being declared (or closing parenthesis of the parameter list), and the following token is "as", it cannot be a valid expression. Consider:

  var x as int;
"var" makes it a declaration, so "x" is the identifier, and "as" has to be the type specifier.

  var x = y as int;
"=" clearly separates the identifier from the initializer, and the latter is an expression, so "as" is the cast operator.

Similar reasoning applies to other places where the two can appear - function parameter list, return type, field and property declarations etc.

So far as I can tell, by the time we get to the point where "as" would be used to specify the type of the declared entity, we will already know that it's a declaration, and that the only other token that can follow in existing grammar is "=", "{", or "=>" (for variable and field initializers and default parameter values, property getters and setters, and lambdas and expression-bodied members, respectively), and none of these start an expression. In all other contexts, "as" would be an operator.

Re:What’s New in C# 7.0 by int_19h on Thursday August 25, 2016 @08:45PM (#12363561)
It was added in C++11 when they added decltype(), so that you could reference arguments when computing return type. It's slightly different though, in that you need to specify the return type in the usual position as "auto" first, and then you can use "->" after the parameter list. So:

  template<typename A1, typename A2>
  auto foo(A1 a1, A2 a2) -> decltype(a1 + a2) {
    return a1 + a2;
  }