
First C# 7 Design Meeting Notes - Romoku
https://github.com/dotnet/roslyn/issues/98
======
MichaelGG
Good start, finally adding records, patterns, tuples, non null, would be a
good first step to making C# not feel so heavyweight compared to F#. If the F#
team ever gets enough resources to complete with C#'s VS features, perhaps
we'd get some serious adoption. As is, F# comes across second class both in
tooling and MS marketing - that's not really competing fairly ;)

But without making things expressions, it's still gonna be clunky. First class
immutability and expressions instead of statements would help propel it
further. I still would feel rather limited about having no type inference on
local functions, though.

What would be really exciting is if the runtime was also open for some real
changes. Traits, non null, slices, maybe even ownership (so we could stack
alloc, a huge perf win)... One can dream.

~~~
hrvbr
Just yesterday there was this article illustrating how C# fundamentally can't
catch-up with F# on some important characteristics:

[http://fsharpforfunandprofit.com/posts/is-your-language-
unre...](http://fsharpforfunandprofit.com/posts/is-your-language-
unreasonable/)

~~~
Someone1234
> Comparing objects of different types is a compile-time error.

Then use C. In OOP comparing objects of different types is key to inheritance.
The reason their example works is because everything in C# inherits from
object, so you'll always find some commonality to compare.

You could have the compiler generate a warning when object.equals is used
(rather than overridden) but getting rid of comparisons between different
object types completely is backwards and will reduce efficiency.

------
DrDimension
I cannot help but think that the overwhelming desire to support immutability
and functional constructs here, as well as in nearly all other modern
languages, gives significant evidence that functional programming is finally
winning out over OOP.

In the future, I hope that FP will be the default design choice, with objects
being used where needed such as for components, plug-ins, and ad-hoc
dictionary-passing-style tools.

After all, simplicity is the most important property of any software system -
[http://www.infoq.com/presentations/Simple-Made-
Easy](http://www.infoq.com/presentations/Simple-Made-Easy)

~~~
noblethrasher
Immutability was never incompatible with OOP, just the opposite in fact. Even
Alan Kay often criticized languages like C++ and Java for encouraging the use
of setters and, thus, “turning objects back into data structures”.

C# is still one of my favorite languages (even though I use F# most of the
time now), but I do admire Java for making it significantly more painful to
write mutable rather than immutable classes; it's too bad that fact was lost
on so many programmers.

Kudos for sharing the Rich Hickey video; it's one of my favorites of all time.

~~~
azth
> but I do admire Java for making it significantly more painful to write
> mutable rather than immutable classes;

Out of curiosity, how does it do that? As far as I know, everything in Java is
mutable by default.

~~~
noblethrasher
You have to go through the extra ceremony of writing a setter.

~~~
azth
The same applies to C# though, correct? Plus, I was thinking more of the lines
of something like:

    
    
        class Foo {
          private int x = 0;
    
          public void bar() {
            this.x += 1; // Whoops!
          }
        }
    
        Foo x = new Foo();
        x.bar(); // Mutating call.
    

Which Java does not prevent.

~~~
noblethrasher
Yes, the same applies to my beloved C#, but that language was much less
hostile to immutability. Indeed, the prettier mutator syntax was even
positioned as a feature once upon a time.

To be clear, I'm the guy that insists on defining classes as either abstract
or sealed, and almost always marks fields as readonly. But, I'm okay with the
kind bounded mutability that you mentioned; clients of a `Foo` instance have
to treat it as immutable.

Here is how I do OOP:

* I make classes to hide state, and hidden state is the same as being stateless.

* As I learn more about the problem, I start subdividing classes into smaller classes (not necessarily via inheritance).

* So, as my understanding of the problem increases, the number of class division increases, and by the pigeonhole principle, the amount of state approaches zero.

------
Rapzid
I would LOVE for C# to get language support for go style channels complete
with select and friends.

C# already has the fantastic Task stuff, and while they aren't as cheap as
go's go-routines they work very well. Channels would just ice the cake so
well. :D~~~

And while I'm at it. I did some testing recently and realized that manually
currying in a for loop is faster than using function composition with
delegates by about 40% :| It feels like in theory it should be compiled down
to code with the same efficiency? This is probably more of a CLR/JIT issue
though?

~~~
rjbwork
If you mean what I think you mean by "manually currying", it's likely because
behind the scenes, there is a proxy class created for most (all?) lambdas that
contains everything it needs to execute, including any scope variables
maintained. So there's some extra overhead there, though not as much as you'd
expect since everything, even value types, are pulled in by reference in the
context of lambdas.

~~~
seanmcdirmid
I did not know that! That explains a lot of the memory performance problems I
was having (structs being moved to the heap...icky); lambdas are sneaky little
turds.

I solved the problem by avoiding lambdas altogether in code where performance
is a concern, using delegates instead and ensuring all arguments are passed in
rather than closed on (so structs would remain structs, GC pressure is
avoided).

