notes-computer-programming-programmingLanguageDesign-prosAndCons-julia

http://www.evanmiller.org/why-im-betting-on-julia.html

" Not only can you write code with the performance of C in Julia, you can take a peek behind the curtain of any function into its LLVM Intermediate Representation as well as its generated assembly code — all within the REPL. Check it out.

emiller ~/Code/julia (master) ./julia _ _ _ _(_)_

A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "help()" to list help topics
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.3.0-prerelease+261 (2013-11-30 12:55 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit 97b5983 (0 days old master)
__/x86_64-apple-darwin12.5.0

julia> f(x) = x * x f (generic function with 1 method)

julia> f(2.0) 4.0

julia> code_llvm(f, (Float64,))

define double @julia_f662(double) { top: %1 = fmul double %0, %0, !dbg !3553 ret double %1, !dbg !3553 }

julia> code_native(f, (Float64,)) .section __TEXT,__text,regular,pure_instructions Filename: none Source line: 1 push RBP mov RBP, RSP Source line: 1 vmulsd XMM0, XMM0, XMM0 pop RBP ret

Bam — you can go from writing a one-line function to inspecting its LLVM-optimized X86 assembler code in about 20 seconds. "

--

Pxtl 3 days ago

link

To be fair, there's also Python+NumPy? and R in that space, not just Matlab. Besides the "tinker with LLVM" thing, what does Julia offer that Python (or Cython for speed)+NumPy? does not?

reply

simonster 3 days ago

link

Writing fast code in Julia requires less effort than it does in Python or R. You don't have to drop down to Cython or Rcpp to get good performance. If you write an algorithm in Julia the same way you'd write it in C, it will achieve equal performance. If you write it the same way you'd write it in Python or R, it may not be optimal due to the cost of memory allocation, but it's still faster than Python or R.

Julia is more concise than Python. The language was designed to work with multidimensional arrays; it wasn't bolted on afterwards. There is no difference between a 2D array and a matrix; * always does matrix multiplication and .* always does element-wise multiplication. There is no awkwardness involving differences between NumPy? arrays and Python lists. Everything has a type, and you can make a multidimensional array that efficiently stores values of any type. You can define your own types and define how arithmetic operators act on them with a minimal amount of code.

Julia's type system makes writing efficient algorithms easy without sacrificing any performance. If you define your own immutable type and define your own operators on it, Julia can make those operators run as fast as they would on ordinary values. In addition to general matrices, we have diagonal, symmetric, and tridiagonal matrices. The same routines that work on general matrices work on these as well with the same syntax, just more efficiently.

Julia uses multiple dispatch instead of traditional class-based OO. Methods are not a part of the object; instead, they operate on the object. Different methods with the same name can be defined to work on different types, or a single method can operate on a set of types, but the functions it calls may be implemented differently for each of these types. This is a better fit for technical applications, where the data doesn't change much but the methods do.

Julia is homoiconic, which is more useful than this article makes it seem :). It's easy to write code that writes code. If built-in language features aren't enough to get good performance with concise syntax, you can write a hygenic macro that does this for you.

reply

--

ngoldbaum 2 days ago

link

Check out the Julia pycall library. It allows arbitrary python calls from inside Julia with nice autogenerated bindings from python objects to Julia types.

reply

--

3JPLW 3 days ago

link

...In my opinion, there's lots of things to love about Julia.

First class arrays and array literals. It's a wonderful thing… like Matlab but very smartly designed.

The type dispatch system makes so much sense for mathematical work. It's simply how math is done. And Stefan Karpinski (co-creator) often compares it to linguistic grammars, too, which may be a stretch but I think there's some truth to it. It just feels right. And it makes things very extensible, right down to the core language.

And the core language is indeed mostly Julia itself. Compared to NumPy? where things are often implemented in C or Cython. I've tried to hack on some Cython things in NumPy? and was immediately turned off. It was so hard to debug and run interactively.

