
An introduction to the Julia language, part 1 - leephillips
https://lwn.net/SubscriberLink/763626/f2990348ebd06167/
======
ArtWomb
Congrats to JuliaLang team on shipping 1.0 release! Adoption is widespread
across disciplines, from genomics to cosmology. Am currently evaluating
JuliaImages, and it's almost feature complete with matlab. Predict next-gen
computer vision framework will be designed in JuliaLang ;)

[http://news.mit.edu/2018/mit-developed-julia-programming-
lan...](http://news.mit.edu/2018/mit-developed-julia-programming-language-
debuts-juliacon-0827)

------
adamnemecek
I’ve been using Julia for a couple of months now and it’s unparalleled for
scientific computation. More expressive than say python, super fast, easy ffi
with python, cpp, MATLAB, Mathematica and others.

But above all it’s the community that takes the cake. So many hard algorithms
that I would have a hard time doing from scratch are implemented in Julia.

~~~
vasili111
How good is symbolic math in comparison to Mathematica?

~~~
cultus
Replying to your other comment

>It's surprising to me that there isn't a good way to call Maxima from either
Python/R/Julia or even a non-CL lisp.

There's Sage, which integrates Scipy/Numpy, Maxima, and some other things.
However, I personally find Maxima to be pretty awful to use, and even it is
nowhere close to Mathematica in functionality at this point. Mathematica
itself is horrible to use (although extemely capable), so I'd love an open
source, good alternative.

~~~
ssivark
A general comment about Mathematica, not just a response to the comment above:

Trying to use Mathematica like Python/Matlab is setting yourself up for
failure. It took me a few months of getting frustrated with Mathematica till I
suddenly "got" it [1]. But once I understood that it's programming model
revolves around pattern matching and string replacement, things just clicked
and it was very easy to write Mathematica code after that.

[1] Coincidentally, I was reading a little bit about functional programming
when Mathematica finally started making sense. In particular, IIRC, I was
looking at "Learn You a Haskell" for fun, unrelated to Mathematica, which was
for work.

