Hacker News new | past | comments | ask | show | jobs | submit login
First C# 7 Design Meeting Notes (github.com/dotnet)
154 points by Romoku on Jan 28, 2015 | hide | past | favorite | 80 comments



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.


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...


> 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.


What a poor article.. let me just cherry pick a number of benefits of functional languages and call them requirements for a 'reasonable' language.


That article could be summed up as: "Look at all of the ways that the language doesn't protect you from yourself (or the creator of the library you're using)!"

It's possible to write shitty code in every programming language. Of course, the specific methods of doing so differ, but I've yet to see a Turing-complete language that makes it impossible to write buggy code.


AFAIK F# is the first class VS citizen since VS 2010. They have a small yet good team working on it. What do you think is missing support in VS for f#?


In general, overall tooling is not at the same level. Code gen is focused on a C#-like model, designers aren't there, debugging isn't the same (immediate window, for instance). Last i checked (which was a while ago), VS testing didn't work with F#. Even Intellisense is not as complete. I'm happy with F#, very happy indeed. But it lacks the resources that C# gets thrown at it. And it suffers from MS not having the honesty to just admit MSR outdid them again (as they did with generics), that as a language, F# simply outclasses C#. Instead, we get lines like "F# is for scientific computing" or similar spin.

So yes, shipping F# with VS is a good step, and technically it's supported, it's obvious MS has some discomfort there. Which is too bad, cause F# is a rare jewel, nothing else has the combination of language features, interop/library, performance, and tooling.


This is something that does rub my the wrong way a bit as well. F# is a fantastic language, easily my favorite non-Lisp FP language, and possibly period, but it was very clearly second-class in the field of actually building full apps with it. MS just flat does not seem to believe that anyone would want to build full apps with F#, so support for doing so is a bit of a wild frontier.

Hopefully with F# in open source hands now this can continue to improve. In the meantime, I'm studying up on C# and .NET, so that I hopefully have at least the bare minimum familiarity to work around these limitations.


It's a self fulfilling prophecy. F# is weak at designing full stack apps because it lacks tooling because it is weak at designing full stack apps.

Even now, doing MVC websites is far more difficult out of the box if I code F#. MS still lacks JS backends, so we need third party compilers for that model... Maybe because they don't want to upset or look less than 1000% behind typescript.

I will say though otherwise I'm happy. In using F# to run my server apps with smooth pinvoke into my Rust code, which is expressive enough to offload a lot of logic. And with VS soon to be free, and Mono working fine, MS might not get any money from it. (Why deploy any sort of scale on Windows when it's line $35/core/month?) So, in that sense it's selfless and I'm quite grateful.


F# is weak at designing full stack apps because it lacks tooling because it is weak at designing full stack apps.

This is just something that takes time and commitment from the community. It's only ~7 years old at this point, and if everyone just sits back and whines about the lack of tooling without, y'know, building & releasing something themselves, it'll be an ongoing problem. It's the "take take take" mentality - often disguised as being an open source advocate - of most software devs where they want everything for free (guilty as charged, myself).

That said, WebSharper is out there, which is a pretty solid framework for a lot of tasks. I've been thinking about ways to creatively encourage/solve the tooling problem though, starting with exhorting all of us in the F# community to reduce the whining and redirect the energy into creating solutions. Tooling is only a self-fulfilling prophecy if we continue to act as-if the outcome is out of our hands.


You're right, I am just whining.

But more to the point, I am pointing out that Microsoft is not treating F# like C#, not giving it the same resources. No one says C# users are just whining when they wanted, say, edit and continue.

Has any community, ever, stepped up and offered an experience as good as Visual Studio's? I mean, that's sort of a major reason Microsoft makes and sells that product.

Yes WebSharper is pretty awesome. But I still don't see why we shouldn't criticize MS for not doing something like that directly. After all, MS got flack over ASP.NET Web Forms then went and put resources into MVC.


Ultimately, I decided this is what I want to do. I wanted to learn more about the Windows ecosystem anyway, so why not learn the missing bits from C# and .NET (which I came to F# without), and then be able to continue working in a language I love with enough know how to help fill in those gaps myself. Besides, having that under my belt can hardly hurt my career; the nice thing about F# is the related skills are also well in demand too, and a lot more pleasant to code in than some other hosted FP languages ...


> Instead, we get lines like "F# is for scientific computing" or similar spin.

You will never sell the typical VB.NET/C# enterprise .NET developer into F#.

I find very commendable what Microsot has done so far, even if it feels too little.

It rises the visibility of the language, specially to managers and drives CLR design decisions that help FP implementations, like TCO.

Let me know when Oracle gives at very least the same level of support to Scala in Netbeans and JVM design.


F# doesn't (or didn't) use tailcall in CLR in general, because it was too slow. It only does so as a last resort. Or did that all change? Same with stuff like tuples. We get tons of heap allocations because the CLR did poorly with structs. F# had to even go back on their design because of this, and match the BCL tuple type.

MS doesn't need to sell the typical enterprise dev. They just need to not sour-coat things and be honest and complete in their statements. It'd also be nice if MS viewed shipping actual language independent code, instead of stuff that takes dependencies on C# compiler details.

MS gained a huge amount from the F# folks by getting CLR generics from them - that's one major benefit over the JVM. Just on that alone perhaps they owe them that (maybe, I've little clue of internal politics, except that there is some resentment towards F#, and at least a bit of censorship on publishing things that make C# look poor).

Let me know when Microsoft starts shipping Rust-level features, so we can deal with memory safely and reduce bugs without losing perf.


> Let me know when Microsoft starts shipping Rust-level features, so we can deal with memory safely and reduce bugs without losing perf.

Is Rust 1.0 out yet?

They are on Microsoft research.

