Live data from Hacker News

Think Julia: How to Think Like a Computer Scientist

benlauwens.github.io

61–70 of 74 posts

Re: Think Julia: How to Think Like a Computer Scientist

#61
post #36

Earlier quoted context omitted.

Ohhh… 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 sa…

I’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…

Many 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.

Re: Think Julia: How to Think Like a Computer Scientist

#62
post #60

Earlier quoted context omitted.

> “You have to ensure that it falls back to C code that uses Int64 for indexing the arrays. I am sure you are not saying that you do sparse multiplications of this size in pure python.” For csc and csr matrices at least, these operations typically iterate the underlying indices, indptr and data arrays, and csc `nonzero` uses len(indices), which both relies on (eventually) the C-level call to malloc that defined `indi…

Lets not weasel with 'typically'. The code that will get called for a multiply is this https://github.com/scipy/scipy/blob/master/scipy/sparse/spar... and https://github.com/scipy/scipy/blob/master/scipy/sparse/spar... It's important that decisions at the python level trickles down to the correct choice when it comes down to this level. On a 64 bit architecture one would expect that using 64bit int arrays for indices…

The code you linked actually seems to refute your claim of this precision error, at least for multiply, because it is using npy_intp for nnz, which will be int64 on a 64 bit platform, and there is even an overflow check below!

Can you post a gist or link some other concrete example to show how it can overflow the intp type based on large nnz? Reading the code, it looks like this could not happen.

(Note that the entire second step function wouldn’t have this problem, because it’s accessing indices inside the other arrays, after nnz has already been computed, and is not looping over a variable that would overflow, apart from nnz from the first function, which I pointed out above seems not to overflow unless you’re compiling things in a non-standard way that affects npy_intp).

I don’t know what your comments about malloc having nothing to do with it are though. That is how numpy arrays possess their post-allocation result for __len__, such as for indices, indptr and data in csr. So __len__ could not overflow an int type (since it requires the platform address space’s int type to allocate underlying contiguous arrays and returns a Python integer).

Re: Think Julia: How to Think Like a Computer Scientist

#63
post #61

Earlier quoted context omitted.

I’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…

Many 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…

I don’t know. My primary corporate experiences with this are all in Scala and Haskell (with teams that have very veteran programmers in each), and the results were terrible.

I liken it to David Deutsch’s comments on good systems of government in his book The Beginning of Infinity where he advised that the trait you should use to evaluate a system of government is not whether it produces good policies, but rather how easy it is to remove bad policies.

Languages don’t cause people to invent better designs for mapping between the real world and software abstractions. They can provide tools to help, but they don’t cause the design.

But statically typed languages do create boilerplate and sunk cost fallacies leading to living with bad designs and accepting limitations that have to be coded around.

Dynamic typing compares favorably in this regard: it is very easy to rip things out or treat a function as if it implicitly handles multiple dispatch (because you can specialize on runtime types with no overhead and no enforcement on type signatures or type bounds), and quickly get feedback on whether a design will be a good idea, or what things would look like ripping out some bad design.

I think exactly what you describe is the hyped up promise that static typing, especially in functional languages, fails to actually deliver in practice. You can still write production code that way, just incurring costs of maintenance of more code & boilerplate without the supposed offsetting benefits of catching more bugs, reducing runtime errors, or communicating design more smoothly in the type system, except in isolated, small parochial cases.

Re: Think Julia: How to Think Like a Computer Scientist

#64

Earlier quoted context omitted.

Early on (as a heavy Stata and Python user) I tried Julia and got quite discouraged by its messy treatment of missing values (and weights, etc). I've also tried R but also found lots of inconsistencies, so not enough reason to switch, besides when plotting nice graphs. But I would say Julia is increasingly getting there. Comparable packages are WAY easier to write in Julia than in Stata/Mata, while being faster, so a…

you were somehow satisfied with the way stata handles missing values??? gen x = y if z > 4 // headaches abound Julia's missing value support is great now and is only going to get better. You have to be more careful with how you use them, but you won't get anything like the output above in julia. * For reference, stata uses +Inf as missing value, so any operation with "greater then" is going to assign missing values t…

One of my least favorite quirks of Stata

Re: Think Julia: How to Think Like a Computer Scientist

#65
post #35

Earlier quoted context omitted.

I've only been learning for about a week, but I think if you're a nerd for language design, you will appreciate it on an aesthetic level as a very tight design around a powerful concept. Common Lisp also has multiple dispatch, but I feel the integration of it into all the nooks and crannies of Julia really pays off. Julia's performance doesn't appear as a side effect of building on the LLVM or because they over-optim…

there's an interesting issue wrt. maths and Juila; yesterday there was a story : https://news.ycombinator.com/item?id=17781475 on unmaintainable code. One of the clauses mentions the use of non standard characters as variable names : δ σ π ρ for example and cites the issue as having to deal with the code in a simple text editor. I recently wrote a simulator intended as the demonstration of some issues in a paper. I f…

[deleted]

Re: Think Julia: How to Think Like a Computer Scientist

#66
post #35

Earlier quoted context omitted.

there's an interesting issue wrt. maths and Juila; yesterday there was a story : https://news.ycombinator.com/item?id=17781475 on unmaintainable code. One of the clauses mentions the use of non standard characters as variable names : δ σ π ρ for example and cites the issue as having to deal with the code in a simple text editor. I recently wrote a simulator intended as the demonstration of some issues in a paper. I f…

The only issue here is with input devices. The Greek alphabet is standard Unicode, so it's not more expensive to render or manipulate for your text editor compared to standard latin.

To be fair, input devices are a pretty serious issue here. Probably the single most common operation I do on code is search it. If I can't type what I'm searching for easily, that's pretty annoying.

Re: Think Julia: How to Think Like a Computer Scientist

#67
post #60

Earlier quoted context omitted.

Lets not weasel with 'typically'. The code that will get called for a multiply is this https://github.com/scipy/scipy/blob/master/scipy/sparse/spar... and https://github.com/scipy/scipy/blob/master/scipy/sparse/spar... It's important that decisions at the python level trickles down to the correct choice when it comes down to this level. On a 64 bit architecture one would expect that using 64bit int arrays for indices…

The code you linked actually seems to refute your claim of this precision error, at least for multiply, because it is using npy_intp for nnz, which will be int64 on a 64 bit platform, and there is even an overflow check below! Can you post a gist or link some other concrete example to show how it can overflow the intp type based on large nnz? Reading the code, it looks like this could not happen. (Note that the entir…

Can't help but say this, you are seriously confused. Not necessarily your fault, as obviously you dont have the full code.

I have mentioned earlier that it is not about precision but about index space. I don't think it's going to be productive use of my time to continue this thread.

One specific reason you are getting confused is because you are looking at function calls in isolation not the entire chain of calls through the different Python ecosystem libraries. The problem is the indptr and indices arrays that begin their life as int64 arrays get transformed into int32 arrays in specific code paths.

By stating that malloc is not relevant I mean its not relevant in this particular instance. By the time control reaches malloc the type mismatch damage has laready taken place.

Getting a runtime error is far from the end of the matter even if in certain cases we do get runtime errors. What static types saves the user from is the hunting needed to find out where in the chain of functions are we losing the type invariant we need.

Stopping such bugs is a no-brainer with static types. You claimed at one point up-streams [0] that type systems cannot rule out such errors. If you believe that, this discussion is a waste of time. That's one of the lowest forms of errors a type-system prevents. Your comments like these make me doubt your grasp over these things.

BTW, not sure if you believe large rows and cols imply large nnz [1]. That's not how sparse works.

Given your handle I would have expected you to be familiar, this is bread and butter stuff in day to day ML. On the other hand if your background was stats I would expect less of computational nitty gritties. Nothing wrong with that they focus on different but important aspects.

If you really care I would encourage you to track the flow of code from csr creation in scipy. sparse using memory mapped arrays of indptr, indices and nnz to the C code that will get invoked on two such objects, carefully. The key word here is carefully. There is no nonstandard compilation because there is no compilation. Its about dispatch to the correct C function.

You seem to believe that on a 64 bit platform such indexing error will not happen. That's patently false because it happened many times.

In other words, you are saying your ill conceived and incompletely considered notion of correctness are more correct and than test cases that fail.

This exactly where a static type system would have helped. Those ill conceived incomplete understanding would have been replaced by a proof that proper types have been maintained over the possible flows of control. In this case it would have saved me a lot of time tracking cases where int64 is dropping down to int32.

At this point I would stop engaging in this conversation because it has become an exercise in pointless dogma.

If you refuse to accept that runtime errors detected or undetected dont have a cost, or that static types can mitigate such costs, -- whatever rocks your boat. What I am claiming is that several times in my Python/Cython use I hit instances where static types would have saved a lot of trouble and time and money.

Another common type related problem happens when you need to ensure things remain float32 and do not get promoted to float64. I work both on the large and in the small, so I encounter these.

[0] https://news.ycombinator.com/item?id=17789837

[1] https://news.ycombinator.com/item?id=17789837

Re: Think Julia: How to Think Like a Computer Scientist

#68
post #61

Earlier quoted context omitted.

Many 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…

I don’t know. My primary corporate experiences with this are all in Scala and Haskell (with teams that have very veteran programmers in each), and the results were terrible. I liken it to David Deutsch’s comments on good systems of government in his book The Beginning of Infinity where he advised that the trait you should use to evaluate a system of government is not whether it produces good policies, but rather how…

There are many things you say here that I can totally agree with. When speed of development is a concern and costs of runtime errors are moderate enough that one can absorb them, it would be a bad idea to use Haskell (haven't used Scala so not qualified enough to comment).

Somewhere along the spectrum of increasing cost to business of runtime errors the needle switches in favor of static tyoes. This is more true when you ship applications to folks who dont necessarily know or care about the internals. Throwing runtime errors is just a bad form in those cases.

When the code is going to be deployed on infrastructure you control, there is a lot more leeway to absorb runtime errors. The choice depends on how costly the runtime errors are and how costly are the fixes. Time being part of the cost.

Re: Think Julia: How to Think Like a Computer Scientist

#69
post #67

Earlier quoted context omitted.

The code you linked actually seems to refute your claim of this precision error, at least for multiply, because it is using npy_intp for nnz, which will be int64 on a 64 bit platform, and there is even an overflow check below! Can you post a gist or link some other concrete example to show how it can overflow the intp type based on large nnz? Reading the code, it looks like this could not happen. (Note that the entir…

Can't help but say this, you are seriously confused. Not necessarily your fault, as obviously you dont have the full code. I have mentioned earlier that it is not about precision but about index space. I don't think it's going to be productive use of my time to continue this thread. One specific reason you are getting confused is because you are looking at function calls in isolation not the entire chain of calls thr…

> “I have mentioned earlier that it is not about precision but about index space.”

Right, and if you read in my comments it shows I have also been only talking about the index space as well, where int64 vs int32 is a matter of int precision for representing large amounts of indices, but where npy_intp will be of the higher precision (to match the platform’s address space) and will not be able to suffer the overflow issue you described unless it’s a custom compilation of numpy defining npy_intp as int32 even on a 64-bit system (which you seem confused about by repeatedly saying compilation isn’t a part of it, as if anyone is suggesting your personal workflow involves compiling anything, when I’m talking about how the numpy you have installed was compiled. If it’s standard numpy compiled for a 64-bit system, then the evidence suggests your claim is just wrong.)

You claim that indptr and indices arrays are silently converted from int64 to int32 on 64-bit platforms but you offer no evidence. You just keep saying that it happened to you, despite the actual code you linked indicating that it couldn’t happen. And I do actually work with indptr and indices arrays with tens of billions of nonzero elements in an Alexa top 300 website search engine every day, and have never encountered any such silent type conversion.

Given that this example of index int precision actually seems unfounded in the code, it just doesn’t seem relevant to any sort of static vs dynamic typing debate. There’s no such issue here that static typing would help with, because it’s clearly not causing the problem you think it’s causing in the dynamic typing code.

Re: Think Julia: How to Think Like a Computer Scientist

#70
post #67

Earlier quoted context omitted.

Can't help but say this, you are seriously confused. Not necessarily your fault, as obviously you dont have the full code. I have mentioned earlier that it is not about precision but about index space. I don't think it's going to be productive use of my time to continue this thread. One specific reason you are getting confused is because you are looking at function calls in isolation not the entire chain of calls thr…

> “I have mentioned earlier that it is not about precision but about index space.” Right, and if you read in my comments it shows I have also been only talking about the index space as well, where int64 vs int32 is a matter of int precision for representing large amounts of indices, but where npy_intp will be of the higher precision (to match the platform’s address space) and will not be able to suffer the overflow i…

All I can say is you will learn a little bit more if your "know it all" persona is in proportion with your actual extensive knowledge :)

There was a recent thread on HN on Ousterhout on exactly that https://news.ycombinator.com/item?id=17779953

Re evidence, you cant possibly expect me to replicate the entire software library stack here on HN or elsewhere to show the loss of type information.

Hint you are still looking at functions in isolation and repeating loss of type info cannot happen and I have dealt with hundreds of counter examples. You can look up the conversation, I did not say the pointed Github code is to blame. I pointed the code saying we have to make sure that piece of code is eventually called with the right type. We have to ensure that at the time of creation of the sparse matrices. With the dynamic type handling this gets lost. Int64 gets dropped to Int32.

Post reply on HN