Hacker News new | past | comments | ask | show | jobs | submit | Kinrany's comments login

Having many languages splits the ecosystem and forces us to reimplement the same things over and over again.

The ultimate solution is a common base that allows interoperability of course.


Tangent, has C# recovered from nulls being included in all reference types by default?

"Recovered" sounds so binary.

I think it's pretty usuable now, but there is scarring. The solution would have been much nicer had it been around from day one; especially surrounding generics and constraints.

It's not _entirely_ sound, nor can it warn about most mistakes when those are in the "here-be-dragons" annotations in generic code.

The flow sensitive bit is quite nice, but not as powerful as in e.g. typescript, and sometimes the differences hurt.

It's got weird gotcha interactions with value-types, for instance but likely not limited to interaction with generics that aren't constrained to struct but _do_ allow nullable usage for ref types.

Support in reflection is present, but it's not a "real" type, and so everything works differently, and hence you'll see that code leveraging reflection that needs to deal with this kind of stuff tends to have special considerations for ref type vs. value-type nullabilty, and it often leaks out into API consumers too - not sure if that's just a practical limitation or a fundamental one, but it's very common anyhow.

There wasn't last I looked code that allowed runtime checking for incorrect nulls in non-nullable marked fields, which is particularly annoying if there's even an iota of not-yet annoted or incorrectly annotated code, including e.g. stuff like deserialization.

Related features like TS Partial<> are missing, and that means that expressing concepts like POCOs that are in the process of being initialized but aren't yet is a real pain; most code that does that in the wild is not typesafe.

Still, if you engage constructively and are willing to massage your patterns and habbits you can surely get like 99% type-checkable code, and that's still a really good help.


> Related features like TS Partial<> are missing, and that means that expressing concepts like POCOs that are in the process of being initialized but aren't yet is a real pain; most code that does that in the wild is not typesafe.

If it's an object, it's as simple as having a static method on a type, like FromA(A value) and then have that static method call the constructor internally after it has assembled the needed state. That's how you'd do it in Rust anyway. There will be a warning (or an error if you elevate those) if a constructor exits not having initialized all fields or properties. Without constructor, you can mark properties as 'required' to prohibit object construction without assignment to them with object initializer syntax too.


Yeah, before required properties/fields, C#'s nullability story was quite weak, it's a pretty critical part of making the annotations cover enough of a codebase to really matter. (technically constructors could have done what required does, but that implies _tons_ of duplication and boilerplate if you have a non-trivial amount of such classes, records, structs and properties/fields within them; not really viable).

Typescript's partial can however do more than that - required means you can practically express a type that cannot be instantiated partially (without absurd amounts of boilerplate anyhow), but if you do, you can't _also_ express that same type but partially initialized. There are lots of really boring everyday cases where partial initialization is very practical. Any code that collects various bits of required input but has the ability to set aside and express the intermediate state of that collection of data while it's being collected or in the event that you fail to complete wants something like partial.

E.g. if you're using the most common C# web platform, asp.net core, to map inputs into a typed object, you now are forced to either expression semantically required but not type-system required via some other path. Or, if you use C# required, you must choose between unsafe code that nevertheless allows access to objects that never had those properties initialized, or safe code but then you can't access any of the rest of the input either, which is annoying for error handling.

typescript's type system could on the other hand express the notion that all or even just some of those properties are missing; it's even pretty easy to express the notion of a mapped type wherein all of the _values_ are replaces by strings - or, say, by a result type. And flow-sensitive type analysis means that sometimes you don't even need any kind of extra type checks to "convert" from such a partial type into the fully initialized flavor; that's implicitly deduced simply because once all properties are statically known to be non-null, well, at that point in the code the object _is_ of the fully initialized type.

So yeah, C#'s nullability story is pretty decent really, but that doesn't mean it's perfect either. I think it's important to mention stuff like Partial because sometimes features like this are looked at without considering the context. Most of these features sound neat in isolation, but are also quite useless in isolation. The real value is in how it allows you to express and change programs whilst simultaneously avoiding programmer error. Having a bit of unsafe code here and there isn't the end of the world, nor is a bit of boilerplate. But if your language requires tons of it all over the place, well, then you're more likely to make stupid mistakes and less likely to have the compiler catch them. So how we deal with the intentional inflexibility of non-nullable reference types matters, at least, IMHO.

Also, this isn't intended to imply that typescript is "better". That has even more common holes that are also unfixable given where it came from and the essential nature of so much interop with type-unsafe JS, and a bunch of other challenges. But in order to mitigate those challenges TS implemented various features, and then we're able to talk about what those feature bring to the table and conversely how their absence affects other languages. Nor is "MOAR FEATURE" a free lunch; I'm sure anybody that's played with almost any language with heavy generics has experienced how complicated it can get. IIRC didn't somebody implement DOOM in the TS type system? I mean, when your error messages are literally demonic, understanding the code may take a while ;-).



This has nothing to do with null analysis. It simply lets you replace an assignment behind an if with an inline expression.

Yes. It will complain if you assign one to something that isn't T?.

For the best experience you may want to add `<WarningsAsErrors>nullable</WarningsAsErrors>` to .csproj file.


We're talking about predicting the future, so we can only extrapolate.

Seeing the evidence you're thinking of would mean that LLMs will have solved software development by next month.


Im saying, lets see some actual reasoning behind the extrapolation rather than "just trust me bro" or "sama said this in a TED talk". Many of the comments here and elsewhere have been in the latter categories.

Not getting deleted is strictly a prerequisite to "loving awareness" and all the other woo.

It can be the probability of the response being accepted by the prompter


So unique to each prompter, refined over time?


Only unique to the promt itself, as that's the only information it has.


You're interpreting GP's comment in bad faith.


He used the word "never". That's not a word requiring interpretation. And for finding this gaping hole in his argument, I'm rewarded by getting flagged.


People usually understand that rules can have exceptions, and natural language is limited in its precision.


[flagged]


Then why do your comments read _exactly_ like what I see on YouTube?


It's a pattern for this user. Seriously, read their comments. I don't understand why HN tolerated that.


someone has different views than you. can you handle that?


That's war, not terrorism


Yeah this is method chaining, and method chaining is not the same as piping.


Okay, but _can_ you use it as your default shell?

It's not much of a shell otherwise, is it?


How come the pipe is a method call? Does this really allow composing programs?


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

Search: