4 ms·
How do you type the min > max constraint though?
by whilenot-dev 1y ago
How do you type the min > max constraint though?
- kuruczgy 1y agoWell, if your language has a sufficiently strong type system (namely, dependent types), you can take proofs of some properties as arguments. Example in Lean: def clamp (value min max : Float) {H : min < max} : Float := ...
- whilenot-dev 1y agoSure, but the author picked TypeScript nonetheless. TypeScript is not a runtime, but a mere type checker - JavaScript is the runtime and a highly dynamic language. This detail got somehow completely lost in the article, but is IMHO the main culprit why such validations aren't bad, or sometimes even preferred. The article also skipped over the following related topics: - When would you wrap errors from lower levels as your own? - What does "parse don't validate" mean when a TypeScript library gets transpiled to JavaScript?
- chongli 1y agoYou don’t need a runtime for dependent types. After type checking the types get erased during compilation.
- whilenot-dev 1y agoNobody would question that, but publishing a JavaScript library means that anyone using plain JavaScript can make use of it. Even though you aren't ever in control of the toolchain of your library's users, it's still your responsibility - as library author - to take that differences into account. If you'd transpile your library from Idris to JavaScript and publish it, these validations just can't be neglected at runtime. Type systems are just another model of the world at runtime.
- thomasmg 1y agoMany libraries throw an exception, panic, or silently swap the parameters at runtime. To detect this at compile time, you would need either min and max to be known at compile time, or a type system that supports value-dependent types. None of the popular language support this. (My language named 'Bau', which is not popular of course, support value-dependent types to avoid array-bound checks.)
- Animats 1y agoIn a compiled language, it takes one or two machine instructions to test assert!(b >= a); Works in C, C++, Go, Rust... Amusingly, nowhere in the original article is it mentioned that the article is only about Javascript. Languages should have compile time strong typing for at least the machine types: integers, floats, characters, strings, and booleans. If user defined types are handled as an "any" type resolved at run time, performance is OK, because there's enough overhead dealing with user defined structures that the run time check won't kill performance. (This is why Python needs NumPy to get decent numeric performance.)
- whilenot-dev 1y agoSure, use macros in function bodies. That won't affect the function signature in any meaningful way for the type checker and remains a check at runtime only, doesn't it? It seems like the point of the article was to not do that though, contrary to my own opinion, and I just wonder why...
- IshKebab 1y agoSome languages can do it, but most can't do you either throw an error or do something reasonable. In this case just returning min would be reasonable.
- roenxi 1y agoIf we're trying to solve problems with good design, use endpoint1 and endpoint2 and then the function sorts them. Having max and min is itself a bad design choice, the function doesn't need the caller to work that out. Why should the caller have to order the ends of the interval? It adds nothing but the possibility of calling the function wrong. So in this this case: export function clamp(value: number, endpoint1: number, endpoint2: number): number { return Math.min(Math.max(value, Math.min(endpoint1, endpoint2)), Math.max(endpoint1, endpoint2)); }
- whilenot-dev 1y agoSo an implicit fallback, but make it explicit through good design. Haven't even thought about this as a principle, since type checking persuades me to avoid anything implicit, thank you!
- vanviegen 1y agoThat would lead to unpleasant surprises. When calling the function from some loop and when the bounds are inclusive, it's pretty common for (correct) edge cases to exist where you'd call the function with end===start-1. The function would do the right thing by returning an empty set. You'd get duplicate/unexpected records in some cases, that may be hard to debug. It seems like your approach is just trying to ignore programmer errors, which is rarely a good idea.
- roenxi 1y agoI have no horse in the race and would usually just implement my clamp function the way the article does. However, if the clamp function clamping a number is an unpleasant surprise, I'm not going to accept that it is the fault of the clamp function. This hypothetical loop is buggy code and should be rewritten to expect clamp to clamp. It is a special type of madness if we're supporting a reliance on implementation specific failure modes of the clamp function when someone calls it with incoherent arguments.
- RHSeeger 1y ago
- Smaug123 1y agoDon't send `start` and `end`; send `start` and `lengthOfInterval`. (Whether that's a good idea in a given API is another question.)
- amavect 1y agoThat trades "min <= max" with "min + interval <= MAXINTEGER": if(number < min) return min; else if(number < min + interval) return number; // "if(number < max)" else return min + interval; // "return max"
- croes 1y agoIf min and max aren’t user inputs maybe we should trust the developer that they know what they are doing.
- fph 1y agoYou define an Interval type, and check the constraint in its constructor.
- sfn42 1y agoYou don't need to. One if statement to check that is not a problem. The problem occurs when you have a bunch of other ifs as well to check all kinds of other stuff that a type system would handle for you like nullability, incorrect types etc. Personally I just write JS like a typed language. I follow all the same rules as I would in Java or C# or whatever. It's not a perfect solution and I still don't like JS but it works.