📜 ⬆️ ⬇️

Why do I bet on Julia

image We don’t talk about Julia here at all. One post two years ago from Alizar, that's all. We correct the situation.

Using different programming languages, I constantly encounter the same problem - their creators are crazy about things that I don’t really care about: security, type systems, homoicity, and so on. All this is very cool, I don’t argue, but when I go to work on my next project in the evenings, I only care about its performance and productivity. The code is just a means to achieve a certain goal, and its “expressiveness” is important for me as well as the “expressiveness” of some catalytic converter.

Some people contemptuously call such an approach to business cowboy programming. But it seems to me that this is not the most correct image - the cowboy has to periodically make halts because of the physical limitations of his horse. Let's better imagine an obsessed scientist, such a professor, who disappears for weeks in the laboratory, and then comes out exhausted, with a blurred look, with his new clever invention, which falls apart at the very first launch.

I usually work this way: first I write a prototype in one language, after I rewrite critical sections in another language, and if I need the program to fly, I use a third language. This approach is quite common. For prototyping, many use Python, Ruby, R, etc. As soon as everything worked, some pieces of code are rewritten to C or C ++. If this is not enough, some cycles are rewritten in assembly language, CUDA or OpenCL.
')
But in this case, we are faced with complex obstacles. Not only do you need to know three languages, you also have to constantly switch between different levels of abstraction. And in real life, you still have to write the linking code - switch between different files, editors and debuggers.

Some time ago I learned about Julia , the language immediately seemed abrupt to me, but I did not feel any particular need for it. Julia is a high-performance dynamic language. It is tempting, of course, but I have already ditched a lot of time to shove the engine from my behi into my shokhu - why do I need something else? In addition, there are a lot of platforms that promise performance at the C level: Java HotSpot, PyPy, asm.js, and others.

And only then I realized what distinguishes Julia from other languages. Julia breaks down the barrier between high-level and assembly code. Julia not only allows you to write code that works as fast as C code, but also gives you the opportunity to look at the LLVM representation of functions and their generated assembler code. And all this right in an interactive environment.

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 

This is how it is. We can write a single-line function and immediately examine its optimized assembly code.

In general, you can forget about the Julia type system , multimethods, and other homoiconics . This is all, of course, entertaining, but Julia’s real trump is that we can start from the prototype, and finish with the optimization of SIMD instructions without leaving one language.

In general, this is the main reason I bet on Julia. I can't wait to make such a comparison: this language will do for technical calculations what Node.js does for web development - it unites different groups of programmers in one language. If for Node.js, these groups are frontend and backend developers, then for Julia there are experts in certain areas of knowledge and insane optimizers. This is a great achievement.

At the moment, the only drawback of the language is the lack of libraries . But it is also compensated for by the ease of interacting with the C libraries. Unlike interfaces for the interaction of other languages, you can call the C function here without writing a single line in C, so it seems to me that the number of libraries will soon begin its rapid growth. If we talk about my own experience, then I managed without any additional C code to use 5 thousand lines of C code in my 150 lines of Julia code .

If you have to maintain code from a mixture of Python, C, C ++, Fortran and R, or you are just as obsessed with performance, then I strongly recommend that you download Julia and give her a chance. If you are not sure whether to complicate your life with another programming language, then just realize that this tool will eventually allow you to reduce the number of languages ​​in your projects.

After all, if you forget about performance for a minute, Julia is an incredibly beautiful language. I'm not a geek, but I almost never encountered any difficulties while learning a language. And now Julia is one of the three preferred languages ​​for me.

In the end, an active community gathered around Julia, always ready to help. I am particularly pleased that a considerable part of it consists of smart and friendly mathematicians and representatives of other sciences. I think it happened just because Julia was created not by geeks, but by students of exact sciences from MIT, who need fast and convenient language to replace C and Fortran. And it was created not to be beautiful (although it turned out that way). It was created to quickly get answers. And this, I believe, is the essence of all our computer science.

The end of the post of Evan Miller.

Post, similar in mood, appeared today on Wired .

Julia in short


In order not to get up twice, I present a translation of the document Learn Julia in minutes .