~~~
MichaelGG
Imagine if the CLR allowed optional borrowing annotations ala Rust. Then safe
non leaking functions would no longer need their callers to use the heap. Even
APIs like String.Split could be actually efficient. In fact you might even get
away with zero alloc for it, for some small cases.

~~~
seanmcdirmid
Lambdas kind of mess that up, since they are indirect and dynamic by their
nature and basically require GC to work. Heck, GC was originally invented to
support Lisp.

There was, maybe is, some work being done on systems C#, not sure about the
status though.

~~~
MichaelGG
I don't see how that is any different, and in fact, lambdas would be one of
the great things to benefit from stack allocation.

You just have to annotate or analyze the functions that don't takeover/leak a
reference to something.

For something like List.ConvertAll (aka map), ConvertAll does not leak the
lambda, it's pure in both input and output. So a stack allocated lambda works
just fine. So the type signature for ConvertAll would indicate that it's Pure
for parameters passed in. With that info, the compiler is free to pass lambdas
on the stack to it.

So whenever the lambda is going to be created, the C# compiler just needs to
look at the usage of it - is it passed only to Pure functions? If so, then no
need to allocate a whole new object on the heap.

They could make it even cooler by doing Haskell's "fusion" which also
contributes to deforesting. We just need the CLR (or even the C# and F#
compilers) to provide real inlining. Then when you pass a lambda to an inlined
function, you can avoid creating the closure in the first place! For common
patterns like "xs.Select(...).Where(...).Aggregate(...)", if each function was
inlined and pure, the resulting code could literally be equivalent to a big
loop, as if you had hand-written the thing. No allocation all over the place,
and much better resulting JIT'd code. I've wanted this in F# for a while (and
F# does have inlining so you do get better code than C#), but Rust actually
implements it, so lambdas are cost-free in many cases. _That_ is progress.

------
vans
I think it's too late for non null ref types. But pattern matching, traits and
built in code contract would be awesome !

~~~
ColinDabritz
Non-nullable reference types have been called an impossible problem, but so
was 'Await in catch and finally blocks' which shipped in C# 6.

From [http://blogs.msdn.com/b/csharpfaq/archive/2014/11/20/new-
fea...](http://blogs.msdn.com/b/csharpfaq/archive/2014/11/20/new-features-
in-c-6.aspx)

"Await in catch and finally blocks has been disallowed until now. We’d somehow
convinced ourselves that it wasn’t possible to implement, but now we’ve
figured it out, so apparently it wasn’t impossible after all."

