4 ms·
There is a lot to like about Julia. It's obviously heavily influenced by Common Lisp. I see offhand only one thing I really don't like: they are using object
by ScottBurson 13y ago
There is a lot to like about Julia. It's obviously heavily influenced by Common Lisp. I see offhand only one thing I really don't like: they are using object semantics rather than value semantics for arrays. So for example:
A = [0, 1, 2, 3]
B = A
A[1] = 2
// now B[1] == 2
Their manual section on arrays says this:
In Julia, all arguments to functions are passed by reference. Some technical computing languages pass arrays by value, and this is convenient in many cases. In Julia, modifications made to input arrays within a function will be visible in the parent function.
but as the above example shows, it's really the semantics of assignment we're talking about here, not just that of function calls.
I believe that value semantics is easier to understand and less bug-prone, particularly for nonexpert programmers. It can also be implemented well enough that the small efficiency cost is worth paying in most cases. For one take on how to do this, see my my FSet functional collections library for Common Lisp[0]. For another, see the Clojure collection types.
[0] http://common-lisp.net/project/fset http://common-lisp.net/project/fset
- StefanKarpinski 13y agoUsing value semantics for arrays is lovely in concept but ends up being really annoying and impractical for writing really high-performance array code. This is one of the most common complaints of library authors attempting to write fast, efficient code in Matlab and is one of the many reasons why one ends up having to write all performance-critical code in C using Matlab data structures. Clojure is reputed to get remarkable performance on a broad variety of data structures, but I've had a hard time finding benchmarks comparing Clojure's purely functional arrays with normal linearly indexed arrays – if you have some references to such comparisons, I'd love to see them. In my experience, nothing beats a plain old linearly indexed, mutable array when that's what you need. Making that basic structure unavailable in a language intended for high-performance numerical computing strikes me as utterly perverse.
- cgag 13y agoClojure gets great performance with its immutable data structures, but no one pretends they're as fast as plain native java arrays or using mutation. It's normal in the Clojure community to drop down to using arrays or transients (http://clojure.org/transients http://clojure.org/transients) in high performance functions and then convert the result back to an immutable data structure. As long as you still present a pure interface, no one knows or cares what kind of mutation you do internally.
- ScottBurson 13y agoOh, I wouldn't suggest making plain old mutable arrays unavailable. I totally agree that library authors and sophisticated users need access to them (and preferably not by dropping into C). I just think the array and other collection types presented to users for ordinary application-level programming should be functional. Mutable types should stay in an "advanced topics" section of the manual.
- marcosdumay 13y agoThat's a bad an completely not intuitive trade-off for a language that is expected to be fast. I've first studied Julia today, but just by knowing its niche I already expected it to use reference semantics, not value. It'd be quite confusing if the examples demonstrated otherwise.
- cgag 13y agoAs long as it's not exceedingly difficult to drop down to using mutation, having immutability by default is ridiculously nice. I don't think I appreciated it fully until I used Clojure a significant amount, but using languages with reference semantics feels disgusting now.
- gfodor 13y agoIirc clojure lets you get your hands on a mutable array for performance via the transient keyword. The contract is such that you can do what you want (fast things) in the transient block, but it's a black box to outside callers who never see the array in its mutable form. Ie the function is still a pure function since no side effects leak. http://clojure.org/transients http://clojure.org/transients
- moomin 13y agoI'm going to nitpick horribly here: in Clojure, an array is just a Java array. But what most people use are vectors, which are immutable. 'transient' returns a mutable vector, not an array.
- susi22 13y agoThe Julia team has made it a convention to end functions with a '!' that alter your input variables. http://docs.julialang.org/en/latest/stdlib/base/ http://docs.julialang.org/en/latest/stdlib/base/ (4th point)
- plg 13y agoI teach scientific programming and this is always the point in the class where the students really start to appreciate the tradeoffs between speed/efficiency, and readability. Passing around large arrays and matrices by value is much more readable, but obviously slower and less efficient than passing by reference, which is in turn more difficult to keep track of, if you're used to languages like matlab and octave. This is also the point in our introduction to python and scipy/numpy where they realize, if they have to contend with passing by reference in this "high level language" then why to just contend with it in C and be 400x as fast?
- StefanKarpinski 13y agoPython is typically more like 40x slower than C, not 400x. Passing arrays by reference really just isn't that big of an issue in practice. We tend to write both non-mutating and mutating versions of most array functions, distinguished by whether they end in ! or not. Typical development procedure is to write an algorithm using non-mutating APIs and get that right; then you figure out where argument copying is slowing things down (using e.g. the built-in profiler) and modify the code to avoid copying, sometimes by simply adding a ! or sometimes by pre-allocating some work array and using a mutating function on it. Compare this with a similar scenario in Matlab where there simply is no straightforward way to avoid copying – if the JIT is clever enough to avoid copying you're in luck, but often it's not that smart and you're forced to live with the copying or drop into C.
- ScottBurson 13y agoI've never used Matlab and know little about it, but in general, there are much better ways to implement value semantics than by copying entire collections. Clojure's collections probably reflect the state of the art here. You might also find Chris Okasaki's book on functional data types of interest (I think Clojure's sequence type was been borrowed from Okasaki). FSet does it with balanced binary trees, which gives log-time update and log-time indexing, which are acceptable for many applications but not the best you can do for sequences.
- 13y ago
- graue 13y agoI love the Clojure collection types: basing a whole language around persistent data structures is an unbelievable win. There is a library for Julia that adds collection types similar to Clojure's[1]. My understanding is it's not very thoroughly optimized right now, but it could be a promising place to look if lack of persistent data structures is keeping you away from Julia. [1] https://github.com/zachallaun/FunctionalCollections.jl https://github.com/zachallaun/FunctionalCollections.jl