Book Image

Julia Programming Projects

By : Adrian Salceanu
Book Image

Julia Programming Projects

By: Adrian Salceanu

Overview of this book

Julia is a new programming language that offers a unique combination of performance and productivity. Its powerful features, friendly syntax, and speed are attracting a growing number of adopters from Python, R, and Matlab, effectively raising the bar for modern general and scientific computing. After six years in the making, Julia has reached version 1.0. Now is the perfect time to learn it, due to its large-scale adoption across a wide range of domains, including fintech, biotech, education, and AI. Beginning with an introduction to the language, Julia Programming Projects goes on to illustrate how to analyze the Iris dataset using DataFrames. You will explore functions and the type system, methods, and multiple dispatch while building a web scraper and a web app. Next, you'll delve into machine learning, where you'll build a books recommender system. You will also see how to apply unsupervised machine learning to perform clustering on the San Francisco business database. After metaprogramming, the final chapters will discuss dates and time, time series analysis, visualization, and forecasting. We'll close with package development, documenting, testing and benchmarking. By the end of the book, you will have gained the practical knowledge to build real-world applications in Julia.
Table of Contents (19 chapters)
Title Page
Copyright and Credits
Dedication
About Packt
Contributors
Preface
Index

Why Julia?


In a nutshell, Julia truly is a new breed of programming language that successfully manages to combine the high performance of compiled languages with the agility of the dynamic ones, through a friendly syntax that feels natural and intuitive right from the start. Julia is fast (programs are compiled at runtime to efficient native code for multiple platforms), general (the standard library supports, out of the box, powerful programming tasks including asynchronous I/O, process control, parallel, and distributed computing, logging, profiling, package management, and more), dynamic and optionally typed (it is dynamically-typed with optional type declarations and comes with a powerful read-eval-print loop (REPL) for interactive and exploratory coding). It is also technical (excelling at numerical computing) and composable (thanks to its rich ecosystem of packages that are designed to work together seamlessly and with high performance).

Although initially it focused on addressing the needs of high-performance numerical analysis and computational science, recent releases have positioned the language in the area of general computing, with many classes of specialized functions being moved out of the core into dedicated modules. As such, it is also a great fit for client and server-side programming, due to its powerful capabilities for concurrent, parallel, and distributed computing. 

Julia implements a type system based on parametric polymorphism and multiple dispatch, it is garbage-collected, uses eager evaluation, packs a powerful regular expression engine, and can call C and Fortran functions without glue code. 

Let's take a look at the most important features of the language, the parts that make Julia stand out. If you're considering Julia for your next project, you can use this as a quick checklist against your requirements.

Good performance

The key to Julia's performance is the combination between the LLVM-based just-in-time (JIT) compiler and a series of strategic design decisions that allow the compiler to generate code that approaches, and most of the times matches, the performance of C.

To give you an idea of where Julia stands in this regard, the official website provides a series of micro-benchmarks against other mainstream languages (including C, Python, R, Java, JavaScript, Fortran, Go, Rust, MATLAB, and Octave) implementing some algorithms for computing the Fibonacci sequence, the Mandelbrot set, a quicksort and a few others. They are designed to evaluate compiler performance against common code patterns such as function calls, string parsing, sorting, iterations, recursion, and more. There is a plot of the benchmarks, available at https://julialang.org/benchmarks/, which illustrates Julia's consistent top performance across all of the tests. The following plot depicts this:

Note

For more details about the testing methodology, you can visit https://julialang.org/benchmarks/.https://julialang.org/benchmarks/

Concise, readable, and intuitive syntax

The creators of Julia have carefully picked the most successful elements of syntax from other languages, with the goal of producing expressive, concise, and readable code. Julia provides powerful and expressive language constructs for high-level numerical computing, in the same way as languages such as R, MATLAB, and Python do. It builds upon the experience brought by existing mathematical programming languages but also borrows much from popular dynamic ones, such as Lisp, Perl, Python, Lua, and Ruby.

To give you a quick taste of idiomatic Julia, here's how to open a file, read it, output it, and then have the file automatically closed by Julia:

open(".viminfo") do io
    read(io, String) |> println
end  

In the preceding snippet, we open the .viminfo file for reading passing io, an IOStream instance, into the underlying code block. The stream is then read into a String that is finally displayed onto the console by piping it into the println function. The code is very readable and easy to understand if you have some coding experience, even if this is your first time looking at Julia code.

This so-called do syntax (named after the do part following the open function) is inspired by Ruby's blocks—and it is, in fact, syntactic sugar for passing anonymous functions as method arguments. It is efficiently used in the preceding example to succinctly express a powerful design pattern for safely handling files, guaranteeing that the resources are not accidentally left open.

This goes to show the amount of attention that was put by the designers of the language to make Julia safe, beginner-friendly, expressive, concise, readable, and intuitive.

Powerful and productive dynamic type system

Julia's type system is a key feature of the language and one that has a major impact on both its performance and productivity. The type system is dynamic and optional, meaning that the developer can, but is not required to, provide type information to the compiler. If not provided, Julia will perform type inference, which is the process of deducing the types of later values from the types of input values. This is a very powerful technique, as it frees the programmers from having to worry about types, allowing them to focus on the application logic and making for a gentler learning curve. This is especially useful for prototyping and exploratory programming, when the complete set of constraints and requirements is not known beforehand.

However, understanding and correctly using the type system offers important performance benefits. Julia allows optionally adding type information, making it possible to indicate that a certain value must be of a specific kind. This is one of the cornerstones of the language, allowing performant method dispatching and facilitating the automatic generation of efficient, specialized code for different argument types. The type system allows the definition of rich type hierarchies, with user-defined types as fast and compact as the built-in ones.

Designed for parallelism and distributed computation

If the languages of the 70s and 80s were designed under the strict requirements imposed by the limited CPU and RAM resources, the ones in the 90s and the 2000s had the optimistic outlook that these resources are forever expanding. However, the last decade had seen something of a stagnation in this regard, with a shift toward multi-CPU, multi-core, and distributed computing. In this regard, Julia's inception only 6 years ago gave it an edge compared to older languages, putting parallel and distributed computing at its center as one of its most important features.

Efficient intercommunication with other languages

One of the most serious barriers in the adoption of a new language is that it takes time for the ecosystem to catch up—and in the beginning, it cannot offer libraries of the quality and richness of the already established languages. This is less of an issue now, when Julia benefits from a large, enthusiastic and continuously growing developer community. But being able to seamlessly communicate with other languages is a very efficient way to enrich existing functionality and to effortlessly supplement any missing features.

Julia has the ability to directly call C and Fortran functions (that is, without glue code)—especially important for scientific computing, where these languages have a strong presence and a long history.

Optional packages extend this capability by adding support for calling functions written in other languages, most notably Python, via PyCall. And there are others, supporting interaction with Java, C++, MATLAB, Rust, and more.

Powerful REPL and shell-like capabilities

The REPL represents a language shell, an interactive computer programming environment at the command line. Julia has an excellent REPL, supporting sophisticated code inputting and evaluation. It includes powerful editing features such as searchable history, tab-completion, and syntax highlighting, to name just a few.

It also comes with three special modes—shell, which allows executing commands as if at the OS Terminal; help, which provides access to documentation without leaving the REPL; and pkg, used for installing and managing application dependencies.

And more...

Julia comes with its own powerful package manager that resolves dependencies and handles the adding and removal of extra packages. Like most modern languages, Julia has full support for Unicode. And finally, it is distributed under the liberal MIT license—it is free and open source.