10 advanced tips for new programmers Julia | by Emmet Boudreau | Jul 2022

0

Some tips and conventions for programmers new to Julia.

picture by Clint Patterson on Unsplash

JThe Julia programming language is beautiful, with a unique and versatile paradigm that is often unmatched by other options available today. However, with any new programming concept or programming language, there will be some level of education to start using it. Of course, Julia is no different, and her interesting new paradigm comes with a substantial amount of learning needed to really master the language.

I’ve been using Julia for a while and love the language. The language is incredibly satisfying and easy to use. However, no language is without its nuances and recommendations. There will always be a substantial difference between the experience of developers in a given programming language. Since I’ve been using Julia for a while, I’ve accumulated many different little things that I wish I had known when I first started. Today, I’d like to shed some light on that little bit of information, providing context for the various ins and outs of the Julia programming language while simultaneously helping to make my readers the best Julia programmers possible!

№1: Follow naming conventions

My first piece of advice is to follow the naming conventions in Julia. Naming conventions are extremely valuable because they allow us to distinguish what we are looking at without going through additional investigation. For example, I know by looking at the name Array whether it will be a Type a AbstractType or one Module . I can distinguish this because the name starts with a capital letter. If it should be named array , however, I’m guessing it’s some sort of method with the same name as array, which could potentially be a cast or something. For lowercase letters, these can describe

  • variables
  • methods
  • and constants.

Methods, at least when called, are distinguished by a parenthesis after their name, e.g.

mymethod()

Immediately looking at this we can determine that it is a method. If we were to use the method without calling it, then it would be considered to be used as a variable or a constant. Although variables and constants are a little harder to tell apart, these two are both quite similar and in nature, so it certainly makes sense that the naming conventions are so close.

№2: Take advantage of insights

Julia is a language that has unparalleled understandings. There’s simply no other language that has done comprehensions as well as Julia, and I’m not just saying that. With such an amazing comprehension syntax, we can replace iterative loops entirely, opting instead for much faster comprehensions. The difference between an understanding loop and an iterative loop is actually quite significant.

An iterative loop creates a new exclusive private scope inside a function or an environment. This means that everything inside this loop is exclusive to the loop unless we define it outside the loop. This often results in the traditional technique of first creating new values ​​and then pushing those values ​​into some sort of defined structure outside the private scope of the loop so that we can access them later. A comprehension, on the other hand, broadcasts a function to the elements of an iterable and generates a return. Additionally, iterative loops are significantly slower than comprehensions, which creates an even more definitive reason to use comprehensions more frequently. This is a subject I have discussed in more detail here:

№3: Anonymous functions are super powerful

One thing you should probably learn relatively early in Julia is the power of anonymous functions. These functions are easy to write and can be written both using normal code and the correct logical operator, as well as with the begin/end syntax. Anonymous functions are used everywhere in Julia in everything from the filter! method to find! method and understandings. These types of functions certainly have quite a large application in Julia. Consider the following example, using findall :

x = [5, 100, 5, 1, 2, 5]
findall(n -> n == 5, x)
[1, 3, 6]

It really doesn’t get any better than being able to do everything you could do with a function. Anonymous functions are an incredibly easy way to write functions without creating a definition or function block.

https://towardsdatascience.com/what-on-earth-is-an-anonymous-function-f8043eb845f3

№4 Explicit typing

Something all newcomers to Julia should probably know is that Julia is incredibly explicit. That being said, it’s very important to keep types in mind when working with any type of value, as failure to do so can lead to a significant amount of error. This applies both to multicasting, where even parameter passing must be explicit, as well as to conversions using the convert method.

Types are something you will constantly want to pay attention to when using Julia. Types are going to be handled in a very specific way, and not paying attention to the type of something you’re using can produce a lot of potentially annoying method errors. One of the ways to manage these types efficiently, while improving performance, is to use type annotations.

№5: Annotate (almost) everything

If you’ve recently decided to jump ship from Python and try out the wonderful world of Julia programming, you’re probably unfamiliar with the concept of annotations. If so, chances are you’re also looking to build performance-critical software. Annotating different variables, returns and arguments in Julia can greatly contribute to the performance of your function.

Additionally, the correct type annotation can provide much more context to arguments, as well as a sensible MethodError whenever the wrong type is provided.

№6: Type Parameters

If you’ve been using Julia for a while, it’s probably a good idea to familiarize yourself with type parameters. You may have seen them before in Julia code, where it is quite common to label the type of contained values ​​with the type parameter. Type parameters are also incredibly simple to provide and actually help speed up the software considerably. In this regard, it is important to provide parameter subtypes correctly and to use parameters rather than abstract types when entering fields. For instance,

struct Example{T <: Number}
x::T
Example(i::Int64) = new{Int64}(i)
Example(i::Float64) = new{Float64}(i)
end

Rather than

struct Example
x::Number
Example(i::Int64) = new(i)
Example(i::Float64) = new(i)
end

Parameters also work to create new dispatches for the same type. This can be useful for a number of reasons. For example, we might want to multiply an array of Int64 with .*, but concatenate an array of strings with .*.

№7: find (all, next, last…)

One of the most useful methods in Julia is findall. This method can be used to search elements for values ​​that meet certain requirements. The function roughly takes a BitArray, an array of 1s and 0s, but this kind of type is often obtained using an anonymous function. Providing an anonymous function will return a new array containing each index where the condition was met. Besides the findall method, there are other search methods, such as findnext and findlast. These are slightly different, as they return an Int64, but they aren’t significantly different either. These are incredibly valuable functions to learn and will probably come in handy more than you think.

№8: varinfo

A really cool method in Julia is called varinfo. This provides information about all the values ​​set in your current environment, including modules, functions, and of course global variables. It’s great because we can even access this data, which is stored in a new Markdown table.

julia> x = varinfo()
name size summary
–––––––––––––––– ––––––––––– ––––––––––––––––––––
Base Module
Core Module
InteractiveUtils 253.909 KiB Module
Main Module
ans 1.385 KiB Markdown.MD
c 72 bytes CarouselArray{Int64}

This can alert us to the memory usage of different values, as well as their type. It can be useful for so many different applications! We can even provide a modulus as an argument to get the memory usage for each individual value inside a given modulus.

julia> varinfo(CarouselArrays)
name size summary
–––––––––––––– ––––––––––– ––––––––
CarouselArray 40 bytes UnionAll
CarouselArrays 148.603 KiB Module

№9: Basic methods

Something I often see new Julia users get confused about is my constant extension of Julia’s Base. This is an incredibly important concept at Julia, and definitely something you should do! Part of the beauty of Julia is that we can explicitly import different functions and supply them with new methods with our types. This is how everything from indexing to display is done in Julia. For a few examples of this on my blog, you really don’t have to look very far, but here are a few posts that I think stand out where I extend Julia’s Base.

If you prefer to learn using video content, there’s a full Julia tutorial for that too!

It’s random, but there will be many more of these tutorials, plus many more to come soon on my channel, so keep an eye out for that 🙂

№10: Broadcasting

The last knowledge of Julia that I would like to share is broadcasting. Casting in Julia allows us to apply any language function to the elements of an array. Needless to say, since Julia is quite a popular choice when it comes to working with data, such a technique is incredibly often useful. We can stream any function using either the @. macro, or the broadcast function. Casting is as simple as calling them on a given array with our function.

julia> broadcast(+, [5, 10], [5, 10])
2-element Vector{Int64}:
10
20

For more information on this topic, I also have another post about it (I’ve written nearly 500 posts!):

Share.

Comments are closed.