I have been using the Julia programming language for three years, and as a daily user, watched it grow up to 1.0 and beyond. For those who are unfamiliar with the language, it is best to start here. I find it to be an excellent tool for writing easy to understand, maintainable, and extensible code. This post is for developers, if you aren't a developer, this may not be for you.

High performance, high level programming

The effortless achievement of high performance code is really amazing. None of the insanity of C++. No build systems to maintain, blazing performance. Basically cheating. Solves the two language problem beautifully.

Type system, along with multiple dispatch

Julia has a powerful type system, and using the type system correctly is at the core of good Julia programming. Types greatly simplify the programming experience, as you can have some certainty about what variables you are using. Multiple dispatch makes it very easy to create a variety of interfaces which can handle the need for long blocks of switch statements in a very simple manner.

switch(your_var)
  case(type(your_var) == type_b)
  ....
  case(type(your_var) == type_z)

to

my_operation(your_var)

where my_operation is defined for each of the cases. I find it easy to use functional paradigms in Julia, resulting in side effect free code that is simple to reason about and easy to maintain.
This construct also allows for simple extensibility. Say you write (or find) a module

module BasePackage
    struct Foo
    a
    b
  end
  function proc(foo::Foo)
    return foo.b
  end
  
  function do_something(foo, pol)
    println(proc(foo))
  end
    
end

Say you want to use do_something in your code, but just want to change proc.

module ExtensionPackage
import BasePackage:proc
struct Bar
  c
  d
 end
 function proc(bar::Bar)
   return bar.c*bar.d
 end
end

Then,

using ExtensionPackage:Bar
using BasePackage:do_something
do_something(Bar(3,4), 5)

Yields 12, as expected. No need to manage complex inheritance, or worse multiple inheritance.

REPL + Revise

The REPL (or Read, Evaluate, Print, Loop interface) allows for quick prototyping and documentation checks, which greatly improves productivity, allowing you to find what function you want and learn how to use it. There is a huge productivity gain using the REPL with Revise: hot reloading in the REPL of your changes in your file, no waiting for recompilation. Instead of recompiling and rerunning your code to see what the effect of a change is, you can test it immediately.

The REPL is also a great interface that allows you to test code fragments. Quick questions can be answered by running just one line of code.

Language Interoperability and Scripting

It is very easy to tie Julia to C/C++, Python, R, or even just command line calls in order to use your existing code. Julia is the best glue language I have ever used. mkdir, mktempdir, cp, rm, and a bunch of other convenient system calls are there to use as Julia functions.

High Quality packages

Unitful and DifferentialEquations make modelling problems much more tractable. Modia.jl is a high performance physical systems modelling library, Flux.jl is a powerful machine learning library. These packages advance the state of development of whatever technical computing problem you are dealing with by large leaps forward.

High quality community

The Julia community is small, but very talented. The odds are the guy answering your questions knows exactly what he is talking about, and he may be a language developer himself. I've even had a minor flame war with Karpinski himself about the package manager.

Issues

I have one issue with Julia, which is a love/hate relationship with the package manager. If you are working with only registered dependencies, it works great. If you have your own unregistered private packages, it works less well. I might be one of the few guys out there who has to deal with dozens of unregistered packages.