While the world still isn't ready for the likes of Singularity and IronClad, Spec# and Dafny, at least part of the technology has landed on Windows Phone 8 and .NET Native compilers.


Rust 1.0 is currently slated for 8-14 weeks away: http://blog.rust-lang.org/2014/12/12/1.0-Timeline.html


I know, and comparing its current state with what F# offers today doesn't make sense, not today.

In a few years time when Rust has the same eco-system has F# offers today to Windows devs, then we can compare the current state of the languages.


Sorry, I thought you were asking a question, not being rhetorical.


I believe c# has had tuple support since .net framework v4.


I believe tuple support in v4 is a simple set of classes. There is no language construct specific for the use of tuples, which means it's just a library instead of a programming language feature.


What are the advantages that language-level tuples would have over the existing System.Tuple class?


Without deconstruction and pattern matching, language level tuples would be only sugar: "var x = (1, 2)" versus "var x = Tuple.Create(1,2)"

The real power of Tuples only comes with deconstruction and matching, such as "var (a,b) = GetSomething()" and "case (_, y)".

So these features would go hand in hand. Deconstruction and matching requires lang level tuples, and lang level tuples are pretty lame without deconstruction and pattern matching.


The ability to write (2, "hello") instead of Tuple.Create(2, "Hello"). But more importantly, syntax for deconstructing tuples will make tuples convenient for returning multiple values from a method. Eg.: (var x, var y) = getPoint(); as shown in the aticle.


Also, the type is simpler to represent. Instead of Tuple<int, string> you just have something like (Int, String).


doesn't C# already have structs ? how are records different from that?



C# has anonymous types, which are closer to records, but there's no way to refer to a particular type structure.

So while I can write

    var x = { FirstName = "Riff", LastName = "Raff" }
and then go ahead and access x.FirstName and x.LastName, I can't declare a method signature like this:

    void Display({ string FirstName, string LastName } nameRecord)
    {
    }
This is the kind of thing which is being proposed (along with possible pattern matching/decomposition syntax which is new ground for C#)



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


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.


> 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.


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


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.


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.


> 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.

You're making an either/or distinction here without any reason. You could just as well say, "The number of cars that recently added anti-lock brakes gives significant evidence that ABS is winning out over seat belts."

I don't see these languages removing any OOP features, so I think what it shows is that functional features are either useful independent of OOP features, or complement them. (My personal belief is the latter: the languages I enjoy the most have both.)


BTW, I must admit I misspoke on the last sentence - obviously the property of a software system working and doing what the user needs is more important than simplicity.

Too short a road from the obvious to the assumed...


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?


Look into Microsoft's Task Parallel Library, it's fantastic! It gives you something similar to channels.

I wish more people knew about it. As someone else mentioned, Reactive Extensions are also great - I believe they will be getting backpressure support which will allow similar semantics to channels (but with first-class error handling)


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.


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).


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.


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.


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.


> 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%.

Interesting. Do you have this benchmarking code posted somewhere? What do you mean by "manual currying"?


You can already get a long way towards channels by using reactive extensions (E.G. http://pastebin.com/h1xteunX)

Some syntactic sugar a la await could be nice though.


Not sure if you're aware, but your Rx example has a few problems:

1.) In the StartSenders method, you're violating the Rx grammar by calling channel.OnNext concurrently. Wrap it on a lock statement.

2) In StartReceiver you're missing out messages the way you handle the channel. Replace the loop with a call to channel.Subscribe


I did not know either of those things! Thanks!


40% is nothing, the last time I tested jquery.each vs a for loop, the for loop was at least 50x faster.


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


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...

"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

'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.


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


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.


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.


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

Specially in the eyes of managers.


I wish they kept the Pattern Matching support.


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.


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.


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).


C# isn't "technically" open source, it's just open source. If you want to contribute actual code and have it actually incorporated into the language, then all you need to do is follow the contribution guidelines here: https://github.com/dotnet/corefx/wiki/Contributing


IIRC, they (MS) said would steer the language and .NET libs, and not involve a community style effort (because they want to ensure compatibility for their customers), did they change that?


That's not different than some open source projects and has no bearing on it being open source. Some project leads call attempted contributors idiots and refuse to even fix security bugs. Some have differing visions for their project. Which projects run by a strict vote, and how would you even decide who gets to vote? Most likely you'd elect leaders that will vote in the benefit of the project... Which is what MS has effectively done.


>That's not different than some open source projects and has no bearing on it being open source.

I didn't say it's different, or that it's not open source for that.

I asked because the parent said: "If you want to contribute actual code and have it actually incorporated into the language, then all you need to do is follow the contribution guidelines here"


And the parent is right .. Right? That's all you gotta do. If your contribution is accepted, you're all set. Same as every other project I've seen.

Anyways, maybe I misunderstood the that, so my apologies if I came off rude.


Of course they would, it's their project after all. So you can contribute but with that in mind, it's about as open as any corporation is going to be when it comes to accepting input from the world at large. At least they got that bit right.


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


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.


There is no silver bullet as such. Open source is just a bullet, the one that keeps the community armed.


Downvotes for what? Was there something controversial in this simple statement?


They are including almost all the frameworks you would use as well. They weren't set up to take pull requests, and I suspect that they're only interested in bug fixes. So, not entirely genuine.


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


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).


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.


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");	 	

	 }


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.


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


You kind of used D's syntax for contracts,

http://dlang.org/contracts.html


cool, thanks!

Multiple bracket blocks is not the most esthetic of solutions I think but it's the best I can think of. Attributes feels too clunky and just stacking contracts as lines after the class statement feels too disorganized


Would be easy to add something like that in CLOS using :before and :after methods and maybe some macros to give suitable syntax.


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


> Method contracts

Oh god, I want it SO BAD.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: