Skip to content

Commit 9ebd290

Browse files
committed
add julia tips and tricks to blog
1 parent 0ef9bc7 commit 9ebd290

2 files changed

Lines changed: 216 additions & 7 deletions

File tree

pages/blog/coding/julia_tips.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
+++
2+
cover = false
3+
+++
4+
5+
# Tips and Tricks for Julia programming
6+
7+
At this point there is a wealth of information for the Julia programming
8+
language. Perhaps one of the best sources (outside of the official documentation
9+
or discourse forum) is [JuliaNotes.jl](https://m3g.github.io/JuliaNotes.jl/stable/).
10+
Personally, I find that more available information is better and since I'm a
11+
big fan of Julia, I've decided to make my own contribution.
12+
13+
Here I'll outline some basic, but at times lesser-known, tips and tricks for
14+
writing Julia code.
15+
16+
## Ternary Conditional Operator
17+
18+
Julia has the ternary operator for `if-else` statements. The best way to explain
19+
it is to show two equivalent blocks of code. First, one that uses `if-else`
20+
21+
```julia
22+
for i = 1:10
23+
if i > 5
24+
println("big")
25+
else
26+
println("small")
27+
end
28+
end
29+
```
30+
31+
This lengthy `if-else` statement can be replaced with a ternary operator while
32+
still preserving the logic in the code.
33+
34+
```julia
35+
for i = 1:10
36+
i > 5 ? println("big") : println("small")
37+
end
38+
```
39+
40+
Within this ternary expression, the `?` operator denotes which boolean expression
41+
(what comes before it) is being evaluated. The `:` operator separates the `if`
42+
(before the `:`) and `else` (after the `:`) outcomes. This can help shrink
43+
lengthy code blocks, but it comes with the additional cost of increased code
44+
complexity. However, once familiar with the ternary operator, the complexity
45+
of the expression goes away.
46+
47+
## Short Circuit Expressions
48+
49+
In Julia the short circuit operators are `&&` (`and` operator), and `||`
50+
(`or` operator). The most basic use for them is conditional statements.
51+
52+
```julia
53+
x = 5
54+
55+
if (x > 3) && (x < 6)
56+
println("True")
57+
end
58+
```
59+
60+
In strictly-typed languages, these expressions can only evaluate to a boolean,
61+
as is the case in the example above. However, Julia is a loosely-typed language,
62+
which affords it the ability to return the last value in this expression. This
63+
becomes a powerful tool for simplifying conditional statements, although some
64+
argue that it unnecessarily increases the complexity of the code. Below I show
65+
how you can convert the `if` statement above into a one-line short circuit expression.
66+
67+
```julia
68+
x = 5
69+
70+
(x > 3) && (x < 6) && println("True")
71+
```
72+
73+
This expression is equivalent to the `if` statement; as such, it only prints
74+
`True` if both conditionals are satisfied (in this case they are). Since both
75+
code blocks shown are equivalent, the choice for which to use comes down to
76+
personal preference (or the repo style guide). I personally find it convenient
77+
to use these statements for `continue` conditionals within loops.
78+
79+
```julia
80+
for i = 1:10
81+
i == 5 && continue
82+
println(i)
83+
end
84+
```
85+
## Pipes
86+
87+
If you are familiar with Bash scripting in Linux, then you will already be
88+
familiar with pipes. In Julia, the pipe operator is `|>`. They can be used to
89+
redirect the output of something into another function. For example, if you
90+
have functions `foo` and `bar` such that you can run `bar(foo(x))`, then you
91+
can also rewrite this as `foo(x) |> bar`. A handy use case for pipes is to
92+
avoid defining multiple temporary variables, while also avoiding hard-to-read
93+
nested calls.
94+
95+
```julia
96+
foo(x) = 2 * sin(x)
97+
bar(x) = 3 * x^2
98+
99+
# Several tmp vars
100+
tmp1 = rand()
101+
tmp2 = foo(tmp1)
102+
x = bar(tmp2)
103+
104+
# Multiple nested calls
105+
x = bar(foo(rand()))
106+
107+
# One clean easy to read line
108+
x = rand() |> foo |> bar
109+
```
110+
111+
## Anonymous Functions
112+
113+
An anonymous function is (as the name suggests) a function without a name.
114+
In Julia, these are done by using the `->` operator. A simple `f(x) = 2 * x^2`
115+
function can be anonymized as `x -> 2 * x^2`; however, this example does not
116+
properly showcase the value of these anonymous functions. Although they can be
117+
used in numerous ways, they are most often used in two ways.
118+
119+
1) Alongside pipes
120+
121+
Sometimes you want to pipe output into a function that takes multiple arguments.
122+
In those cases, you need to couple a pipe and an anonymous function. The example
123+
below shows a simple version of this use case.
124+
125+
```julia
126+
foo(x) = 6 * x^2
127+
bar(x,y) = x^2 - y^2
128+
129+
z = rand() |> foo |> (x -> bar(x, 6))
130+
```
131+
132+
In this example the output of `foo` is piped into an anonymous function
133+
(`x -> bar(x, 6)`) which passes the output into `bar` alongside an additional
134+
argument.
135+
136+
2) Within function calls
137+
138+
Many built-in functions take an expression/function as an argument, for instance,
139+
`filter` and `find` take expressions that evaluate to booleans as arguments.
140+
141+
```julia
142+
x = rand(50)
143+
144+
filter(e -> e > 0.5, x)
145+
```
146+
147+
The code block above uses the anonymous function `e -> e > 0.5` as the
148+
expression argument for `filter`, which in this case filters out the values
149+
larger than 0.5 from the array `x`.
150+
151+
## Base Functions with Custom Types
152+
153+
This feature involves Julia's multiple dispatch, which is simply when multiple
154+
functions have the same name but different arguments. This allows you to
155+
write custom base functions for custom types. This is easier to understand
156+
through an example.
157+
158+
```Julia
159+
struct Point{F <: Float64}
160+
x::F
161+
y::F
162+
z::F
163+
end
164+
165+
function Base.show(io::IO, point::Point)
166+
println(io, "(x,y,z) = ($(point.x),$(point.y),$(point.z))")
167+
end
168+
```
169+
170+
The example above shows how to make a custom `show` function for a custom
171+
type `Point`. This is called "extending" the `show` function. This makes it
172+
so that when you display variables of the type `Point`, they will be displayed
173+
using the custom `show` function above. This means that when instantiating a
174+
variable `p = Point(1.0, 2.0, 3.0)` in the `repl`, the following output will
175+
be `(x,y,z) = (1.0,2.0,3.0)`.
176+
177+
This can be done to all functions you have access to within your Julia code,
178+
even those from other imported packages. An important consideration here is
179+
to make sure you avoid "type piracy", where you extend a function on types
180+
that you did not define. For example,
181+
182+
```julia
183+
Base.show(io::IO, f::Float64) = println(io, "This is type piracy")
184+
```
185+
186+
extending `show` on the `Float64` type (which would not be extending but
187+
rather "redefining", since it already exists) is a case of type piracy.
188+
This is considered bad practice since it can cause unexpected behavior within
189+
your code, or someone else's code if they import your code.