I'm hoping this is one of those 'Clark's first law' situations:
[http://en.wikipedia.org/wiki/Clarke's_three_laws](http://en.wikipedia.org/wiki/Clarke's_three_laws)

'When a distinguished but elderly scientist states that something is possible,
he is almost certainly right. When he states that something is impossible, he
is very probably wrong.'

They've got quite a lot of smart folks working on C#, and it's heartening to
me to see them taking another look at non-nullable reference types.

~~~
pbz
It would be such an important feature that I'd be willing to tolerate breaking
changes -- the language designers may not however.

------
x0x0
As a java programmer, who is involved in some large projects that can't be
ported, I'm really jealous. And eagerly waiting to see how well the .net core
runtime targets linux and mac.

Good, no copy interop with native code would also be awesome. Particularly for
machine learning.

~~~
mike_hearn
The Java world moves on too, you know. A lot of the features that are listed
as things that would be nice to have in C# already exist in Kotlin, which has
been created by JetBrains to be fully drop-in compatible with Java. To the
extent that it has a hotkey that automatically rewrites a Java class into
Kotlin, and the entire project keeps compiling and working (they have
full/close to perfect interop).

For example, Kotlin has:

• Nullability in the type system

• Good support for efficient functional programming, e.g. you can do
collection.map { it * 2 } and it's as fast as an imperative for loop as the
compiler inlines the block.

• Strong support for meta-programming / DSL features, so there's less need to
make code generators. JetBrains are still working on this but basically the
language has a lot of features that don't initially seem all that significant,
but can be combined to create useful DSLs.

• Lightweight data classes that support immutability and editing via copy
construction (using named arguments)

• Traits

• Delegation

• etc etc

... and it's all here today, with good IDE support, and compatible with Java 6
even.

For good native interop there is JNA and there's a research project over at
Oracle looking at how to do something better than JNA directly integrated with
the JVM in a future version. So don't be too jealous.

~~~
pjmlp
There is a big difference between being the platform's system programming
language and a third party language.

Specially in the eyes of managers.

------
jpgvm
If even 50% of this makes it into C# it's going to be a pretty amazing
language.

Native code interfaces were already reasonably fast, allowing more no copy
semantics and array slice behaviour is going to do wonders for native library
performance.

~~~
Cakez0r
I really hope they implement this. It would make IO so much more efficient if
you could pin a big chunk of memory and allocate buffers from it.

------
coldtea
If only the open source languages we use had that many resources and paid
developers...

(Well, technically C# and the related libs are fully OSS now too, IIRC).

~~~
CmonDev
What's the matter? Open-source did not turn out to be such a silver bullet?

~~~
coldtea
Did I say anywhere that I'm a proponent of Open Source?

I just said, "if only open source languages had the same resources".

Because that's what I mostly get to use, and because I don't run Windows but
OS X, so I don't get to play with a fully supported C# environment.

------
mhomde
I've been trying to think of something that drastically change how I coded.
Bugs and productivity really are the two major dragons to slay.

I'm just spitballing here but something I'd really like to see stuff like code
contracts and unit testing, but more integrated with the language, less
verbose and requiring less to setup. Being able to let the "meat" of a method
be separated from all the error-checking, post, pre conditions etc would
really make things cleaner.

Current implementation feels like it requires too much setup with separate
classes, duplicate method signatures in several places etc etc. It would be
really cool to have something like

    
    
      public int SomeMethod(int a, int b)
    
      pre 
      { 
        Requires (a > 5);
        Requires (b >= 0, new Exception("something something"));
      }
    
      {
         // DoStuffHere
      }
    
      post
      {
        Ensures (result > 0, new Exception("needs to be above 0"));
      }
    

I'd even want to be able to separate it into separate files using partial
classes (or something) so you could the condition stuff separate , with or
without duplicating signature depending if you wanted to target specific
overloads

Full signature would simply be without the body:

    
    
      public int SomeMethod(int a, int b)
    
      pre
      {
        Requires (a > 5);
        Requires (b >= 0 ,new Exception("something something"));
      }
    
      post
      {
        Ensures (result > 0);
      }
    

Without signature is trickier, but would be cool since you could use same
conditions for several overloads, and just target the variables that are
included in each:

    
    
      Conditions.SomeMethod
      {
        pre
        {
          Requires (a > 5);
          Requires (b >= 0, new Exception("something something"));
        }
    
       post
       {
         Ensures (result > 0);
       }
      }
    
    

heck, why not even throw in "test blocks" and Visual studio could run light-
weight kind of unit test as you programmed and mark the whole method as
functioning or not. Imagine having a sort method and throw in something like:

    
    
      public IEnumerable<int> Sort (IEnumerable<int> list, Order order)
      test
      {
         (list = {3,5,6,2}, order = Order.Ascending) => result == {2,3,5,6};
         (list = {3,5,6,2}, order = Order.Descending) => result == {6,5,3,2}
      }
    

VS could highlight the failed test(s) directly in the editor as you coded

The specifics and syntaxes of these things requires some thought but I love
the basic premise, am I rambling?

edit: I saw that something in this direction if not as extensive was actually
discussed

~~~
noblethrasher
We've had a robust way of doing code contracts since C# 2.0.

If you instruct the compiler to treat all warnings as errors (so that
variables must be defintitely assigned), then the following code gives you
what you want:

    
    
    	 public PositiveInt SomeMethod(GreaterThanFive a, NonNegative b)
    	 {
    	 		//do stuff;
    	 } 
         
    	 public struct GreaterThanFive
    	 {
    	 	readonly int n;
    	 	
    	 	public GreaterThanFive (int n)
    	 	{
    	 		if(n < 5)
    				throw new ArgumentException("n must be greater than 5")
    			
    			this.n = n;
    	 	}
    	 	
    	 	public static implicit operator GreaterThanFive(int n)
    	 	{
    	 		return GreaterThanFive(n);
    	 	}
    	 	
    	 	public static implicit operator int (GreaterThanFive n)
    	 	{
    	 		return n.n;
    	 	}
    	 }
    
    	//Similar definitions for NonNegative and PositiveInt
    

We can even have nice diagnostic messages since the advent of C# 5's
CallerInfo attributes (CallerMemberName, CallerLineNumber, and
CallerFilePath).

~~~
MichaelGG
Very clever. It may be robust, but is ridiculously verbose and feels sorta
obfuscatory. Also pays a runtime penalty unless they've improved the CLR
codegen.

It also might not be super amenable to static analysis.

~~~
noblethrasher
But, structs pay a very small runtime penalty, if at all, right?

The verbosity will be mostly ameliorated with primary constructor. I propose
going further by allowing programmers to annotate constructors so that they
can be used as user-defined conversion operators.

Thus, the aforementioned code could become something like:

    
    
    	 public struct GreaterThanFive implicit (int n)
    	 {
    	 	readonly int n = n;
    
    	 	if(n <= 5)
    	 	    throw new ArgumentException("n must be greater than 5");	 	
    
    	 }

~~~
MichaelGG
Traditionally, structs paid a large codegen penalty, as a lot of optimizations
and stuff were turned off. It also seemed like the codegen wasn't super smart
about passing them around. Maybe that's all changed.

I meant the verbosity of having to create a custom type for each kind of
restriction, versus some inline "int n [n > 5]" notation.

~~~
noblethrasher
In addition to the benefit of brevity, something like your proposal also has
the virtue of being compatible with the `checked/unchecked` keywords.

------
bartwe
I'd like some method to write GC-less code for games. Structs with copy
constructors and destructors perhaps.

------
talles
> Method contracts

Oh god, I want it SO BAD.