Julia's interactivity is wonderful. The IJulia project brings over some of the best user experience of NumPy? (in my opinion)… which is not NumPy? but IPython.

And the community is so very great and supporting. The package system is such a great asset and really lowers the bar to entry.

reply

--

jamesjporter 2 days ago

link

This already exists as a prototype as part of IJulia, see Leah Hanson's awesome blog post about it here: http://blog.leahhanson.us/julia-calling-python-calling-julia...

The collaboration between the scientific Python and Julia communities in recent months has been awesome to watch.

reply

--

avodonosov 2 days ago

link

The reason to bet on Julia is disassembling a function? This is a standard feature in Common Lisp (ANSI standardized in 1994)

  CL-USER> (defun f(x) (* x x))
  F
  CL-USER> (disassemble 'f)
  L0
           (leaq (@ (:^ L0) (% rip)) (% fn))       ;     [0]
           (cmpl ($ 8) (% nargs))                  ;     [7]
           (jne L33)                               ;    [10]
           (pushq (% rbp))                         ;    [12]
           (movq (% rsp) (% rbp))                  ;    [13]
           (pushq (% arg_z))                       ;    [16]
           (movq (% arg_z) (% arg_y))              ;    [17]
           (leaveq)                                ;    [20]
           (jmpq (@ .SPBUILTIN-TIMES))             ;    [21]
  L33
           (uuo-error-wrong-number-of-args)        ;    [33]

reply

kisielk 2 days ago

link

This is also possible to a degree in Python, though you only get the bytecode:

    >>> def f(x):
    ...     return x * x
    ...
    >>> import dis
    >>> print dis.dis(f)
      2           0 LOAD_FAST                0 (x)
                  3 LOAD_FAST                0 (x)
                  6 BINARY_MULTIPLY
                  7 RETURN_VALUE

reply

sitkack 2 days ago

link

And the bytecode is just calling polymorphic methods. All the real work is done in the object implementations of type(x). I was very bummed years ago to realize how shallow the bytecode representation in Python is. There is no sub-terpreter, just C.

reply

steveklabnik 2 days ago

link

You can get the bytecode in Ruby too: http://www.ruby-doc.org/core-2.1.0/RubyVM/InstructionSequenc...

reply

--

sdegutis 3 days ago

link

Wait a minute! Can you embed Julia into a C program like Lua? Can it interface with complex C types cleanly?? This might be the scripting language I'v been looking for in my side project!

reply

sdegutis 3 days ago

link

Wow. Okay, yes. It can be embedded[1]. It can call C code[2].

Julia may have just saved my project (which was dying because it needed a good scripting language that was fast)!

[1]: http://docs.julialang.org/en/latest/manual/embedding/

[2]: http://docs.julialang.org/en/latest/manual/calling-c-and-for...

reply

3JPLW 3 days ago

link

And embedding (and its documentation) will likely get much better very soon.

https://github.com/JuliaLang/julia/pull/4997

reply

sdegutis 3 days ago

link

One big pain point so far is that it won't be easy to actually embed Julia into my app. So users of my app will have to install Julia (probably via homebrew) before they can script the app with it.

reply

--

RivieraKid? 2 days ago

link

I've used Julia for couple of projects and it's amazing, I seriously believe that Julia is better - in several ways - than all of the widely used dynamic languages like Python, Ruby, Clojure, Octave or Lua. It's a brilliantly designed language. There are so many things to like about this language.

reply

--

tenfingers 2 days ago

link

There's a lot to love in Julia, but my biggest nitpick is the 1-based array index. I can see where it comes from, but it's not something I can praise. I use R on a daily basis, where the aim is mostly interactive analysis, and still I cannot see any reason to use 1-based indexes. For a language that is instead mostly oriented to programming, I would have not went for the "familiarity" argument.

reply

thinkpad20 2 days ago

link

I'm guessing whoever was responsible for that decision was either a hardcore FORTRAN or MATLAB user, since both of those have 1-based indices. Or by a similar token, they could have chosen that because they expect that many of their users might be coming from either of those languages. I guess you'd get used to it, but I agree it's a big drawback.

reply

--

foundart 3 days ago

link

I see the Julia home page lists multiple dispatch as one of its benefits. Since my only real exposure to multiple dispatch was when I inherited some CLOS code where it was used to create a nightmare of spaghetti, I'm wondering if any Julia fans here would care to elaborate on how they've used multiple dispatch for Good™ instead of Evil™

reply

astrieanna 2 days ago

link

Multiple dispatch lets you make math operators work like they do in path. That means that you can use `+` the same way on ints, floats, matrices, and your own self-defined numeric type. If `x` is a variable of your new numeric type, OO languages make making `x + 5` work easy, but `5 + x` super hard. Multiple dispatch makes both cases (equally) easy. This was, as I understand it, the major reason that Julia uses multiple dispatch.

Multiple dispatch can make interfaces simpler: you can easily offer several "versions" of a function by changing which arguments they take, and you can define those functions where it makes sense, even if those places are spread across multiple modules or packages. Julia provides great tools (functions) that make methods discoverable, help you understand which method you're calling, and help you find the definition of methods.

Looking at some Julia code (the base library or major packages) might give you a better idea of how Julia uses multiple dispatch.

--

allochthon 1 day ago

link

I like what I see so far at this page [1] and will watch closely to see whether Julia catches on.

One thing -- can we call agree that dictionary literals begin and end with '{}', that arrays are zero-indexed and that an index into a unicode string is properly a character and not a byte? Or are we doomed to permute endlessly on details such as these? I wish any new languages would set aside a large set of tempting innovations and just go with the flow on the smaller points.

[1] http://learnxinyminutes.com/docs/julia/

reply

3JPLW 21 hours ago

link

Well, in many ways, they are going with the flow. They're targeting mathematicians, and R/Matlab users… all of whom use 1-indexed arrays. And, really, the kinds of dictionaries you're used to are constructed with {} braces. The square braces hold more specifically-typed keys and objects. It's a very clever analogy to their typed/untyped arrays. And wonderful for performance.

    ["one"=> 1, "two"=> 2, "three"=> 3] # -> Dict{ASCIIString,Int64}
    {"one"=> 1, "two"=> 2, "three"=> 3} # -> Dict{Any,Any}

reply

--

astrieanna 3 days ago

link

Julia does not compile the C code; it links against shared libraries. It helps that Julia types can model C structs easily.

Manual entry on calling C: http://docs.julialang.org/en/latest/manual/calling-c-and-for...

Blog post on passing Juila callback functions to C code: http://julialang.org/blog/2013/05/callback/

reply

--

sixbrx 1 day ago

link

I've had some problems with Julia performance for a finite element method implementation (https://github.com/scharris/WGFEA), mostly I believe because of (1) garbage generated in loops causing big slowdowns and (2) slow calls of function closures. Functions defined at the top-level which don't close over environment values are fast, closures however are quite slow, which is really painful for situations where closures are so useful, e.g. to pass as integrands to integration functions.

There is an github-issue about the closure slowdown, but I don't have it handy. Both can be worked around, by writing in a lower level style, e.g. by using explicit loops acting on pre-allocated buffers, avoiding higher-order functions, etc. The pre-allocated buffers can be a lurking hazard though (Rust avoids the danger in the same strategy with its safe immutable "borrow" idea). I felt like these workarounds were giving up too much of the advantages of a high level approach for my own tastes.

I have converted to Rust to avoid the garbage collection for sure, and I'm extremely pleased with the performance. It would be nice having a REPL though, I do miss that. And I do intend to stay involved with Julia. I'm sure the situation will improve.

Good high performance garbage collectors aren't easy (and they are easy to take for granted after being on the JVM for a while) - that's probably the biggest challenge for Julia as a high performance language, IMO.

reply

--

http://julialang.org/blog/2012/02/why-we-created-julia/

---

http://julia.readthedocs.org/en/latest/manual/noteworthy-differences/?highlight=decimal