Live data from Hacker News

Parse, Don't Validate (2019)

lexi-lambda.github.io

111–120 of 288 posts

Re: Parse, Don't Validate (2019)

#111

Earlier quoted context omitted.

Plenty of people know multiple statically typed and dynamic languages, and multiple functional, imperative, and other languages; and use dynamic languages for some things but not other things. The set of people using dynamic languages isn't just "those that haven't had their eyes opened yet to what static languages can do". Different languages and paradigms make different things easier. I do believe that, for long la…

> The set of people using dynamic languages isn't just "those that haven't had their eyes opened yet to what static languages can do". This was more aimed at people who are new to the idea of parsing over validating. In a strong statically typed language, the type system would naturally guide you to use this approach so if this isn't natural to you then time in other languages would probably be worthwhile.

My misunderstanding then. Your comment came across (to me) as saying that people using dynamic language just don't know any better; that, if they would just learn a static language, they would suddenly understand the error of their ways. That's the thought that I was responding to.

Re: Parse, Don't Validate (2019)

#112

From the Twitter link: > IME, people in dynamic languages almost never program this way, though—they prefer to use validation and some form of shotgun parsing. My guess as to why? Writing that kind of code in dynamically-typed languages is often a lot more boilerplate than it is in statically-typed ones! I feel that once you've got experience working in (usually functional) programming languages with strong static ty…

Plenty of people know multiple statically typed and dynamic languages, and multiple functional, imperative, and other languages; and use dynamic languages for some things but not other things. The set of people using dynamic languages isn't just "those that haven't had their eyes opened yet to what static languages can do". Different languages and paradigms make different things easier. I do believe that, for long la…

For sure. I do most of my work in situations of high volatility of domain and requirements and relatively high risk. (E.g., startups, projects in new areas.)

Static typing really appeals to me on a personal level. I enjoy the process of analysis it requires. I love the notion of eliminating whole classes of bugs. It feels way more tidy. I took Odersky's Scala class for fun and loved it.

But in practice, they're just a bad match for projects where the defining characteristic is unstable ground. They force artificial clarity when the reality is murky. And they impose costs that pay off in the long run, which only matters if the project has a long run. If I'm building something where we don't know where we're going, I'll reach for something like Python or Ruby to start.

This has been brought home to me by doing interviews recently. I have a sample problem that we pair on for an hour or so; there are 4 user stories. It involves a back end and a web front end. People can use any tools they want. My goal isn't to get particular things done; it's to see them at their best.

After doing a couple dozen, I'm seeing a pattern: developers using static tooling (e.g., Java, TypeScript) get circa half as much done as people using dynamic tooling (Python, plain JS). In the time when people in static contexts are still defining interfaces and types, people using dynamic tools are putting useful things on the page. Making a change in the static code often requires multiple tweaks in situations where it's one change in the dynamic code. It makes the extra costs of static tooling really obvious.

That doesn't harm the static-language interviewees, I should underline. The goal is to see how they work. But it was interesting to see that it wasn't just me feeling the extra costs. And those costs are only worth paying when they create payoffs down the road.

Re: Parse, Don't Validate (2019)

#113
post #94

Earlier quoted context omitted.

Tractability vs possibility. You don't grok the difference. You can implement EVERYTHING in Brainfuck. Tractability is the reason you don't. The goalposts are exactly where I set them. With my first comment. "Every programming paradigm is a good idea if the respective trade-offs are acceptable to you."

Its perfectly tractable though. Just because you don't understand it or don't think it is, doesn't make it true. > "Every programming paradigm is a good idea if the respective trade-offs are acceptable to you." That's not what we are responding to. Nobody here is arguing over this statement. We are responding to you assertion that static typed compile-time checked languages _prevent_ you from having dynamic dispatch…

[deleted]

Re: Parse, Don't Validate (2019)

#114
I couldn't agree with this post more.

I found myself replacing the configuration parsing code in a C++ project that was littered with exactly the validation issues described, and converted it to that which the author advocates. The result was a vastly more readable and maintainable codebase, and it was faster and less buggy to boot.

Another nice advantage is that the types are providing free/self- documentation, too.

Re: Parse, Don't Validate (2019)

#115
post #68

Earlier quoted context omitted.

This is a trivial and obvious implication of Turing completeness. Why do you even bother making the point? With the right amount of indirection/abstraction you can implement everything in Assembly. But you don't. Because you like all the heavy lifting the language does for you. First Class citizens is what we are actually interested in when we talk about programming language paradigm-choices. https://en.wikipedia.org…

Did you mean something other than "dynamic dispatch", or what do you mean by "first class support"? No offense, but your claim sounds like you're confused to me, but maybe I am the one confused. AFAIK I do dynamic dispatch all the time in strongly typed languages. Can you show an example that a strongly typed language can't accomplish?

>I do dynamic dispatch all the time in strongly typed languages.

I believe semantics is getting in our way of communicating.

You don't do dynamic dispatch ___ALL___ the time. You only do it at runtime. And you only do static type safety at compile time. Those are different times.

You can't have both of those features at the __SAME TME__, therefore you can't have both features ALL the time. They are mutually exclusive.

Re: Parse, Don't Validate (2019)

#116
post #108

Earlier quoted context omitted.

Its perfectly tractable though. Just because you don't understand it or don't think it is, doesn't make it true. > "Every programming paradigm is a good idea if the respective trade-offs are acceptable to you." That's not what we are responding to. Nobody here is arguing over this statement. We are responding to you assertion that static typed compile-time checked languages _prevent_ you from having dynamic dispatch…

