Live data from Hacker News

What was the last breakthrough in computer programming? (2019)

quora.com

191–200 of 226 posts

Re: What was the last breakthrough in computer programming? (2019)

#191
post #173

Earlier quoted context omitted.

So... why NOT a type for even numbers? Or prime numbers? I'm not asking for someone to supply these things in the standard library of $FOOLANG. I'm saying that very few languages offer the tools to define such things without it being very cumbersome and often incurring significant runtime overhead. I know it's possible to do better because I've read up a bit on Ada. I've used Rust and written my own "newtypes" with t…

My point was that focusing on an empty string as the hill to die on was a touch artificial. My argument for why not, is that I don't think it pays off for most uses. You will wind up putting a ton of logic into the types, but then you have to do a ton of logic to correctly serialize into the types you have. Do I think there are times/places this could pay off? I'd hope/expect so. But where the data hits the wire is l…

> My point was that focusing on an empty string as the hill to die on was a touch artificial.

There must be a term for this phenomenon. My original reply that sparked this thread could be tl;dr as "I get frustrated with most programming languages. People at work know me as the guy that always complains about programming languages. One example of that is that I recently complained about most languages making it hard to statically guarantee that an input string is non-empty."

But then I get painted as "dying on a hill" for non-empty strings. It was one example, and it's not even the most important complaint I have about current programming languages. It was just one that came up this week at work because we literally had to deal with a bug from a REST API of a big company because THEY sent an empty string in a JSON payload that isn't supposed to be empty. Their code obviously missed a check somewhere and instead of sending a 404 response, they sent a bad payload (according to their own docs).

> My argument for why not, is that I don't think it pays off for most uses. You will wind up putting a ton of logic into the types, but then you have to do a ton of logic to correctly serialize into the types you have. > > Do I think there are times/places this could pay off? I'd hope/expect so. But where the data hits the wire is likely not where you can set many of these constraints such that your type system can really help with them.

This is hard to debate because we're speaking in very abstract terms. Obviously different domains will have different needs, etc.

So, unfortunately, I'm not sure I follow your argument for "why not". But here's my argument for "why". A lot of times, when we design software, it ends up working in "layers". Some function calls some other function calls some other function, etc.

If that "bottom" function requires something like a non-empty string (maybe that function is going to print a mailing label and it would be ridiculous to waste printer time on a blank label), you have two options: compile time enforcement or runtime enforcement.

In my experience, the majority of the time, "we" choose runtime enforcement, even in statically typed languages. What does runtime enforcement look like? Usually it's one of two things: you throw an exception or you return some kind of failure value.

If you throw an exception, it bubbles all the way up and your top level main loop has to catch it and understand how to handle it. That somewhat implies that your top level has to know everything that could go wrong at any layer of your code.

