Today, we're going to be teaching a bunch of random Julia concepts we think are interesting. Hopefully, you guys like it and find some of these concepts enjoyable. Because we're going to be dealing with more packages this week, use this block of code to instantiate packages if you're having issues loading them:
using Pkg; Pkg.instantiate()
First, let's present the problems for homework. These were:
"The kids will go nuts for this one" - Christian
Julia is great in that it provides the PyCall
package. You can import the PyCall package and import Python packages and run Python code.
using PyCall
base64 = pyimport("base64") # importing modules with pyimport
# b64 encode a string
base64.b64encode(b"Hi class!")
# b64 decode a string
base64.b64decode(b"SGkgY2xhc3Mh")
# Import whatever modules you want (ex: math, hashlib, requests etc)
hl = pyimport("hashlib")
hl.sha256(b"hi class!").hexdigest()
# current XKCD comic: https://xkcd.com/info.0.json
requests = pyimport("requests")
requests.get("https://xkcd.com/info.0.json").json()["alt"]
# writing a method using a triple quoted string
py"""
def hello_world():
return "Hello world!"
"""
# calling the method
py"hello_world"()
# evaluating stuff
py"5+5"
We can also write Julia in Python using the julia
package in Python. You can sorta just import Julia modules into Python.
# going to the terminal to run python-jl
Now we're going to be covering some more advanced Julia programming features. First up, Julia macros! A Julia macro returns a piece of code, wrapped in a :( code )
that is executed when you call the macro. So, it's kinda like a function that returns a function, which then, when you call it, calls the code it returns.
# Write sayhello macro
macro sayhello()
return :( println("hi class!") )
end
# call sayhello
@sayhello
We can also pass functions to our macros, so our macros can control how the functions execute, like Python decorators.
isAllowed = false
# Write security macro
macro security(e::Expr)
if isAllowed
return e
end
return "You aren't allowed to do that!"
end
# test security macro
@security println("Hello!")
Symbol
s¶A Symbol
in Julia is sort of in between a string, but they're treated similar to the names of functions or variables. Symbols start with a colon :
and can have any name you want.
# Defining some symbols
sinsymb = :sin
We can use symbols to talk about functions or variables. Notice that if we eval
a symbol, we get the thing it represents.
# eval-ing some symbols
eval(sinsymb)(π)
So this gets really neat, because now we can use symbols as standins for function names, especially in common with the @eval
macro, which does eval(quote( code ))
. Say, we want to make a unit circle:
for funcname = [:fun1, :fun2, :fun3]
@eval $funcname(x) = "I am $($funcname) with param $x"
end
fun3(5)
In short, Symbol
→ eval
call → thing the symbol represents (function, variable). It's beyond the scope of this class, but Symbol
s and Expr
s allow you to generate Julia code really quickly, which is documented in the Metaprogramming section of the Julia docs.
Expr
s¶An Expr
in Julia is a piece of code that can be evaluated, kind of like an "expanded" Symbol. They're what a macro returns. If we want to get extra fancy, we can talk about quote
blocks. They can contain code and we can call them with the eval(code)
method.
# Defining and calling a quote block
code = quote
num = 5+5
string = "hello"
println(num, string)
end
# Writing a macro to return a quote
macro doExpression()
return code
end
@doExpression
using CSV, DataFrames
# pulling in roster and setup
students = DataFrame(CSV.File("C14008 Roster and Setup - Attendance Wk 2.csv"))
We access DataFrames similarly to Julia matrices, df[rows, cols]
.
# pull attendance for 1-Aug and Student Name
students[:, ["25-Jul","1-Aug"]]
We can use the describe
method to learn overall information about our DataFrame, like the percentage of students that showed up to each class!
# describe students
describe(students)[:, Not(["min", "max", "nmissing"])]
We can also add conditions while we're picking which rows and columns we want, by specifying the "1-Aug" column in the rows
parameter.
# only pick students that showed up for class on August 1st
students[students[:, "1-Aug"], :]
# A closer look at how this actually works
students[:, "1-Aug"]
Plots
¶Now, let's try and use the Plots
package to visualize some of this data. First, we need to import the Plots
package and tell it we're going to use the GR
backend.
using Plots
gr()
Now, let's just plot some mathematical functions, by using a function in place of y
.
# plotting functions
plot(x=0:5, x -> ℯ^x)
Now, to plot some data out of our Data Frame, we can plot the number of students that showed up to class on each date:
dates = ["18-Jul", "25-Jul", "1-Aug"]
bar([sum(col) for col in eachcol(students[:, dates])], xaxis=("date"))
Plotting daily weather data for the memes
# pull temp data
using PyCall
py"""
import requests
weather = requests.get("https://forecast.weather.gov/MapClick.php?lat=30.33&lon=-97.74&unit=0&lg=english&FcstType=json").json()
"""
data = py"weather"
# plot temperature data
plot(parse.(Int, data["data"]["temperature"]), yaxis=("temperature", (75,105)))
There's actually no homework! Today's lecture was just mostly for fun, and next lecture is challenge day. If you're itching for something to do, then go have some fun solving Euler problems. Otherwise, sit back, relax, ask questions, and get ready for next week!