Live data from Hacker News

I was wrong, reflecting on the .NET design choices

ayende.com

121–130 of 139 posts

Re: I was wrong, reflecting on the .NET design choices

#121

Earlier quoted context omitted.

That's true in the clr too as long as everything supports generics.

Things that have CLR-like generics work on the CLR. Anything else doesn't. E.g. Scala.

F* has an advanced type system with support for dependent types and refinement types. Yet, it runs on the CLR.

Source: https://www.fstar-lang.org

Re: I was wrong, reflecting on the .NET design choices

#122
post #56

Earlier quoted context omitted.

As a low-level game dev, I consider C# a nearly perfect, wonderful language, tragically self-defeated by garbage collection.

As a game developer having used C# for two large scale projects, I can tell you that the garbage collector was the least of our worries. Just be a good citizen and don't trash like crazy and the GC will never block in the action phase. Also, don't use the default mono GC, that one is terrible.

Ah, but everybody's data is different, and that's the problem with a prescribed one-size fits all, too-clever mem manager. If you need a complex graph with a million nodes, then any heap walk during a frame is a catastrophe, and your only out is to write a custom mem manager within the confines of c#, or put your game's core data structure in a C++ lib.

Re: I was wrong, reflecting on the .NET design choices

#123
post #116

Earlier quoted context omitted.

It's very interesting that you were able to see my use cases and come to this conclusion...

Regardless of the use case this is what the official documentation says about namespaces: The namespace keyword is used to declare a scope that contains a set of related objects. You can use a namespace to organize code elements and to create globally unique types. And about partial classes: There are several situations when splitting a class definition is desirable: When working on large projects, spreading a class…

How would you propose to split a struct that has a single data member? Say, a struct where the only data is one unsigned short?

Also, "regardless of the use case" ? I barely know how to respond to that. Have a little imagination.

Re: I was wrong, reflecting on the .NET design choices

#124
post #85

Earlier quoted context omitted.

> There is a deep semantic difference between TryParse and Parse Sure, but I don't think that splitting every possibly-failing API call into throwing and non-throwing forms is the right way to express that difference, and a lot of the time it'll be a matter of context (meaning that the implementation can't magically do the right thing). It's fairly easy to layer throwing behaviour on top of nonthrowing in a generic a…

I agree it's easy to layer throwing behavior on top of non-throwing behavior -- Java easily chose the worst possible way to do it. But having both a Parse and TryParse means that I can ignore the result of the Parse call entirely and let it fall through to the exception handler. It is by-definition always expected to succeed so when it doesn't then that's a bug. If you only have one of TryParse or Parse you cannot ju…

> If you only have one of TryParse or Parse you cannot judge the intention.

Sure you can. To take Java as an example, if you only have one parse method and it returns an `Optional`, you can indicate the intention by whether or not you call `get` directly or call something like `isPresent` or `orElse` first/instead. Yes, you can get that wrong, but you can get the choice between `TryParse` and `Parse` just as wrong.

Re: I was wrong, reflecting on the .NET design choices

#125

Earlier quoted context omitted.

I have absolutely no experience with Rust, but I know it normally depends on libunwind, isn't that for unwinding the stack?

Perhaps to implement https://doc.rust-lang.org/std/panic/fn.catch_unwind.html But also just to display traces on asserts/panics, even if not "unwound" per se.

By default, rust's panics _do_ unwind the stack. However, you can also set a flag to compile them as an abort instead. Stack traces are still useful in that case.

Re: I was wrong, reflecting on the .NET design choices

#126

Earlier quoted context omitted.

That's true in the clr too as long as everything supports generics.

Things that have CLR-like generics work on the CLR. Anything else doesn't. E.g. Scala.

I don't really get the complaint. Even if they had type erasure you couldn't use Scala in the CLR because nobody has written a CLR target. And on the other hand, I don't know why there couldn't be a Scala implementation with true generics. A lot of crap like DummyImplicit and ClassTag is there for no other reason than to work around those limitations anyway.

Re: I was wrong, reflecting on the .NET design choices

#127

Earlier quoted context omitted.

> + no checked exceptions (checked exceptions have benefits in theory but real-world practice shows that it forces programmers to copy-paste mindless boilerplate to satisfy the checked-constraint) As languages like Rust or Swift demonstrate, the issue is less the checked exceptions and more the abject lack of support for them in the language and type system, which ends up making them essentially unusable. > Gosling s…

I find unsigned types more dangerous than signed bounded types. For unsigned types the edge-case is at 0, a frequently used number in eg. arrays. For signed types the edge-cases are at (random) positive and negative numbers. Having to think more about edge-cases makes the code more dangerous: for(uint i = arr.len()-1; i >= 0; i--) {...}

> I find unsigned types more dangerous than signed bounded types.

So you do agree that signed bounded types are dangerous, and it's only a matter of degrees between them and unsigned. Thank you.

Re: I was wrong, reflecting on the .NET design choices

#128

Earlier quoted context omitted.

We use regions to standardize the layouts of our classes. Except for trivial classes, you will find the same regions in the same positions making it eas(ier) to find, for example, all methods implementing an interface, or all of the private helper methods.

Regions are just useless visual clutter most of the time. You can put the methods/fields in the same order without using the regions. In my experience regions are a very bad practice used only to mask bad design that produced gigantic classes. The only place where I think they may be helpful is when you are writing a library and your class must be huge because you are implementing for example a Trie or some other col…

Not sure where to go from there. You've precluded the possibility that regions and good design should exist at the same time in the same file.

Where does the absolutism in the tech industry come from? We are a bunch of individuals who have individual experience and then try to form a view of the world that satisfies our experiences. What about the experiences you haven't had or conceived of? We are constantly rewriting the rules in our head to fit the new experiences we have every day to make sure we are right all of the time. Surely, our current world views are not complete or we would have no room to grow.

Still, I'll take your comment under advisement in case my classes are big, poorly designed non-Tries.

Re: I was wrong, reflecting on the .NET design choices

#129

Earlier quoted context omitted.

Things that have CLR-like generics work on the CLR. Anything else doesn't. E.g. Scala.

I don't really get the complaint. Even if they had type erasure you couldn't use Scala in the CLR because nobody has written a CLR target. And on the other hand, I don't know why there couldn't be a Scala implementation with true generics. A lot of crap like DummyImplicit and ClassTag is there for no other reason than to work around those limitations anyway.

I think it's largely an urban myth.

All expressive languages whose type systems don't have a 1-to-1 equivalence in the runtime's type system need to employ some degree of erasure.

The distinction between "erasure" and "no erasure" doesn't make much sense. It's always just about more (CLR 1, JVM = 2, JVM >= 10) erasure.

Re: I was wrong, reflecting on the .NET design choices

#130
post #98

"Another issue is that my approach to software design has significantly changed. Where I would previously do a lot of inheritance and explicit design patterns, I’m far more motivated toward using composition, instead." This, more than anything, has dramatically improved the quality of my designs... and made coding fun again. Immutability and Lambda functions have also had a tremendous impact on my designs. Is the ter…

I don't see how preferring composition over inheritance makes OOP less relevant. In fact, GoF even suggests using composition over inheritance in OOP. Nor do I see how immutability and lambda functions are mutually exclusive to OOP either. You can have all of these things and still reap plenty of benefits from OOP. The benefits of OO polymorphism and several decades worth of architectural design patterns are not irre…

It's possible to do Functional Programming with an OO language these days using anonymous methods/Lambdas.

The GoF patterns either need updating or perhaps we're on the verge of calling this hybrid environment something completely different (?)

Post reply on HN