Live data from Hacker News

The compiler is your best friend

blog.daniel-beskin.com

141–149 of 149 posts

Re: The compiler is your best friend

#141
post #86

Earlier quoted context omitted.

Ideally, if you can convince yourself something cannot happen, you can also convince the compiler, and get rid of the branch entirely by expressing the predicate as part of the type (or a function on the type, etc.) Language support for that varies. Rust is great, but not perfect. Typescript is surprisingly good in many cases. Enums and algebraic type systems are your friend. It'll never be 100% but it sure helps fil…

Until you have a bit flip or a silicon error. Or someone changed the floating point rounding mode.

Funny you should mention the floating point rounding mode, I actually had to fix a bug like that once. Our program worked fine, until you printed to an HP printer - then it crashed shortly after. It took forever to discover the cause - the printer driver was changing the floating point rounding mode and not restoring it. The fix was to set the mode to a known value each and every time after you printed something.

Re: The compiler is your best friend

#142

Earlier quoted context omitted.

I think we are talking past each other because we are optimizing for different domains. You seem to want the ergonomics of a structural type system like TypeScript where data shapes are fluid but explicitly unsound [1]. In that paradigm requiring a named Enum feels like clutter because it forces you to pause and define a relationship that you just want to infer. But Swift is a nominal static language designed for lon…

I agree that you should evaluate languages in their domains. At the end of the day, Swift is mainly used for systems and iOS apps. In this, it is inadequate, as you can tell by, again, most apps not using the type system to enumerate valid views but instead (because enums and union types more broadly are so clunky to use!) masses of uncoupled types in their views, allowing for many, many implicitly invalid states.

Lol Swiftui =/= Swift

Everything looks like nails to you with that TS hammer you're holding huh?

Re: The compiler is your best friend

#143
post #137

Earlier quoted context omitted.

Well, no, you're mistaken about Zig. There are custom panic handlers which are some kind of exceptions. I think Rust has something similar.

I'm not mistaken. Panic handlers are not any kind of exception.

I general I don't agree with that view, but indeed exceptions can be defined in different ways. An exception doesn't need to have a dedicated keyword or a glorified syntax to be one: if it's something that traverses the stack, has a handler or occurs on exceptional events, it's fair to call it an exception. A language doesn't have to support idiomatic use of exceptions for workflow control (such as C++) to have exceptions. Panic handlers, signals and interrupts might be defined exceptions as well. There are languages, such as Pony, that strive to have no runtime exceptions whatsoever. Not even panic handlers.

Re: The compiler is your best friend

#144

Earlier quoted context omitted.

I agree that you should evaluate languages in their domains. At the end of the day, Swift is mainly used for systems and iOS apps. In this, it is inadequate, as you can tell by, again, most apps not using the type system to enumerate valid views but instead (because enums and union types more broadly are so clunky to use!) masses of uncoupled types in their views, allowing for many, many implicitly invalid states.

Lol Swiftui =/= Swift Everything looks like nails to you with that TS hammer you're holding huh?

SwiftUI is almost certainly the biggest application of Swift; even if we relax it to just iOS applications you'll see the same issues appear with invalid state combinations.

Re: The compiler is your best friend

#145
post #140

Earlier quoted context omitted.

Are you saying decent code avoids indexing into arrays? Or are you saying it avoids doing so without certainty the bounds checks will succeed?

Decent code generally avoids indexing into arrays at all; if it does so then it does so in ways where the bound checks are so certain to succeed that you can usually explain it to the compiler (e.g. split an array into slices and access those slices).

that is what I thought you were saying, and it doesn't make much sense to me. AFAICT the point of arrays as a data structure is to allow relatively cheap indexing at the cost of more expensive resizing operations. What else would you do with an array other than index into it?

> e.g. split an array into slices and access those slices

How is this not indexing with a little abstraction? Aren't slices just a way of packaging an array with a length field it a standard way? I'm not aware of many array implementations without a length (and usually also capacity) field somewhere , so this seems like a mostly meaningless distinction (ie all sclices are arrays, right).

Re: The compiler is your best friend

#146
post #141
post #86

Earlier quoted context omitted.

Until you have a bit flip or a silicon error. Or someone changed the floating point rounding mode.

Funny you should mention the floating point rounding mode, I actually had to fix a bug like that once. Our program worked fine, until you printed to an HP printer - then it crashed shortly after. It took forever to discover the cause - the printer driver was changing the floating point rounding mode and not restoring it. The fix was to set the mode to a known value each and every time after you printed something.

That is amazingly devious. Well done HP.

Re: The compiler is your best friend

#147
post #140

Earlier quoted context omitted.

Decent code generally avoids indexing into arrays at all; if it does so then it does so in ways where the bound checks are so certain to succeed that you can usually explain it to the compiler (e.g. split an array into slices and access those slices).

that is what I thought you were saying, and it doesn't make much sense to me. AFAICT the point of arrays as a data structure is to allow relatively cheap indexing at the cost of more expensive resizing operations. What else would you do with an array other than index into it? > e.g. split an array into slices and access those slices How is this not indexing with a little abstraction? Aren't slices just a way of packa…

> AFAICT the point of arrays as a data structure is to allow relatively cheap indexing at the cost of more expensive resizing operations. What else would you do with an array other than index into it?

The main thing you do with arrays is bulk operations (e.g. multiply it by something), which doesn't require indexing into it. But yeah I think they're a fairly niche datastructure that shouldn't be privileged the way certain languages do.

> How is this not indexing with a little abstraction? Aren't slices just a way of packaging an array with a length field it a standard way?

Sure (well, offset and length rather than just a length) but the abstraction is safe whereas directly indexing into the array isn't.

Re: The compiler is your best friend

#148

> A common pattern would be to separate pure business logic from data fetching/writing. So instead of intertwining database calls with computation, you split into three separate phases: fetch, compute, store (a tiny ETL). First fetch all the data you need from a database, then you pass it to a (pure) function that produces some output, then pass the output of the pure function to a store procedure. Does anyone have a…

Sounds like a chain of “fetch compute store” stages, where the output of one is used as input to the next, where you then decide what other data needs to be fetched. So a pipeline instead of just a single shell and a single core.

Re: The compiler is your best friend

#149

Earlier quoted context omitted.

Ideally, if you can convince yourself something cannot happen, you can also convince the compiler, and get rid of the branch entirely by expressing the predicate as part of the type (or a function on the type, etc.) Language support for that varies. Rust is great, but not perfect. Typescript is surprisingly good in many cases. Enums and algebraic type systems are your friend. It'll never be 100% but it sure helps fil…

There is no inherent benefit in going and expressing that fact in a type. There are two potential concerns: 1) You think this state is impossible but you've made a mistake. In this case you want to make the problem as simple to reason about as possible. Sometimes types can help but other times it adds complexity when you need to force it to fit with the type system. People get too enamored with the fact that immutabl…

I think those concerns are straw men. The real concern is that the invariants we rely on should hold when the codebase changes in the future. Having the compiler check that automatically, quickly, and definitively every time is very useful.

This is what TFA is talking about with statements like "the compiler can track all code paths, now and forever."

Post reply on HN