Nothing PREVENTS you from doing anything with a computer except your own, mutually incompatible design goals! I am pointing out (and you seem to be agreeing) that you can't have static type safety AND dynamic dispatch _______AT THE SAME TIME__________ Which is why you get static type safety ____AT COMPILE TIME____. And dynamic dispatch ____AT RUNTIME___. You were the one moving the goal posts all along by flip-floppi…

Ok, I think I understand what you are trying to say. Instead of telling us how we don’t understand various things, how about next time you define your terms, choose your words more carefully and be clearer with your explanations, so we can actually understand what you’re trying to say.

So let me restate what I think you meant. Maybe I’m wrong.

> a limitation of compile time static types is that they cannot do dynamic dispatch, which is relies on information that isn’t known at compile time.

I think we can all agree on this?

Note that I said it’s a limitation, not that it’s bad. Limitations don’t make something bad in themselves, they only constrain when it is an appropriate tool. You wouldn’t say that a submarine is bad because it can’t go on land? It’s a limitation but that doesn’t make it bad.

Then you said that because of this limitation, “you can’t have routers”.

But you can have routers in static languages like C++, Rust or even Haskell.

You have a choice (trade off) to make:

1. either you give up on some dynamism to keep compile time checks by enumerating the types you can dispatch on (as std::variant does)

2. or you choose to give up static checking (for this part of your code only!) and move it to runtime first full dynamic logic (as std::any does). When giving up compile time safety for one part of your code, you do not give it up for all of your code, because you can runtime validate then on the boundaries going back into statically checked code paths, so the compiler cab assume that they are valid if they get back in (as the runtime checks would reject bad types)

Neither case is “you can’t have routers”, but sure you can’t have fully dynamic routers purely at compile time.

Also, both options are perfectly tractable and both cases are typically first class language features (at least in the static types languages I’ve used). In no case are the “bad” options, despite each option having different limitations.

In a dynamic-types-only language, you don’t get to choose the trade offs at all, you only get “fully dynamic no compile time checking, runtime checks only”.

Note also that in real life, few things are truly fully dynamic. You are always constrained by the operations that are expected to be carried out on the dynamic data and while you might not know at runtime what days you could get, you DO know what operations you expect to run on the data. And you can perform compile time checks around that.

So for a router, so you really need it to be fully dynamic? Or can you live with it being generic (ie it’s a library that does routing and it can support any type, but you constrain it to known types when you actually use it). If so, you have options that maintain type safety: you can use OOP inheritance, you can use enumerated types like std::variant, you can use generics/templates. The library works for any types but the user chooses what types to implement based on the operations that will be performed on the data. Even dynamic types do this, they just defer it to runtime.

Or you can have the router operate on purely dynamic types but the handlers that are routed to are statically typed (eg if in C++ the router uses std::any and the handler registers what types it can accept and the router checks validity before handing the data off).

Re: Parse, Don't Validate (2019)

#117
post #108

Earlier quoted context omitted.

Nothing PREVENTS you from doing anything with a computer except your own, mutually incompatible design goals! I am pointing out (and you seem to be agreeing) that you can't have static type safety AND dynamic dispatch _______AT THE SAME TIME__________ Which is why you get static type safety ____AT COMPILE TIME____. And dynamic dispatch ____AT RUNTIME___. You were the one moving the goal posts all along by flip-floppi…

Ok, I think I understand what you are trying to say. Instead of telling us how we don’t understand various things, how about next time you define your terms, choose your words more carefully and be clearer with your explanations, so we can actually understand what you’re trying to say. So let me restate what I think you meant. Maybe I’m wrong. > a limitation of compile time static types is that they cannot do dynamic…

I chose my words as well as I thought necessary.

Had I know I am going to be lynched for my choices - I would've chosen them even better. Or maybe I would've just censored myself.

How about you practice the principle of charity next time?

Re: Parse, Don't Validate (2019)

#118
post #95
post #90

Earlier quoted context omitted.

> Neither C++ nor Rust have dynamic dispatch You appear to be using some other definition of dynamic dispatch than the rest of the software industry...

You appear to be conflating compilers with runtimes. Dynamic dispatch happens at runtime. C++ and Rust are compile-time tools, not runtimes.

You are wrong. C++ supports dynamic dispatch.

Please read about it on Wikipedia

https://en.m.wikipedia.org/wiki/Dynamic_dispatch

And for the future to not litter HN with comments like these, next time 10 different people in thread are all explaining to you why you're mistaken, take a moment to try to listen and think through what they're saying instead of just digging deeper.

Having an open mind to learning something new, not just arguing a point is a great approach to life.

Re: Parse, Don't Validate (2019)

#119
post #84

This principle is how pydantic[0] utterly revolutionized my python development experience. I went from constantly having to test functions in repls, writing tons of validation boilerplate, and still getting TypeErrors and NoneTypeErrors and AttributeErrors left and right to like...just writing code. And it working ! Like one time I wrote a few hundred lines of python over the course of a day and then just ran it... a…

I've found this to be simply a matter of experience, not tooling. As the years go by I find the majority of my code just working right - never touched anything like pydantic or validation boilerplate for my own code, besides having to write unit tests as an afterthought at work to keep the coverage metric up.

Re: Parse, Don't Validate (2019)

#120

Earlier quoted context omitted.

I wish it had actual proper examples. I've no idea how to use that.

Check out https://github.com/gcanti/io-ts/blob/master/index.md instead. I find it more composable and you can define a codec and get a native type from it so you are only defining things once.

Assert combinators are composable, light, terse (very little verbosity), types can be defined in single place, instead of type/interface definition you can use return type of assert function.

They don’t go into deep category theory, you won’t find monads and friends, they are first level, straightforward any typescript developer can pick up in minutes - this is by design. It stops at combinators in typescript to solve very specific problem and nothing more. Haskell in ts is not the goal of this npm.

Post reply on HN