Welcome back to The Comprehensive Julia Tutorials! Today we are going to be taking a general overview of multiple concepts such as indexing, scope, and working better with different types. We are of course going to be doing this all in order to further the development of our SuperFrames.jl package! We are also going to be looking further into the real power that is Julia by extending the Julian base to do whatever we need it to do! This is easily one of the greatest things about Julia, as it makes it easy to work with modules across the board, even if it was never the original creators intention for you to be working with it. Often times, programmers need to write their own syntax in order to facilitate something like extensions, but that is certainly not the case with Julia!
Scope and Indexes
The first topic I wanted to review today is scope. Scope is an incredibly important programming concept that is absolutely crucial to understand. In languages like Julia, we might not be used to this as typically most things are written to perform in the global scope. However, it is important to remember that this is not always the case. Scope effects every aspect of how we choose to program a package, or just about anything. Everything in a language has scope, and there are different levels of access to that scope.
For instance, our SuperFrames module has a SuperFrame struct that is private to that module. Therefore, it cannot be called anywhere else unless it is loaded into there. This goes further down the line with functions. Consider that we can write different functions with the same argument and variable names without ever redefining a constant.
Another important thing we are going to be looking at is indexing. Indexing is a way to access certain parts of an iterable directly with a number representing its position in the iteration process. Julia iterables start their indexes with 1, not 0, so we can call any number 1–3 in this 3-element array in order to get a specific index in return:
array = [5, 10, 15]
This actually calls the Base.getindex method, which we are now going to extend in order to make direct calls for indexes on our SuperFrame type.
Now that we have a proper inner constructor to create our SuperFrame type, we need to be able to work with this type outside of its constructor with methods. The most important aspect to working with this data in this regard is most certainly going to be the ability to actually index and call this data effectively. As of right now, we would have to call our child object, the lookup dictionary. The code would look something like this:
Of course, we would like to call this with
That makes a lot of sense. We can do this by changing the functionality of the getindex method when used on our SuperFrame type. We are also going to do this with setindex, in order to allow us to add new columns. Of course, this is done with Julia’s dispatch. In order to dispatch method calls to provide new functionality, we will also need to import the method in question explicitly:
import Base: getindex, setindex!
Now we will extend the two functions from base in order to provide the exact types of calls we desire:
getindex(sf::SuperFrame, s::Symbol) = sf.lookup[s]
setindex!(sf::SuperFrame, x::Array, s::Symbol) = push!(sf.lookup, s => x)
We can now call indexes of the lookup dictionary on our type directly by calling our type! Just as well, we can set these indexes in order to create new columns! In the next episode, we will be taking things a step further with display output! I think that you are really going to like what I have in store! Thank you very much for sticking around, and I hope these tutorials are helpful on your Julian DS/ML journey!