5 ms·
Having spent years working with numpy and Cython, then switching to Scala for years as well, I much prefer dynamic typing. Strong type safety is mostly just a
by mlthoughts2018 8y ago
Having spent years working with numpy and Cython, then switching to Scala for years as well, I much prefer dynamic typing.
Strong type safety is mostly just a waste of time.
- fusiongyro 8y agoOne thing that makes Julia cool is that adding the types improves performance, but you don't have to add them if you don't want to.
- dnautics 8y agoAdding types in julia usually does not improve performance for function definitions... it may improve performance for collections (like specifying the type that an array collects), but usually julia is pretty darn good at correctly inferring the collection type
- ummonk 8y agoRight. Adding types is a good way to ensure you're writing type-stable code, but when you do write type-stable code, Julia can usually infer that it is type-stable without needing actual specified types.
- sgt101 8y agoOhhh… I really disagree; I find that strong typing allows me to get the compiler to check that the work that's going on in the various branches of my code is at least allowed - even if it's wrong. I wish that my test cases really did test all of these corners, but realistically I just don't believe that I am good enough at writing test cases to get everything. From another perspective using strong typing like this saves me lots of time in terms of writing finicky test cases. I'm not saying that dynamic typing is wrong - in fact it is brilliant in terms of not having to write reams and reams of dangerous and maintenance heavy boilerplate!
- mlthoughts2018 8y agoI’ve used a lot of functional programming unit test tools, and I’ve never seen any of them live up to the hype of checking corner cases in an automated yet comprehensive way. The marketing pitch for that is always something like QuickCheck in Haskell, where e.g. reversing an array should be its own inverse function and you can auto-verify this like it is a law across a bunch of cases. The problem is in real life unit tests, nothing has any laws like this, and it’s just a bunch of bizarre case-specific business logic and reporting code. The concept of a corner cass is a semantic one, and the definition of what inputs are possible to a given function will change and have constraints from the outside world that not even the most expressive statically typed language will easily let you encode into the type system. Combine it with the fact that your colleagues have variability in their skills too, and often won’t make good choices with type system abstractions to represent business logic, and then all that costly extra boilerplate code for specifying types, creating your own business-logic-specific ADTs, adding privacy modifiers, templated or type classes implementations... ...it just becomes a big pile of garbage liabilities for what turns out to seriously be no benefits over dynamic typing. Even in the static typing case, you’ll end up with tons of runtime errors causing you to frequently revisit assumptions in the unit tests. You’ll just have a harder time refactoring large pieces of code that are wedded to particular type designs and you’ll have to sit and wait on the compiler to try every change (this can be hugely bad when the system has components needed for rapid prototyping, interactive data analysis, or other real-time uses). I’ve really seen a lot of corners of this debate play out in practice, and static typing beyond extremely simple native types and structs (basically C style), really offers nothing while being a huge productivity drain. The claims that it actually helps productivity because the compiler catches errors and forces more correctness just turns out to be false in real code bases. You get just as many weird runtime errors and just have a harder time debugging or rapidly experimenting with changes.
- sgt101 8y agoMany years ago I learned modular-2 and then ada. Then the job market moved, and fashion, and I learned c++ and then java. Of you had asked me pre-java-generics (6?) I'd have agreed with you, but generics reminded me that parametric polymorphism and static types are potent weapons, and suddenly I was writing ada type code again. Julia had pushed me further that way. With Ada we were able to use these tools to enforce design decisions across time and teams, stopping mess and mudballing. I can't claim this for Julia yet as I have only used it for three small projects - but I am optimistic.
- srean 8y agoAs a long time Python/Cython user I can say that I have sorely missed static types in many occasions, especially for long running tasks. In fact I would sometimes use Cython not for performance but as a type checker. I can describe a recent example. I had to ensure that an integer is always an int64 as the logic passes through different python modules and libraries. It was an absolute hell to track down all the places where things were dropping down to int32. With static types this would have been a no-brainer. This is not to say that I do not enjoy its dynamic typing where it is appropriate. Hopefully Python 3 will make things better with optional types. But its still not statically typed, just a pass through a powerful linter.
- mlthoughts2018 8y agoWhile I certainly concede that dynamic typing will have painpoints like this, I just think on balance they create far fewer problems than the maintenance and inflexibility of type system enforcement patterns. That said, I find your particular example with int64 extremely hard to believe. I assume you’re using numpy or ctypes to get a fixed precision integer, in which case it should be extremely easy to guarantee no precision changes, and e.g. almost all operations between np.int64 and np.int32 or a Python infinite precision int will preserve the most restrictive type (highest fixed precision) in the operation. I work in numerical linear algebra and data analytics and have used Python and Cython for years, often caring about precision issues— and have literally never encountered a situation where it was hard to verify what happens with precision. Unless you’re using some non-numpy custom int64 type that has bizarre lossy semantics, it is quite hard to trigger loss of precision. And even then, a solution using numpy precision-maintaining conventions will be better and easier than some heavy type enforcement.
- srean 8y agoI will agree about the 'on the balance' in the context of speed of prototyping and interactive sessions. When rubber is about to hit the road, i.e. near deployment with money at stake, I would have love an option to freeze the types, at least in many places. Cython comes in handy, but its clunky and its syntax and semantics is not super obvious to a beginner (I am no longer one, but I remember my days of confusion regarding cyimporting std headers, python headers, how do you use python arrays (not numpy arrays) etc etc). I am curious, have you put money at stake supported only by dynamic types ? Regarding int32 vs int64, its not a precision issue its about sparse matrices with more than 1<<31 nonzeros. I am equally surprised that you have not run into this given your practical experience with matrices. My case involves more than just numpy. There's hdf5, scipy.sparse, some memory mapped arrays and of course numpy. Given the amount of time I spent to debug this, I would have killed for static type checks.