pages/blog/index.md

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,30 @@ name = "Blog"
44
+++
55

66
My blog is mostly a collection of random tutorials/guides on how to do things
7-
(mostly coding based). I will also occasionally write some product reviews.
7+
(mostly coding based). I will also occasionally write some product reviews,
8+
share pictures of animals, or ramble about some topic.
9+
10+
In theory, a person will read through my posts, maybe even find some of them
11+
helpful, but certainly a robot will read them. To me, it doesn't matter if
12+
my posts help someone directly or if an AI uses them to give someone a response.
13+
In both cases, I'm still happy to have provided something that became useful to
14+
someone.
15+
16+
## Animal Pictures
817

918
\post{
10-
"Climbing Shoe Reviews",
11-
"My thoughts on climbing shoes I've owned.",
12-
"/pages/blog/product_reviews/climbing_shoes.md"
19+
"Pigeon Pictures",
20+
"A collection of pictures I've taken of pigeons.",
21+
"/pages/blog/gallery/pigeons.md"
22+
}
23+
24+
## Coding
25+
26+
\post{
27+
"Julia Tips and Tricks",
28+
"Several basic, but at times lesser-known, tips and tricks for
29+
writing Julia code.",
30+
"/pages/blog/coding/julia_tips.md"
1331
}
1432

1533
\post{
@@ -18,8 +36,10 @@ My blog is mostly a collection of random tutorials/guides on how to do things
1836
"/pages/blog/coding/cvr_example.md"
1937
}
2038

39+
## Product Reviews
40+
2141
\post{
22-
"Pigeon Pictures",
23-
"A collection of pictures I've taken of pigeons.",
24-
"/pages/blog/gallery/pigeons.md"
42+
"Climbing Shoe Reviews",
43+
"My thoughts on climbing shoes I've owned.",
44+
"/pages/blog/product_reviews/climbing_shoes.md"
2545
}

0 commit comments

Comments
 (0)