Julia REPL .

 #      . #################################################### ## 1.      #################################################### #   Julia — . #    3 #=> 3 (Int64) 3.2 #=> 3.2 (Float64) 2 + 1im #=> 2 + 1im (Complex{Int64}) 2//3 #=> 2//3 (Rational{Int64}) #      1 + 1 #=> 2 8 - 1 #=> 7 10 * 2 #=> 20 35 / 5 #=> 7.0 5 / 2 #=> 2.5 #  Int  Int   Float div(5, 2) #=> 2 #      div 5 \ 35 #=> 7.0 2 ^ 2 #=> 4 #    12 % 10 #=> 2 #        (1 + 3) * 2 #=> 8 #   ~2 #=> -3 #  (NOT) 3 & 5 #=> 1 #  (AND) 2 | 4 #=> 6 #  (OR) 2 $ 4 #=> 6 #    2 (XOR) 2 >>> 1 #=> 1 #    2 >> 1 #=> 1 #    2 << 1 #=> 4 # /   #  bits     bits(12345) #=> "0000000000000000000000000000000000000000000000000011000000111001" bits(12345.0) #=> "0100000011001000000111001000000000000000000000000000000000000000" #     true false #   !true #=> false !false #=> true 1 == 1 #=> true 2 == 1 #=> false 1 != 1 #=> false 2 != 1 #=> true 1 < 10 #=> true 1 > 10 #=> false 2 <= 2 #=> true 2 >= 2 #=> true #     1 < 2 < 3 #=> true 2 < 3 < 2 #=> false #       — " "This is a string." #        — ' 'a' #      "This is a string"[1] #=> 'T' #     #       UTF8-, #     (map, for-  ..). #       ($): "2 + 2 = $(2 + 2)" #=> "2 + 2 = 4" #       . #     —  printf @printf "%d is less than %f" 4.5 5.3 # 5 is less than 5.300000 #################################################### ## 2.    #################################################### #  println("I'm Julia. Nice to meet you!") #      some_var = 5 #=> 5 some_var #=> 5 #         try some_other_var #=> ERROR: some_other_var not defined catch e println(e) end #     . #      , , #     . SomeOtherVar123! = 6 #=> 6 #   unicode- = 8 #=> 8 #       2 * π #=> 6.283185307179586 #   : # *     ,    #  ('\_'); # # *     CamelCase; # # *        #     ; # # *  ,     (in-place function), #   . #    ,     n: a = Int64[] #=>   Int64- #      . b = [4, 5, 6] #=>    Int64-: [4, 5, 6] b[1] #=> 4 b[end] #=> 6 #       . #    . matrix = [1 2; 3 4] #=> 2x2 Int64 Array: [1 2; 3 4] # push!  append!      push!(a,1) #=> [1] push!(a,2) #=> [1,2] push!(a,4) #=> [1,2,4] push!(a,3) #=> [1,2,4,3] append!(a,b) #=> [1,2,4,3,4,5,6] # pop!      pop!(b) #=>  6;  b   [4,5] #  6  push!(b,6) # b  [4,5,6]. a[1] #=> 1 #    ! #       end a[end] #=> 6 #   shift!(a) #=> 1 and a is now [2,4,3,4,5,6] unshift!(a,7) #=> [7,2,4,3,4,5,6] #       , #      . arr = [5,4,6] #=>   3 Int64-: [5,4,6] sort(arr) #=> [4,5,6];  arr  [5,4,6] sort!(arr) #=> [4,5,6];   arr — [4,5,6] #       BoundsError try a[0] #=> ERROR: BoundsError() in getindex at array.jl:270 a[end+1] #=> ERROR: BoundsError() in getindex at array.jl:270 catch e println(e) end #      ,   , #       . #    Julia   , #        base. #      a = [1:5] #=>   5 Int64-: [1,2,3,4,5] #  a[1:3] #=> [1, 2, 3] a[2:] #=> [2, 3, 4, 5] a[2:end] #=> [2, 3, 4, 5] # splice!     # Remove elements from an array by index with splice! arr = [3,4,5] splice!(arr,2) #=> 4 ; arr   [3,5] # append!   b = [1,2,3] append!(a,b) #  a  [1, 2, 3, 4, 5, 1, 2, 3] #    in(1, a) #=> true #   length(a) #=> 8 #  —  . tup = (1, 2, 3) #=> (1,2,3) #  (Int64,Int64,Int64). tup[1] #=> 1 try: tup[1] = 3 #=> ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64) catch e println(e) end #         length(tup) #=> 3 tup[1:2] #=> (1,2) in(2, tup) #=> true #      a, b, c = (1, 2, 3) #=> (1,2,3) # a = 1, b = 2  c = 3 #       d, e, f = 4, 5, 6 #=> (4,5,6) #          (1,) == 1 #=> false (1) == 1 #=> true #   e, d = d, e #=> (5,4) # d = 5, e = 4 #     empty_dict = Dict() #=> Dict{Any,Any}() #       filled_dict = ["one"=> 1, "two"=> 2, "three"=> 3] # => Dict{ASCIIString,Int64} #        [] filled_dict["one"] #=> 1 #    keys(filled_dict) #=> KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) # ,    ,    . #   . values(filled_dict) #=> ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) #      . #      in(("one", 1), filled_dict) #=> true in(("two", 3), filled_dict) #=> false haskey(filled_dict, "one") #=> true haskey(filled_dict, 1) #=> false #        try filled_dict["four"] #=> ERROR: key not found: four in getindex at dict.jl:489 catch e println(e) end #   get    ,     # get(dictionary,key,default_value) get(filled_dict,"one",4) #=> 1 get(filled_dict,"four",4) #=> 4 #       Set empty_set = Set() #=> Set{Any}() #   filled_set = Set(1,2,2,3,4) #=> Set{Int64}(1,2,3,4) #   push!(filled_set,5) #=> Set{Int64}(5,4,2,3,1) #      in(2, filled_set) #=> true in(10, filled_set) #=> false #    ,   . other_set = Set(3, 4, 5, 6) #=> Set{Int64}(6,4,5,3) intersect(filled_set, other_set) #=> Set{Int64}(3,4,5) union(filled_set, other_set) #=> Set{Int64}(1,2,3,4,5,6) setdiff(Set(1,2,3,4),Set(2,3,5)) #=> Set{Int64}(1,4) #################################################### ## 3.   #################################################### #   some_var = 5 #  if.    . if some_var > 10 println("some_var is totally bigger than 10.") elseif some_var < 10 #   elseif. println("some_var is smaller than 10.") else # else-  . println("some_var is indeed 10.") end #=> prints "some var is smaller than 10" #  for     #   : Range, Array, Set, Dict  String. for animal=["dog", "cat", "mouse"] println("$animal is a mammal") #          $ end # : # dog is a mammal # cat is a mammal # mouse is a mammal #   . for animal in ["dog", "cat", "mouse"] println("$animal is a mammal") end # : # dog is a mammal # cat is a mammal # mouse is a mammal for a in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"] println("$(a[1]) is a $(a[2])") end # : # dog is a mammal # cat is a mammal # mouse is a mammal for (k,v) in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"] println("$k is a $v") end # : # dog is a mammal # cat is a mammal # mouse is a mammal #  while    ,    x = 0 while x < 4 println(x) x += 1 #   x = x + 1 end # : # 0 # 1 # 2 # 3 #   try error("help") catch e println("caught it $e") end #=> caught it ErrorException("help") #################################################### ## 4.  #################################################### #        'function' #function () # ... #end function add(x, y) println("x is $x and y is $y") #      x + y end add(5, 6) #=>  11,  "x is 5 and y is 6" #       . function varargs(args...) return args #         'return' end #=> varargs (generic function with 1 method) varargs(1,2,3) #=> (1,2,3) #  (...) —  splat. #        . #       , #          . Set([1,2,3]) #=> Set{Array{Int64,1}}([1,2,3]) #    Set([1,2,3]...) #=> Set{Int64}(1,2,3) #  Set(1,2,3) x = (1,2,3) #=> (1,2,3) Set(x) #=> Set{(Int64,Int64,Int64)}((1,2,3)) #   Set(x...) #=> Set{Int64}(2,3,1) #    function defaults(a,b,x=5,y=6) return "$a $b and $x $y" end defaults('h','g') #=> "hg and 5 6" defaults('h','g','j') #=> "hg and j 6" defaults('h','g','j','k') #=> "hg and j k" try defaults('h') #=> ERROR: no method defaults(Char,) defaults() #=> ERROR: no methods defaults() catch e println(e) end #   function keyword_args(;k1=4,name2="hello") #    ; return ["k1"=>k1,"name2"=>name2] end keyword_args(name2="ness") #=> ["name2"=>"ness","k1"=>4] keyword_args(k1="mine") #=> ["k1"=>"mine","name2"=>"hello"] keyword_args() #=> ["name2"=>"hello","k2"=>4] #         function all_the_args(normal_arg, optional_positional_arg=2; keyword_arg="foo") println("normal arg: $normal_arg") println("optional arg: $optional_positional_arg") println("keyword arg: $keyword_arg") end all_the_args(1, 3, keyword_arg=4) # : # normal arg: 1 # optional arg: 3 # keyword arg: 4 #   Julia   function create_adder(x) adder = function (y) return x + y end return adder end #   (x -> x > 2)(3) #=> true #      create_adder function create_adder(x) y -> x + y end #   ,     function create_adder(x) function adder(y) x + y end adder end add_10 = create_adder(10) add_10(3) #=> 13 #     map(add_10, [1,2,3]) #=> [11, 12, 13] filter(x -> x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] #   [add_10(i) for i=[1, 2, 3]] #=> [11, 12, 13] [add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] #################################################### ## 5.  #################################################### # Julia has a type system. #    ,      . #  `typeof`   . typeof(5) #=> Int64 # Types are first-class values #      typeof(Int64) #=> DataType typeof(DataType) #=> DataType #  DataType  ,   . #     ,    . #    . #      #        #        `type` # type Name # field::OptionalType # ... # end type Tiger taillength::Float64 coatcolor #    `::Any` end #     —   #    . tigger = Tiger(3.5,"orange") #=> Tiger(3.5,"orange") #          sherekhan = typeof(tigger)(5.6,"fire") #=> Tiger(5.6,"fire") #  ,   ,  . #     ,    . #    —  . # abstract Name abstract Cat #        #     , #       . # , Number —   . subtypes(Number) #=> 6    Array{Any,1}: # Complex{Float16} # Complex{Float32} # Complex{Float64} # Complex{T<:Real} # ImaginaryUnit # Real subtypes(Cat) #=>   Array{Any,1} #     .      `super`. typeof(5) #=> Int64 super(Int64) #=> Signed super(Signed) #=> Real super(Real) #=> Number super(Number) #=> Any super(super(Signed)) #=> Number super(Any) #=> Any #   ,   Int64, . #      <: type Lion <: Cat # Lion —   Cat mane_color roar::String end #      . #       ,   , #    . Lion(roar::String) = Lion("green",roar) #    (..     ) . type Panther <: Cat # Panther —    Cat eye_color #        Panther() = new("green") end #     # ,     . #       . #################################################### ## 6.  #################################################### #     generic-, # ..      . #    Lion —   generic- Lion. #     ,   meow #  Lion, Panther  Tiger function meow(animal::Lion) animal.roar #       end function meow(animal::Panther) "grrr" end function meow(animal::Tiger) "rawwwr" end #  meow(tigger) #=> "rawwr" meow(Lion("brown","ROAAR")) #=> "ROAAR" meow(Panther()) #=> "grrr" #    issubtype(Tiger,Cat) #=> false issubtype(Lion,Cat) #=> true issubtype(Panther,Cat) #=> true #  ,      Cat function pet_cat(cat::Cat) println("The cat says $(meow(cat))") end pet_cat(Lion("42")) #=>  "The cat says 42" try pet_cat(tigger) #=> ERROR: no method pet_cat(Tiger,) catch e println(e) end #  -     — #        . #  Julia       . #   ,     . function fight(t::Tiger,c::Cat) println("The $(t.coatcolor) tiger wins!") end #=> fight (generic function with 1 method) fight(tigger,Panther()) #=>  The orange tiger wins! fight(tigger,Lion("ROAR")) #=>  The orange tiger wins! #   ,  Cat-  Lion- fight(t::Tiger,l::Lion) = println("The $(l.mane_color)-maned lion wins!") #=> fight (generic function with 2 methods) fight(tigger,Panther()) #=>  The orange tiger wins! fight(tigger,Lion("ROAR")) #=>  The green-maned lion wins! #      ! fight(l::Lion,c::Cat) = println("The victorious cat says $(meow(c))") #=> fight (generic function with 3 methods) fight(Lion("balooga!"),Panther()) #=>  The victorious cat says grrr try fight(Panther(),Lion("RAWR")) #=> ERROR: no method fight(Panther,Lion) catch end # ,       fight(c::Cat,l::Lion) = println("The cat beats the Lion") #=> Warning: New definition # fight(Cat,Lion) at none:1 # is ambiguous with # fight(Lion,Cat) at none:2. # Make sure # fight(Lion,Lion) # is defined first. #fight (generic function with 4 methods) #  ,  ,    : fight(Lion("RAR"),Lion("brown","rarrr")) #=>  The victorious cat says rarrr #        Julia fight(l::Lion,l2::Lion) = println("The lions come to a tie") fight(Lion("RAR"),Lion("brown","rarrr")) #=>  The lions come to a tie 

What's next?


Read the documentation ! A help search the mailing list .

Hab-user magik recommends watching a couple of videos from conferences: “ Julia: A Fast Dynamic Language for Technical Computing ” and “ Julia and Python: a dynamic duo for scientific computing ”.

Source: https://habr.com/ru/post/210298/


All Articles