In addition, you now have a dilemma. You know that if you pass an empty-string through, that you'll eventually hit the function that requires a non-empty string. So you have two sub-options for this option. You can validate at the top level and pass it only if it's valid, or you can pass everything through and potentially do a lot of computational work before hitting the failing function and throwing away all that work. Most people choose to validate at the top level. So, you're validating at the top level anyway, and you're possibly validating in TWO places (the function doesn't know who might call it)- not DRY.

Other issues with the (unchecked) exception approach: It ALSO means that the type signature on your bottom-layer function is LYING. It "said" that you could pass it a string and it would return Whatever. It was wrong. You passed a string and instead of returning a Whatever, it started unwinding the stack for you. That's not static typing. Callers of this function can't trust its type signature to be complete. Instead they now have to read documentation (hopefully you wrote some). But if they already have to read documentation to understand what your function accepts and returns, why did we bother write the types at all? Just use Python or JavaScript and don't put types on anything. You just have to read the docs to know how to call it and the types will never get in the way.

The other runtime option is that your function might return a value that indicates failure. Some languages have "Result" or "Try" types. But if you do that, then the function that calls that bottom function has to handle the return value. There's a good chance that the "second layer" function can't really handle the failure, so it ALSO has to return a failure value. Etc, etc, until every function in the call chain has altered its return type to indicate that it may fail. Then your top level loop inspects the return value and handles the failure. I include Java-style checked exceptions in this category and not in the above "exception" category.

This return-failure-value approach pollutes all layers of your code even worse than if you just had a NonEmptyString type! Instead of the top level inspecting the bubbled up failure value after doing a bunch of computation, it could have just tried creating a NonEmptyString type from the input. If it failed, then the top-level handles the failure same as before, but didn't waste a bunch of CPU and clock time doing computations before hitting the failure. Furthermore, it's very DRY because the validation logic is in the type itself, either in some kind of type refinement mechanism, or in a factory function, etc.

Furthermore, the NonEmptyString type approach gives you more compile-time safety from bugs. If you try to call that bottom function with a maybe-empty-string, it won't compile. In the other cases, you'll only find out at runtime, even though you KNOW ahead of time that it's illegal to do so. I hope your tests cover everything.

Re: What was the last breakthrough in computer programming? (2019)

#192
post #94

Earlier quoted context omitted.

Right. And I look forward to advances in them. I can count how many times this would have actually helped my program, though...

Edit: It seems I confused dependant and algebraic types. Wouldn't you love the compiler giving an error when you write something that could result in illegal state? (Business rule violations for example) This is where such types shine. https://fsharpforfunandprofit.com/posts/designing-with-types...

I actually meant my "looking forward" to be sincere. I've used tooling that can point out exactly where an injection attack is possible, and that was quite nice. That said, u expect more of these tricks in my tooling, not necessarily cuffed by me.

Elsewhere I pointed to format strings checked at compile time for valid shape and arguments. This is actually common in lisps, ironically enough, and is akin to this sort of affordance.

I have just also seen too many projects fail that thought they could get it all in the types. It is very frustrating.

Re: What was the last breakthrough in computer programming? (2019)

#193
post #183

Earlier quoted context omitted.

The TLD part matters as some part of the email format is defined through the format of a valid host name. "something.com" is a valid host name, but "something.something" isn't currently a valid host name. So an email address "something@something.something" isn't a valid email address (currently). But at the end of the day this is all moot, imho. The "only" sane test to check the validity of an email address when some…

The point I was making is that whether or not you can successfully deliver email is not a sensible test of the validity of an email address, looking at the address purely as data. As I pointed out, my email archive contains many email addresses that are no longer ‘valid’ by your definition, but they are still valid as data. By your definition email address validity changes literally on a moment to moment basis. Addre…

I've got your point already before and I think it's valid.

That's why I've formulated my "definition" carefully:

> the validity of an email address when someone shows you one

It's of course not a "definition" someone could write down into a spec. But It's by far the best "informal validity check" in practice. It checks whether an email address is currently valid. You practically can't do more anyway!

The "formal validity" of an email address changes with time nowadays as I've pointed out: It depends directly on the formal validity of the host name part which can change over time given the fact that the list of TLDs changes over time (which wasn't the case at the time those specs have been written; fun fact: there is more than one spec, and they're contradicting each other).

To add on that there are two more important aspects: Firstly an email address you can't send mail to is mostly worthless in practice as it can't be used for its primary purpose. Secondly even perfectly "valid" addresses (by the spec) aren't accepted by a lot of parties that claim to handle email addresses! I guess a lot of systems would for example refuse an address looking like "-@-", wouldn't they? But it's perfectly valid!

http://sphinx.mythic-beasts.com/~pdw/cgi-bin/emailvalidate

http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html

https://stackoverflow.com/questions/5090272/can-anyone-expla...

We're moving in circles by now…

My initial argument was that claiming that it's "easy" to validated email addresses is wrong in multiple dimensions. In fact it's one of the more complicated questions out there (given the tragedy of the specs).

Re: What was the last breakthrough in computer programming? (2019)

#194
post #173

Earlier quoted context omitted.

My point was that focusing on an empty string as the hill to die on was a touch artificial. My argument for why not, is that I don't think it pays off for most uses. You will wind up putting a ton of logic into the types, but then you have to do a ton of logic to correctly serialize into the types you have. Do I think there are times/places this could pay off? I'd hope/expect so. But where the data hits the wire is l…

> My point was that focusing on an empty string as the hill to die on was a touch artificial. There must be a term for this phenomenon. My original reply that sparked this thread could be tl;dr as "I get frustrated with most programming languages. People at work know me as the guy that always complains about programming languages. One example of that is that I recently complained about most languages making it hard t…

First, an ack that I am almost certainly not touching all of your points. My apologies on that.

I think I am going to lean in on our arguments. I would rather change mine from "why not" to "why this isn't worth forcing".

That is, on the logic and aims, I fully agree with you. It is more that in practice, I have seen this fail too many times. I expect and look forward to it succeeding some day, but I still caution against jumping all in.

I should also ack that I am pretty happy with how common lisp does this. By mixing in read time and evaluation time, you can actually get a lot of this. I'm on my phone right now, but (format nil "~{") will not evaluate in sbcl. Instead, it will indicate an error in the format string. This is similar to how c will fail the build with Wall and Werror on similar bad format strings. Difference is that in lisp, you can add such evaluation time checks as a user.

As for why we do so much at runtime, my assertion is we check at runtime that which is determined at runtime. When getting data from outside the static program, there is little help the static type system can offer. So, deep in your system, get things out of strings and primitives as soon as you can. Don't pass a string username, pass a username. This gets you essentially what you want, but flags where the invalid value could have come from, as well as where it could have been used. And lets you add on other validations. AuthenticatedUsername and UnauthenticatedUsername, for example.

I get that you called those out as another category of error, but types are explicitly for that, as well.

And finally, in somewhat reverse form, I agree that arguments on specifics as a proxy for general are frustrating. For my part, apologies on adding to it.

Re: What was the last breakthrough in computer programming? (2019)

#195
post #67

Earlier quoted context omitted.

I'm not so sure that I sympathize with your example. Why not a type for even numbers? Odd, prime, not-prime, etc? You really are asking for a type that is "valid data." Commendable, but not a static property of data. As a fun example, what is a valid email address? Once established as valid, how long will it stay that way? If invalid, how long until it can become valid? Do I think better typing can be a boon? Absolut…

So... why NOT a type for even numbers? Or prime numbers? I'm not asking for someone to supply these things in the standard library of $FOOLANG. I'm saying that very few languages offer the tools to define such things without it being very cumbersome and often incurring significant runtime overhead. I know it's possible to do better because I've read up a bit on Ada. I've used Rust and written my own "newtypes" with t…

#1 You want to define a type with specific properties.

#2 You don't want to write a validator.

#3 Presumably you want to instantiate values of that type with user given input.

I don't think the three requirements make sense at all.

If you're willing to drop #3 you can always use some sort of enum-ish thing.

Re: What was the last breakthrough in computer programming? (2019)

#196
post #173

Earlier quoted context omitted.

My point was that focusing on an empty string as the hill to die on was a touch artificial. My argument for why not, is that I don't think it pays off for most uses. You will wind up putting a ton of logic into the types, but then you have to do a ton of logic to correctly serialize into the types you have. Do I think there are times/places this could pay off? I'd hope/expect so. But where the data hits the wire is l…

> My point was that focusing on an empty string as the hill to die on was a touch artificial. There must be a term for this phenomenon. My original reply that sparked this thread could be tl;dr as "I get frustrated with most programming languages. People at work know me as the guy that always complains about programming languages. One example of that is that I recently complained about most languages making it hard t…

Type checking is not a panacea. You cannot use type checking to spot and fix all bugs.

Funny enough the problem you raised was trivially solvable by creating a BNF-like checker based on the spec for "THEIR" API response data.

YOU just didn't want to do it.

I'm pretty sure there are solutions at least in C++ and Java (eg. validate at the edge and convert it into a ValidatedString type and use this type throughout), but honestly, you seem like the type that complains about missing incoherent features that can be trivially resolved (and not recognizing that the "imperfect" parts being an inherent part of the problem as opposed to being a deficiency in tooling), so I'll just leave my comment at that.

Re: What was the last breakthrough in computer programming? (2019)

#197
post #192

Earlier quoted context omitted.

Edit: It seems I confused dependant and algebraic types. Wouldn't you love the compiler giving an error when you write something that could result in illegal state? (Business rule violations for example) This is where such types shine. https://fsharpforfunandprofit.com/posts/designing-with-types...

I actually meant my "looking forward" to be sincere. I've used tooling that can point out exactly where an injection attack is possible, and that was quite nice. That said, u expect more of these tricks in my tooling, not necessarily cuffed by me. Elsewhere I pointed to format strings checked at compile time for valid shape and arguments. This is actually common in lisps, ironically enough, and is akin to this sort o…

It was more because of the, what I thought, was "counting on one hand". Seems like my brain tricked me.

Re: What was the last breakthrough in computer programming? (2019)

#198

Earlier quoted context omitted.

The point was that these were either dismissed or weren't considered by Kay when describing breakthroughs in computer programming. They aren't breakthroughs in computer programming languages, but IMO are breakthroughs in computer programming. > RCS - 1982 CVS - 1990 I don't accept CVS as a breakthrough in the same way as git has been. Back in 2000 - 10 years after CVS - using source control wasn't a given. We had art…

> We had articles like "The Joel Test"[1] encouraging teams to use source control. IMHO source control used more widely nowadays not thanks to git per se, but thanks to availability of free VCS hosting platforms like github.com Subversion IMHO is more beginner friendly than git, but we AFAIR didn't have good subversion platforms (with cheap of free private repos). Sourceforge added SVN in 2006 (which is late), but so…

I suspect this has a lot to do with the architecture of git allowing relatively "dumb" servers. To run a git server, you only need the capacity to receive, serve and compare git hashes and blobs.

For SVN at least (last I used it), the server is expected to perform all sorts of potentially expensive operations (esp. for large repos): diffs, merges, branches, etc. since the client does not have the full repo/history. Given at the time computing power was less cheap, it would mean that hosting SVN services incurred a non-trivial cost.

(And IIRC CVS was so bad that I don't think anyone in their right mind should actually try to host a free/cheap service around it.)

Also, initial versions of SVN was released around 2004, while git 1.0 was technically in 2005. It took a while for people to get used to git, but given its technical superiority (and its momentum given Linus' approval) and being less demanding on the server side to host, hosting for git was a correct decision to make anyways.

Re: What was the last breakthrough in computer programming? (2019)

#199
post #164

Earlier quoted context omitted.

Could you expand on what you mean by this? Because it sounds like a level of hype bordering on nonsense. 1. How is a SAT solver going to do formal verification? How do you turn a formal verification into a SAT problem? 2. You can only formally verify what your formal verifier can handle, which is usually somewhat less than "everything". Can your SAT-driven formal verifier verify that the worst case response time of t…

Lookup what CBMC does. SAT solvers will also be also be applied in traditional compilers soon. The remaining problem with formal verification and compilation is proof of termination, which is not a SAT problem. Running all test cases via cbcm is magnitudes faster than writing 100% coverage (only line cov, not covered values) tests. It's like one day vs one month. And I've never seen code with full value test coverage…

Even if everything you say is true, it's true the first time. Then I make a change to the code. Now if I have unit tests, I have to fix a test (maybe minutes, maybe an hour) and re-run the tests (minutes). Or I have to re-run the formal verification (a day).

Re: What was the last breakthrough in computer programming? (2019)

#200
post #195

Earlier quoted context omitted.

So... why NOT a type for even numbers? Or prime numbers? I'm not asking for someone to supply these things in the standard library of $FOOLANG. I'm saying that very few languages offer the tools to define such things without it being very cumbersome and often incurring significant runtime overhead. I know it's possible to do better because I've read up a bit on Ada. I've used Rust and written my own "newtypes" with t…

#1 You want to define a type with specific properties. #2 You don't want to write a validator. #3 Presumably you want to instantiate values of that type with user given input. I don't think the three requirements make sense at all. If you're willing to drop #3 you can always use some sort of enum-ish thing.

I don't want to write a validator and litter calls to it throughout my code base.

I want the "validator" to be the constructor of a type (or a refinement mechanism, etc).

Then every function in my code base can have a clear contract via its type signature. What good is a function that says it accepts a string and returns a string if it actually just explodes when given some strings? That's not the same thing as returning a string...

I want to do three-ish things:

1. Make my function's type signature be correct. It is NOT correct to say that you accept an "int" but actually crash if you're given `0`.

2. Push bug catching to compile time instead of runtime. Calling a validation function inside a function is a runtime check. In the meantime I can write 100 calls to a function that I know will cause a crash and the compiler will say nothing.

3. Push type requirements to the callers of functions. Everyone preaches "validate at the edges", but if your function signatures had very precise types, that would happen "automatically." Your code won't compile unless you pipe the correct types all the way from the top function call down to the bottom one.

Post reply on HN