|
| 1 | +<!doctype html> |
| 2 | +<html lang="en" data-theme="light"> |
| 3 | +<head> |
| 4 | + <meta charset="UTF-8"> |
| 5 | + <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 6 | + <meta name="google-site-verification" content="9CIsKebPd-hNdMScya0EZx2Z_GtQ9g3yDXmpbgs2mrU" /> |
| 7 | + |
| 8 | + <link rel="stylesheet" href="/libs/highlight/styles/github.min.css"> |
| 9 | + |
| 10 | + |
| 11 | +<link rel="stylesheet" href="/css/franklin.css" /> |
| 12 | +<link rel="stylesheet" href="/css/icons.css" /> |
| 13 | +<link rel="icon" href="/assets/avatar.svg" /> |
| 14 | + |
| 15 | +<!-- Font Awesome Icons --> |
| 16 | +<link |
| 17 | + rel="stylesheet" |
| 18 | + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" |
| 19 | +/> |
| 20 | + |
| 21 | + |
| 22 | +<link rel="stylesheet" href="/css/nav.css" /> |
| 23 | +<link rel="stylesheet" href="/css/sidebar.css" /> |
| 24 | +<link rel="stylesheet" href="/css/cards.css" /> |
| 25 | +<link rel="stylesheet" href="/css/showcase.css" /> |
| 26 | +<link rel="stylesheet" href="/css/software.css" /> |
| 27 | +<link rel="stylesheet" href="/css/posts.css" /> |
| 28 | +<link rel="stylesheet" href="/css/gallery.css" /> |
| 29 | + |
| 30 | + |
| 31 | + <title>Brian C. Ferrari's Website</title> |
| 32 | +</head> |
| 33 | +<body> |
| 34 | + |
| 35 | + |
| 36 | + <div class="masthead"> |
| 37 | + <nav> |
| 38 | + <div class="author-name-nav"> |
| 39 | + <li><a href="/">Brian C. Ferrari</a></li> |
| 40 | + </div> |
| 41 | + <a class="theme-switch" onclick="toggleTheme()"> |
| 42 | + <i id="theme-icon" class="fas fa-moon"></i> |
| 43 | + </a> |
| 44 | + <a class="burger-nav" onclick="myFunction()"> |
| 45 | + <i class="fa-2x fa fa-bars"></i> |
| 46 | + </a> |
| 47 | + <div class="desktop-nav"><li> |
| 48 | + <a href="/pages/aboutMe">About Me</a> |
| 49 | +</li> |
| 50 | + |
| 51 | +<li> |
| 52 | + <a href="/pages/software">Software</a> |
| 53 | +</li> |
| 54 | + |
| 55 | +<li> |
| 56 | + <a href="/pages/blog">Blog</a> |
| 57 | +</li> |
| 58 | + |
| 59 | +</div> |
| 60 | + <div id="hidden" class="mobile-nav"><li> |
| 61 | + <a href="/pages/aboutMe">About Me</a> |
| 62 | +</li> |
| 63 | + |
| 64 | +<li> |
| 65 | + <a href="/pages/software">Software</a> |
| 66 | +</li> |
| 67 | + |
| 68 | +<li> |
| 69 | + <a href="/pages/blog">Blog</a> |
| 70 | +</li> |
| 71 | + |
| 72 | +</div> |
| 73 | + </nav> |
| 74 | +</div> |
| 75 | + |
| 76 | + <div class="academic-sidebar"> |
| 77 | + <div class="author_avatar"><img |
| 78 | + src="/assets/figs/me.jpg" |
| 79 | + class="author_avatar" |
| 80 | + alt="Brian C. Ferrari" |
| 81 | + /></div> |
| 82 | + |
| 83 | + <h3>Brian C. Ferrari</h3> |
| 84 | + |
| 85 | + <!-- Pronouns are a class --> |
| 86 | + <p class="pronouns"> |
| 87 | + (he/him) |
| 88 | + </p> |
| 89 | + |
| 90 | + <!-- Bio is just text --> |
| 91 | + Chemistry PhD Candidate at Leiden University |
| 92 | + <br /><br /> |
| 93 | + |
| 94 | + <br><br> |
| 95 | +<li> |
| 96 | + <a href="https://www.linkedin.com/in/brian-ferrari-001b8a163/" target=_blank> |
| 97 | + <i class="fa fa-brands fa-linkedin" aria-hidden="true"></i> |
| 98 | + </a> |
| 99 | +</li> |
| 100 | +<li> |
| 101 | + <a href="https://orcid.org/0000-0002-7416-8629" target=_blank> |
| 102 | + <i class="fa fa-brands fa-orcid" aria-hidden="true"></i> |
| 103 | + </a> |
| 104 | +</li> |
| 105 | +<li> |
| 106 | + <a href="https://www.researchgate.net/profile/Brian-Ferrari-2?ev=hdr_xprf" target=_blank> |
| 107 | + <i class="fa fa-brands fa-researchgate" aria-hidden="true"></i> |
| 108 | + </a> |
| 109 | +</li> |
| 110 | +<li> |
| 111 | + <a href="https://github.com/Cavenfish" target=_blank> |
| 112 | + <i class="fa fa-brands fa-github" aria-hidden="true"></i> |
| 113 | + </a> |
| 114 | +</li> |
| 115 | +<li> |
| 116 | + <a href="https://scholar.google.com/citations?user=col48NcAAAAJ&hl=en" target=_blank> |
| 117 | + <i class="fa fa-graduation-cap" aria-hidden="true"></i> |
| 118 | + </a> |
| 119 | +</li> |
| 120 | + |
| 121 | +</div> |
| 122 | + |
| 123 | + |
| 124 | +<!-- Content appended here --> |
| 125 | +<div class="franklin-content"> |
| 126 | +<h1 id="tips_and_tricks_for_julia_programming"><a href="#tips_and_tricks_for_julia_programming" class="header-anchor">Tips and Tricks for Julia programming</a></h1> |
| 127 | +<p>At this point there is a wealth of information for the Julia programming language. Perhaps one of the best sources (outside of the official documentation or discourse forum) is <a href="https://m3g.github.io/JuliaNotes.jl/stable/">JuliaNotes.jl</a>. Personally, I find that more available information is better and since I'm a big fan of Julia, I've decided to make my own contribution.</p> |
| 128 | +<p>Here I'll outline some basic, but at times lesser-known, tips and tricks for writing Julia code.</p> |
| 129 | +<h2 id="ternary_conditional_operator"><a href="#ternary_conditional_operator" class="header-anchor">Ternary Conditional Operator</a></h2> |
| 130 | +<p>Julia has the ternary operator for <code>if-else</code> statements. The best way to explain it is to show two equivalent blocks of code. First, one that uses <code>if-else</code></p> |
| 131 | +<pre><code class="language-julia">for i = 1:10 |
| 132 | + if i > 5 |
| 133 | + println("big") |
| 134 | + else |
| 135 | + println("small") |
| 136 | + end |
| 137 | +end</code></pre> |
| 138 | +<p>This lengthy <code>if-else</code> statement can be replaced with a ternary operator while still preserving the logic in the code.</p> |
| 139 | +<pre><code class="language-julia">for i = 1:10 |
| 140 | + i > 5 ? println("big") : println("small") |
| 141 | +end</code></pre> |
| 142 | +<p>Within this ternary expression, the <code>?</code> operator denotes which boolean expression (what comes before it) is being evaluated. The <code>:</code> operator separates the <code>if</code> (before the <code>:</code>) and <code>else</code> (after the <code>:</code>) outcomes. This can help shrink lengthy code blocks, but it comes with the additional cost of increased code complexity. However, once familiar with the ternary operator, the complexity of the expression goes away. </p> |
| 143 | +<h2 id="short_circuit_expressions"><a href="#short_circuit_expressions" class="header-anchor">Short Circuit Expressions</a></h2> |
| 144 | +<p>In Julia the short circuit operators are <code>&&</code> (<code>and</code> operator), and <code>||</code> (<code>or</code> operator). The most basic use for them is conditional statements.</p> |
| 145 | +<pre><code class="language-julia">x = 5 |
| 146 | + |
| 147 | +if (x > 3) && (x < 6) |
| 148 | + println("True") |
| 149 | +end</code></pre> |
| 150 | +<p>In strictly-typed languages, these expressions can only evaluate to a boolean, as is the case in the example above. However, Julia is a loosely-typed language, which affords it the ability to return the last value in this expression. This becomes a powerful tool for simplifying conditional statements, although some argue that it unnecessarily increases the complexity of the code. Below I show how you can convert the <code>if</code> statement above into a one-line short circuit expression.</p> |
| 151 | +<pre><code class="language-julia">x = 5 |
| 152 | + |
| 153 | +(x > 3) && (x < 6) && println("True")</code></pre> |
| 154 | +<p>This expression is equivalent to the <code>if</code> statement; as such, it only prints <code>True</code> if both conditionals are satisfied (in this case they are). Since both code blocks shown are equivalent, the choice for which to use comes down to personal preference (or the repo style guide). I personally find it convenient to use these statements for <code>continue</code> conditionals within loops.</p> |
| 155 | +<pre><code class="language-julia">for i = 1:10 |
| 156 | + i == 5 && continue |
| 157 | + println(i) |
| 158 | +end</code></pre> |
| 159 | +<h2 id="pipes"><a href="#pipes" class="header-anchor">Pipes</a></h2> |
| 160 | +<p>If you are familiar with Bash scripting in Linux, then you will already be familiar with pipes. In Julia, the pipe operator is <code>|></code>. They can be used to redirect the output of something into another function. For example, if you have functions <code>foo</code> and <code>bar</code> such that you can run <code>bar(foo(x))</code>, then you can also rewrite this as <code>foo(x) |> bar</code>. A handy use case for pipes is to avoid defining multiple temporary variables, while also avoiding hard-to-read nested calls.</p> |
| 161 | +<pre><code class="language-julia">foo(x) = 2 * sin(x) |
| 162 | +bar(x) = 3 * x^2 |
| 163 | + |
| 164 | +# Several tmp vars |
| 165 | +tmp1 = rand() |
| 166 | +tmp2 = foo(tmp1) |
| 167 | +x = bar(tmp2) |
| 168 | + |
| 169 | +# Multiple nested calls |
| 170 | +x = bar(foo(rand())) |
| 171 | + |
| 172 | +# One clean easy to read line |
| 173 | +x = rand() |> foo |> bar</code></pre> |
| 174 | +<h2 id="anonymous_functions"><a href="#anonymous_functions" class="header-anchor">Anonymous Functions</a></h2> |
| 175 | +<p>An anonymous function is (as the name suggests) a function without a name. In Julia, these are done by using the <code>-></code> operator. A simple <code>f(x) = 2 * x^2</code> function can be anonymized as <code>x -> 2 * x^2</code>; however, this example does not properly showcase the value of these anonymous functions. Although they can be used in numerous ways, they are most often used in two ways.</p> |
| 176 | +<ol> |
| 177 | +<li><p>Alongside pipes</p> |
| 178 | +</li> |
| 179 | +</ol> |
| 180 | +<p>Sometimes you want to pipe output into a function that takes multiple arguments. In those cases, you need to couple a pipe and an anonymous function. The example below shows a simple version of this use case.</p> |
| 181 | +<pre><code class="language-julia">foo(x) = 6 * x^2 |
| 182 | +bar(x,y) = x^2 - y^2 |
| 183 | + |
| 184 | +z = rand() |> foo |> (x -> bar(x, 6))</code></pre> |
| 185 | +<p>In this example the output of <code>foo</code> is piped into an anonymous function (<code>x -> bar(x, 6)</code>) which passes the output into <code>bar</code> alongside an additional argument.</p> |
| 186 | +<ol start="2"> |
| 187 | +<li><p>Within function calls</p> |
| 188 | +</li> |
| 189 | +</ol> |
| 190 | +<p>Many built-in functions take an expression/function as an argument, for instance, <code>filter</code> and <code>find</code> take expressions that evaluate to booleans as arguments.</p> |
| 191 | +<pre><code class="language-julia">x = rand(50) |
| 192 | + |
| 193 | +filter(e -> e > 0.5, x)</code></pre> |
| 194 | +<p>The code block above uses the anonymous function <code>e -> e > 0.5</code> as the expression argument for <code>filter</code>, which in this case filters out the values larger than 0.5 from the array <code>x</code>. </p> |
| 195 | +<h2 id="base_functions_with_custom_types"><a href="#base_functions_with_custom_types" class="header-anchor">Base Functions with Custom Types</a></h2> |
| 196 | +<p>This feature involves Julia's multiple dispatch, which is simply when multiple functions have the same name but different arguments. This allows you to write custom base functions for custom types. This is easier to understand through an example. </p> |
| 197 | +<pre><code class="language-Julia">struct Point{F <: Float64} |
| 198 | + x::F |
| 199 | + y::F |
| 200 | + z::F |
| 201 | +end |
| 202 | + |
| 203 | +function Base.show(io::IO, point::Point) |
| 204 | + println(io, "(x,y,z) = ($(point.x),$(point.y),$(point.z))") |
| 205 | +end</code></pre> |
| 206 | +<p>The example above shows how to make a custom <code>show</code> function for a custom type <code>Point</code>. This is called "extending" the <code>show</code> function. This makes it so that when you display variables of the type <code>Point</code>, they will be displayed using the custom <code>show</code> function above. This means that when instantiating a variable <code>p = Point(1.0, 2.0, 3.0)</code> in the <code>repl</code>, the following output will be <code>(x,y,z) = (1.0,2.0,3.0)</code>.</p> |
| 207 | +<p>This can be done to all functions you have access to within your Julia code, even those from other imported packages. An important consideration here is to make sure you avoid "type piracy", where you extend a function on types that you did not define. For example,</p> |
| 208 | +<pre><code class="language-julia">Base.show(io::IO, f::Float64) = println(io, "This is type piracy")</code></pre> |
| 209 | +<p>extending <code>show</code> on the <code>Float64</code> type (which would not be extending but rather "redefining", since it already exists) is a case of type piracy. This is considered bad practice since it can cause unexpected behavior within your code, or someone else's code if they import your code.</p> |
| 210 | +<div class="page-foot"> |
| 211 | + | Website built with <a href="https://franklinjl.org/">Franklin.jl</a> | |
| 212 | + <a href="/sitemap.xml">Sitemap</a> | |
| 213 | +</div> |
| 214 | +</div><!-- CONTENT ENDS HERE --> |
| 215 | + |
| 216 | + |
| 217 | + <script src="/libs/highlight/highlight.min.js"></script> |
| 218 | +<script>hljs.highlightAll();hljs.configure({tabReplace: ' '});</script> |
| 219 | + |
| 220 | + |
| 221 | + <script src="/libs/buttons/nav.js"></script> |
| 222 | + <script src="/libs/buttons/theme.js"></script> |
| 223 | + </body> |
| 224 | +</html> |
0 commit comments