~~~
cultus
The term-rewriting paradigm of Mathematica is very cool, kind of like lisp
rotated a few degrees. I'd really like to see a more mainstream language adopt
that approach. My complaints are more about everything else. Insane scoping
rules and constructs (like variables shared between notebooks), and how it is
difficult to productively use the language outside of the GUI, but yet the
text editor is beyond awful (can't undo more than once, no redo). That and the
cells and such drive me crazy.

I'm no expert, but I've been forced to use it on a few occasions, and I've
hated every minute of it. I'm fairly fluent in several of languages in
different paradigms, but the frustration I experience with Mathematica is
worse than any of them.

------
sgillen
I’ve been really excited about Julia for awhile now.

Does anyone here happen to know why the decision was made to not allow
“normal” classes in Julia? I know you can define your own types to get some of
the functionality but sometimes in numerical computing with matlab or python
it really makes sense for me to pack functionality into a class.

I know in matlab using classes causes a performance hit but I always thought
that wasn’t because the feature was bolted on afterwards. Is there something
I’m missing here?

~~~
mac01021
> it really makes sense for me to pack functionality into a class.

Why? Where you would ordinarily write

    
    
        class Foo {
           int x;
    
           int my_method() { ... }
        }
    

can't you just equivalently write

    
    
        type Foo
          x::Int
        end
    
        my_method(foo::Foo) = begin ... end
    
    ?

~~~
sgillen
Sure, I guess my question is WHY do it this way, which (to me) coming from
C++/python seems pretty foreign. I was hoping one of the contributors to the
language might be lurking here and offer some insight. I found a nice
discussion about it here [1] though, if you are interested.

([https://groups.google.com/forum/#!searchin/julia-
users/objec...](https://groups.google.com/forum/#!searchin/julia-
users/object$20oriented/julia-users/VY4XDx9aHdU/qnFZU3kfBQAJ))

~~~
StefanKarpinski
Classes in C++ and Python are essentially types bundled with a bunch of
methods associated with that type. In a multiple dispatch [1] language like
Julia, methods are not associated only with the first argument—they "belong
to" all of the arguments. This is because which method is called depends on
the types of all of the arguments, not just the first one, so it no longer
makes sense to associate those methods only with the type of the first
argument. Therefore it also no longer makes sense for method definitions to
live "inside of" the type—aka "class"—of the first argument. Therefore, you
don't have classes as bundles of types with their methods anymore—because the
methods don't belong to the types. Instead, they belong to "generic function"
objects, which are a first class abstraction for what in a class-based
language is just a collection of methods that happen to have the same name
(and may or may not actually be conceptually related). In short, you could
shoehorn something that looks like a class into Julia, but it wouldn’t really
make any sense.

To answer the next-level question of "why multiple dispatch?"... Multiple
dispatch is a generalization of single dispatch and leads to much more
composable, extensible systems, largely by providing a simple, intuitive and
efficient solution to the somewhat esoteric-sounding “Expression Problem” [2].
Even though the problem sounds obscure, it has profound practical consequences
and most of the stumbling blocks to writing reusable, composable code in both
object oriented and functional languages boil down to it being hard to either
extend existing operations to new types or to define new operations on
existing types. Julia does both so easily that it’s easy to forget that it’s a
problem in other languages. Multiple dispatch is also a particularly good fit
for numerical programming problems where it often makes little sense for a
specialized operation to "belong" only to its first argument. For example, `x
+ y` doesn't belong to `x` any more than it does to `y`.

[1]
[https://en.wikipedia.org/wiki/Multiple_dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch)

[2]
[https://en.wikipedia.org/wiki/Expression_problem](https://en.wikipedia.org/wiki/Expression_problem)

------
PinkMilkshake
The Wikipedia page on Julia says one of the original goals was that Julia
could be used as a specification language. Does Julia already provide tools
for formal verification?

~~~
StefanKarpinski
That seems likely to be an unfounded claim since that wasn't one of the
original goals.

------
jgmjgm
I recall reading that the biggest problem with Julia was that the language was
not sufficiently well tested in an automated way. The result of which was that
complex bugs kept creeping back in making the language less reliable in a
production environment.

Is my memory faulty? If not, have these concerns been addressed?

~~~
KenoFischer
You're probably thinking of complaints that our CI was flakey at times
(failing despite changes being ok), which is true (though it's been pretty
stable lately). However, people sometimes equate that with bad test coverage,
which is absolutely not the same thing. Easiest way to get a test to pass is
to delete it.

From my perspective at least, the julia test suite is quite comprehensive (if
something passes the test suite, I'm generally happy to put it on master and
have people use it). We're also lucky that there is so much open source julia
code available, which we can use as essentially one giant regression test. We
used that heavily in the lead up to 1.0 to make sure that there weren't any
surprise bugs waiting for people.

------
m3mpp
What is the language lineage? Is it functional or imperative? Dynamic or
statically typed? Garbage collected or not? I wish every introduction to a new
language would contain that kind of info, it'd be so much more informative.

Edit: missed one, natively compiled or VM based.

~~~
FridgeSeal
I’ll have a stab at answering this, someone who knows better can correct me.

Dynamic with optional typing. General consensus is that it has a pretty great
type system. Union types, language level implementation of high performance
missing types. Garbage collected. JIT compiled using LLVM backend; entire
language is written in itself, so the compiler doesn’t have any “black boxes”,
I.e. it can optimise everything. Great multiple dispatch system. Imperative
technically I guess? But feels like it’s lifted a bunch of good ideas from
various functional and domain specific languages.

Anything I missed?

~~~
tejtm
User defined types are __no__ different than "native" types.

You are talking to the llvm compiler, sure you are talking in Julia most of
the time, but if you happen to want to talk in C or FORTRAN or ASM in the
middle of your high level script, just do. No marshalling of I/O or data
structure impedance it all compiles the same.

~~~
earenndil
So can I define custom operations in llvm ir?

~~~
tejtm
You can write custom code in llvm IR.[0] I must leave it to you to tell me if
you can use it as an operator. My guess is yes, but I will not be getting to
play any time soon.

[0][https://docs.julialang.org/en/stable/base/c/#Core.Intrinsics...](https://docs.julialang.org/en/stable/base/c/#Core.Intrinsics.llvmcall)

------
gerdesj
_Julia can handle rational numbers, with a special syntax: 3 //5 + 2//3
returns 19//15, while 3/5 + 2/3 gets you the floating-point answer
1.2666666666666666._

Why not allow a/b + c/d = (a.d + c.b)/(b.d)? It's what happens when I get my
pen and paper out in the real world (along with my tongue sticking out and
much perspiration and perhaps a few doodles.) Why does Julia use / to cause
one of those weird repeated decimal expansion things to appear but // is
needed to keep things pure?

Yes I am partially taking the piss but I'm also interested into the design
decision into why // is needed to avoid a type conversion. I note that 1/2 =
0.5 was also a design decision.

~~~
chrispeel
A rational number is represented in a fundamentally different way than a
floating-point type, or a fixed-point number, or a BigFloat. Julia allows you
to define your own types, so if you want to define a type that behaves in the
special way you want, you're welcome to do so.

~~~
gerdesj
If I write 2/3 on a piece of paper it does not suddenly become
0.666666666666666666666 why does Julia (int al) insist on this? (tongue still
in cheek)

~~~
KenoFischer
Well, yeah, that's because it's a piece of paper, not a calculator. More
seriously, you have to be very careful "spooky action at a distance" in
programming language design. For example, you might say something like "Well,
if the compiler can prove that every constant involved is provable in rational
arithmetic, do that, otherwise use floating point arithmetic", which seems
like a perfectly sensible thing to do, until you realize that it means that
very small changes to the code will have drastic effects on the correctness of
your program (if suddenly the compiler is no longer able to prove rational
arithmetic is the same answer). We do have that sort of thing happen with
performance in Julia (and in many other languages too, of course) - if the
compiler can prove it can do something faster, it'll try to, but we try, very,
very hard to give everything predictable, sequential execution semantics (i.e.
you should be able to take code, run it step by step and generally get the
same answer as if you had executed it all at once). One particular example of
this is comprehensions. In early versions of julia, the type of `[f(x) for x
in a]` would depend on what the compiler was able to prove about `f` (and some
other things), e.g. if the compiler knew that `f` always returned an `Int`,
you'd get a `Vector{Int}`, otherwise a `Vector{Any}` (or whatever the compiler
could prove). This turned out to be hugely annoying to people because the
semantics of the computation changed (slightly, only an eltype which you
generally don't look at), depending on what the compiler was or was not able
to prove about your program. These days, we have runtime semantics for non-
empty comprehensions and only use static information to improve performance
(which as I said before, we do anyway, so users are used to it). That's not to
say that you couldn't do a language that changes semantics based on whole
program analysis (you could probably do it in Haskell for example), but you'd
lose part of the gradual transition from REPL to full program, which is very
important to a system like Julia.

------
leephillips
If, for some incomprehensible reason, you are not an LWN subscriber, here is a
free link:

[https://lwn.net/SubscriberLink/763626/f2990348ebd06167/](https://lwn.net/SubscriberLink/763626/f2990348ebd06167/)

Please consider subscribing, so they can pay me and other authors for more
articles.

~~~
sctb
Thanks! We've updated the link so users can get there right away.

------
anonytrary
> Subscription required. The page you have tried to view (An introduction to
> the Julia language, part 1) is currently available to LWN subscribers only.
> Reader subscriptions are a necessary way to fund the continued existence of
> LWN and the quality of its content. If you are already an LWN.net
> subscriber, please log in with the form below to read this content.

I'm pretty sure I can find a tutorial somewhere else.

~~~
kryptiskt
Articles on LWN are publicly available the week after publishing.

