This project is read-only.

'let' / 'def' / 'val' keyword

Topics: C# Language Design
Jun 22, 2014 at 7:04 AM
The feature is simple, a complementary part of 'var' which creates a local variable with one initialization.
def a = 1;
a = 2; // Error !

int x;
f(out x);
x = 2; // We didn't mean but we can.

f(out def y); // like 'out var' but cannot change later
y = 1; // Error !
Jun 23, 2014 at 10:51 AM
'let' keyword already exists in LINQ and have the same meaning (something you can't change)
Jun 24, 2014 at 7:49 AM
Edited Jun 24, 2014 at 7:50 AM
I already suggested this, or at least a simpler variation of this, under the title "local const type inference". For a discussion, see https://roslyn.codeplex.com/discussions/545655.
Jun 24, 2014 at 9:16 AM
KrisVDM wrote:
I already suggested this, or at least a simpler variation of this, under the title "local const type inference". For a discussion, see https://roslyn.codeplex.com/discussions/545655.
I think it is different.
In C# const != readonly .
const is used only for real constants that can be written in CIL, while readonly means object that cannot be changed later.
Jun 26, 2014 at 9:30 PM
I actually wrote a patch prototyping this, as a let keyword analogous to var. That gist has some regenerated resources which I was unable to satisfactorily clean up, the actual change was done in a hurry and god knows if the patch even works with today's Roslyn - most likely not, although many of the stages where the check happens are probably largely intact. As always, there are many potential language feature collisions and a prototype will not cover them all. But it is clearly doable.

Another interesting thing that happened is that Apple introduced the Swift language which actually has exactly this approach (with var and let). My first and second impressions of it is that it works really well since it lets you make a distinction between what's supposed to change and what's not, although in Swift it also goes a lot deeper. But this is a sidebar.
Jun 26, 2014 at 11:00 PM
I think let is a good idea. I don't remember which thread it was in, but Mads mentioned some time ago that the reason they haven't done readonly for local variables is that it would be too verbose and it would mean the "right" way to do things requires more verbose code. I think let as a readonly alternative to var solves that problem really nicely.
Jun 27, 2014 at 8:42 AM
Edited Jun 27, 2014 at 8:43 AM
I would too much appreciate let support. Also, if it would support re-declaration in-scope like F# does, that would be really awesome, but it's not really a requirement. To explain, if it worked like this I would be very happy xD:
let a = 5; // success
a = 10; // compiler error
let a = 10; // success, a refers to a new variable.

if(true) {
  let a = 15; // success, still a redeclaration
  Console.WriteLine(a); // 15
}

Console.WriteLine(a); // 10
In F# this is achieved by compiling different versions of the variable as different variables, so you get stuff like int a@1 = 5 and int a@2 = 10 in the CIL.
If this is not achievable I would still much appreciate let to be "readonly var" though...
Jun 27, 2014 at 4:10 PM
To me, such a let keyword is one of the best features still missing in C#.
I experienced it five years ago in Scala (their let is called val, which is closer to var, but since LINQ uses let it's better to follow that).
The guarantee of single-assignment would help tremendously reading and understanding complex code written by others. I'm not sure that we want a let to override a previous let.
I think this would be a very good feature in terms of usefulness/cost tradeoff. I would appreciate to read the opinion of members of the language design team on this.
Jun 27, 2014 at 8:04 PM
eldritchconundrum wrote:
To me, such a let keyword is one of the best features still missing in C#.
I experienced it five years ago in Scala (their let is called val, which is closer to var, but since LINQ uses let it's better to follow that).
The guarantee of single-assignment would help tremendously reading and understanding complex code written by others. I'm not sure that we want a let to override a previous let.
I think this would be a very good feature in terms of usefulness/cost tradeoff. I would appreciate to read the opinion of members of the language design team on this.
What I would like to see would be a let with the semantics that a name could be reused in a scope if, when a variable was written, it would either always or never be replaced before any particular usage. For example, if all of the case statements and the default for a switch statement let foo= [some int expression], then the scope of foo would extend past the case statement, but if only some cases include such statements, then after the case statement the name foo would have no meaning (even if it had been let before the switch statement, the scope of that variable would end at the switch statement.

Essentially, the basic concept would be that name reuse would be permitted in cases where variable reuse would be semantically insignificant; if it wouldn't matter whether a variable was reused or not, then it's unlikely that problems would be caused by either inadvertent unintentional reuse or accidental creation of a new variable when reuse would have been appropriate.