4 ms·
> “ Interestingly, CSV.jl can do all of those.“ That sounds like a poorly designed library to me. Instead of doing one thing well, it forces users to consume s
by mlthoughts2018 6y ago
> “ Interestingly, CSV.jl can do all of those.“
That sounds like a poorly designed library to me. Instead of doing one thing well, it forces users to consume something meant as a jack of all trades, which may not meet their use case.
I wish such a thing wasn’t forced in a standard package - rather split into different ones. Then I can easily compose them according to my needs, instead of having the stdlib force feed me some set of tradeoffs I might not want.
I’m sure these extra third party libraries exist or will exist in Julia just as they do in Python and users will have lots of good options - but what a shame for people to take a needlessly myopic view that core libraries need to be obsessed either with performance or with breadth of use case coverage coupled into one library, which seems to purely be for macho bragging rights or something?
- cbkeller 6y agoWell, the promise of overhead-free multiple dispatch is that you don't have to choose between a general solution with poor performance and a specific solution with good performance. You can have all the specific solutions you need in one place and automatically dispatch to the right one without any extra effort. I know it sounds too good to be true, but my limited experience so far is that it really is true, with surprisingly few pitfalls (mostly, you have to think about type instability, which will be new to most, but is really not that hard to avoid).
- mlthoughts2018 6y agoMultiple dispatch based on static typing only solves a very narrow set of optimization problems - most complex trade offs that would lead to the need for eg multiple different third party csv readers are not addressable at all by multiple dispatch. I’d also point out that with fused typing in Cython, it’s also trivially easy to get overhead-free multiple dispatch in Python too, and unlike Julia, this had the benefit that it can be a gradual trade off, where you only bother writing the Cython module with autogenerated multiple dispatch implementations based on different types for the ~1% of use cases where it has any impact on the application, and you get the benefit of super easy to develop, flexible Python for everything else, with none of the code liability that comes from describing multiple dispatch generics in the 99% of the code that does not benefit from it.
- tikej 6y ago> Multiple dispatch based on static typing only solves a very narrow set of optimization problems - most complex trade offs that would lead to the need for eg multiple different third party csv readers are not addressable at all by multiple dispatch. How about multiple dispatch with dynamic (runtime) typing?
- dklend122 6y agoYou are very misinformed here. Julia doesn't have static typing and there are a very large set of problems that are trivially solved with it's type system. See the tables.jl ecosystem for example
- mlthoughts2018 6y agoI think you are misinformed. Runtime dispatch on multiple argument types is still using static typing under the hood (Julia is using this, just as Cython is). The fact that input types are dynamic and resolved at runtime (which works identically in both Julia and Python using a Cython extension module) does not mean the multiple dispatch “is dynamic” (it’s still based on a registry of types that determine which overloaded implementation to select). The only trade-off is whether you want to be able to extend this registry of static types mapping to implementations on the fly (similar to type classes in Haskell) which Julia supports natively and Python supports via tools like numba, or you need to ahead-of-time compile it (Cython). This is a trade-off though, between AOT resolver speed vs JIT flexibility. It’s not definitely better one way or the other, and Cython gives you a level of control over explicit language features to enable or disable (eg Exception disabling) that is much better for some use cases.
- dklend122 6y agoNo. You're confusing static dispatch with static typing. Julia can do both static and dynamic dispatch. The latter works with function barriers works to maintain codebases that are impossible to achieve with just one or the other. There's no resolving trade-off because when Julia knows types and call time (or a union of them ) it can inline function calls. Anyway, neither numba nor cython has the combin of features that allows for one to define a fast custom abstract array and have another package seamlessly define a subtype that works fast and with other data structures, overloading only the necessary functions. Then a third package can come and build on top using traits from the first and some weird solver.
- imtringued 6y agoI think parents' point is that a fast CSV parser can be written once and then used to implement many different features. Meanwhile in python every library has to reimplement its own CSV parser because switching from C to python and then back to C would ruin performance. To avoid this context switch the csv parser has to be written again and again.
- mlthoughts2018 6y agoThis is not true at all. Most libraries do not reimplement csv parsing - I’m saying only a select few libraries do this because they have very different design goals. For example optimizing for maximum rows per second parsed is a totally different design goal from optimizing to read into Spark DataFrame types to connect to Spark. Prioritizing one of these might come at the cost of the other, which is totally fine and having more than one library to choose from is a good thing. > “ switching from C to python and then back to C would ruin performance.” This is explicitly wrong in regards to Python. Optimizing Python often involves writing an implementation directly in C (or better, Cython) and autogenerating bindings that marshal between CPython native C types and the types of your extension module. This is extremely fast - as fast as calling native C code, there is no performance penalty for this.
- StefanKarpinski 6y agoThat you believe this violates the principle of "do one thing and do it well" indicates a certain "abstraction blindness". Do you really believe that "parse CSV to a data frame" and "parse CSV to a parquet file" and "parse CSV and apply a query to it in-place" are completely separate, unrelated things? It seems clear to me in any case that with the right abstraction, those are the same thing composed with different choices of what to do with the parsed data. At a higher level, this seems like a classic Julia versus Python dynamic. In the Python ecosystem there are a dozen different versions of each thing that make different trade-offs and specialize in different ways. When you're picking one, you have to spend a week evaluating all the possible CSV parsers (for example). In the Julia ecosystem, the ideal it to have one really high-quality, fast, flexible implementation that everyone collaborates on to make it great for all kinds of use cases. And the language design and the compiler make this possible, since you can write pretty abstract code and compose it with various types and get a really fast implementation. The annoying and tricky logic of parsing the CSV format only needs to be done once, and reused for all different situations. This isn't done for "macho bragging rights" but because it is a waste of time and effort to implement a dozen half-baked versions of the same thing. When there are a dozen separate implementations of something like this, they also end up disagreeing on their behavior, which causes no end of headaches.
- mlthoughts2018 6y ago> “ Do you really believe that "parse CSV to a data frame" and "parse CSV to a parquet file" and "parse CSV and apply a query to it in-place" are completely separate, unrelated things?“ Yes, absolutely. Very high level design goals are completely different between those use cases and you would be forced to make mutually exclusive trade offs to solve any one of those problems - which will directly lead to concessions in terms of the other use cases. No one generic csv parser can be optimal to all three.
- StefanKarpinski 6y agoCSV.jl seems to be proof that you're wrong about that. More concretely, the only difference between parsing to a data frame, parsing to a parquet file, and executing a query over data is a) where you put the data in memory and b) optionally calling some code to operate on the data as you go. It's hard to see how those applications require radically different designs.