Glossario

Seleziona una delle parole chiave a sinistra ...

Programming in JuliaCustom types

Momento della lettura: ~10 min

Suppose you want to write a program which keeps track of the albums you own. Each album is associated with several data, like the name of the album, the year it came out, the number of tracks, etc. You could store all these data by assigning them to different variables, but that becomes untidy very quickly. For example, you will frequently want to pass an album to a function, and you don't want that function to require a long list of parameters just because the album has a lot of data associated with it.

What you want is to be able to treat each album as its own Julia object, with all its associated data stored inside. In other words, you want an Album type. You can do that with the struct keyword.

struct Album
    name
    artist
    year
    duration
end

A = Album("Abbey Road", "The Beatles", 1969, "47:23")

In the last line, we have defined a new object of type Album and saved it to the variable A. We call name, artist, year, and duration fields of the Album type. The fields of an object can be accessed by name using dot syntax:

A.duration

We can define functions to operate on our new data type. For example, we might want to be able to calculate how old an album was as of a given year. We can specify types for a function's arguments using double colon syntax:

function num_years_ago(A::Album, year::Integer)
    year - A.year
end

Note: Integer is an abstract type which encompasses Int64, Int32 (which uses 32 bits instead of 64), and any other type which represents a mathematical integer.

One reason it's helpful to be able to specify type information when defining a function is that we can specify different behavior for different types:

function num_years_ago(earlier_year::Integer, later_year::Integer)
    later_year - earlier_year
end

num_years_ago(A, 2019) # returns 50
num_years_ago(1986, 2019) # returns 33

We say that num_years_ago now has two methods: one which accepts an Album as its first argument and an Integer as its second argument, and one which accepts Integers for both arguments. Julia is responsible for correctly dispatching each function call to the correct method. This feature of Julia is called multiple dispatch.

Exercise
Write a type Line for representing non-vertical lines in the plane. Write a two-argument method intersect which finds the intersection point of two lines (you may return the intersection point as a tuple of floats, and for simplicity, you can assume the lines intersect).

Solution. Since we only need to store non-vertical lines, we can represent every line via its slope and intercept. We can specify that these data types should be Float64s if we want:

struct Line
    slope::Float64
    intercept::Float64
end

The intersection point of two lines is given by

function intersect(L::Line,M::Line)
    x = -(L.intercept-M.intercept)/(L.slope-M.slope)
    y = L.intercept + x*L.slope
    (x,y)
end
Bruno
Bruno Bruno