Here, I would like to summarize the free software and programming languages I like to use, possibly giving a short explanation why I prefer them over others and give tools I have tested but dismissed to use at the end.
Julia – Favorite Programming Language
Familar with: C++, Python, Java
Tested: LISP, Clojure, Haskell, C, JavaScript
When I first came across julia back in 2014, I was thinking of at as good exercise to learn a new language, mainly for plotting and analysis part of my daily scientific work. But after playing around with it for a while I soon realized that this new language hast the power to replace anything I used so far and combine speed, easiness and versatility in one solution. For now, I use it for anything from performance related code for cluster calculation to statistical analysis and plotting and even small scripts.
What I particularly like about this language is the integrated parallelism, fully typed code under the hood but only visible if needed, possibility to use UTF8 symbols and the end keyword instead of indentation syntax. Really, I love indentation and I use it to 100%, but that is exactly the reason I don’t want to rely on it as a part of the syntax – goodbye copy/paste and welcome debugging.
In my opinion we will see a big change and growth of the julia language in the upcoming 5 to 10 years.
Basically, it is much closer to julia than previous versions and shares a lot of modern concepts, exact that the syntax is much more complex, usually.
Here is and example code which is an introduction to julia I did for a tutorial.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | # Welcome to julia introduction # by Stanislav Kazmin # You can download julia from: https://julialang.org/downloads/ # The documentation can be found on https://docs.julialang.org/en/v1/ # The forum can be used to ask questions or search for similar problems: https://discourse.julialang.org # After extracting the .tar archive you should be able to run julia by executing bin/julia. # To run a script interactively, load it by executing `include("path/to/script.jl)` inside the REPL. # In my opinion the best way to use julia is within Atom or VS Code where you can send # parts of a script, blocks or the whole file directly to the REPL. # This file is meant to be executed line by line. # The output is written in a comment after the code on the same line. # NOTE: On a 32 bit machine the default types would be Int32 and Float32. # In the REPL when the prompt is empty, typing ? and typing a function/type name (or part of the name) will open the # documentation fo this function/type. # In the REPL when the prompt is empty, typing ] will lead to the package manager mode. # Here one can add packages by typing "add PackageName" (tab works for auto-complete the names). # Some useful packages are PyPlot, Plots, DataFrames. # You can leave the help mode or the package manager mode by pressing the backspace when the prompt is empty. # Once a package is downloaded it can be used by calling e. g. using LinearAlgebra # preinstalled package # Note, that the first call for a specific package may take longer because the packages get precompiled. # lines starting with ‚#‘ or everything after ‚#‘ on the same line is considered as a comment ################################################### # Basics ################################################### # In julia every object/structure/number has a type. # They follow a hierarchy and are essential part of julia’s concept. # Basic number types are 1 # Int64 1.0 # Float64 1e2 # also a Float64, not Int64! 1 // 2 # Rational big"123456789123456789123456789" # BigInt true # Bool false # Bool # One can check the type of any object by calling e. g. typeof(1.0) # When defining a variable we do not have to explicitly state the type. # However a concrete type will be determined by julia. a = 2.0 typeof(a) # Float64 # One can redefine variables and give them other types a = 2 typeof(a) # Int64 # To avoid such redefinitions one can use the `const` prefix (only in global scope). # This will force the variable to have the type it was first defined with. # However, you still will be able to change its value (a warning will be printed, though). const c = 3.14 typeof(c) # Float64 c = 2.71 # WARNING: redefining constant c c = 1 # ERROR: invalid redefinition of constant c ################################################### # Basic Operations ################################################### 1 + 3 # 4 1 + 3.0 # 4.0; the type is "promoted" to the type which can hold the result 1 / 2 # 0.5 (Float64); integer division is promoted to Float64 1 / 2.0 # 0.5 (Float64) div(1, 2) # 0 (Int64); this is the integer division as used in c/cpp 1 ÷ 2 # 0 (Int64); same as div(1, 2) but using the unicode symbol ‚÷‘ 3 * 4 # 12 a = 2.0 3a # 6.0; you can skip the ‚*‘ for multiplication when the number is followed by a variable or parenthesis 3(4 + 5) # 27 4^2 # 16 (Int64); ‚^‘ is the power operator 4.0^6 # 4096.0 1 + 2im # Complex Number # It is a parametric type Complex{Int64} – complex number a + b*i where a and b are Int64. # More on parametric types will be discussed later. # It is useful as you can e. g. perform an exact complex number division bu using rationals (1 + 2im) // (3 – 4im) # -1//5 + 2//5*im typeof(–1//5 + 2//5*im) # Complex{Rational{Int}} # Further, you have the mod operator ‚%‘ and the left-division operator ‚\‘ # ‚\‘ is much more powerful and is used to efficiently solve system of equations in matrix form. 35 / 5 # 7.0 5 \ 35 # 7.0 35 % 7 # 0 35 % 36 # 35 sqrt(2) # 1.4142135623730951 √2 # 1.4142135623730951 √Complex(–2) # 0.0 + 1.4142135623730951im ################################################### # Strings ################################################### # Strings are enclosed into double quotes. # Single quotes define a single character (different type). s = "This is a string." # Multi-line strings can be defined through tripled double quotes. s2 = """First line Second line""" # Alternatively you can use the new line escape character \n. s3 = "First line\nSecond line" s2 == s3 # true # String concatenation is done with ‚*‘ (not ‚+‘ like in other languages, because the operation in non-commutative). "String 1" * " String 2" # However, this is rarely needed as one can use a very powerful string interpolation with ‚$‘. a = 1 b = "COOL!" "a is $a. When we add 3 to it, it becomes $(a + 3). $(b)" ################################################### # Functions ################################################### # Functions are defined with the ‚function‘ keyword. # The return value is the last statement in the function. # The ‚return‘ keyword is optional. function add1(x) x + 1 # same as return x + 1 end # You can use a shorter notation. add1(x) = x + 1 # You can define default values for the arguments (the arguments without default values come first). myadd(x, y = 0) = x + y myadd(1) # 1 myadd(1, 2) # 3 # myadd(x = 0, y) is not valid. # You can define keyword arguments after a semicolon ‚;‘. question(surname, q = "How are you?"; answer = "I’m fine!") = "$(q) $(surname): $(answer)" question("Martin") # "How are you? Martin: I’m fine!" question("Robot", "How old are you?") # "How old are you? Robot: I’m fine!" question("Ann"; answer = "I am sleepy…") # "How are you? Ann: I am sleepy…" # Functions in julia are first class elements. # They can be passed as arguments to other function and defined within other functions. # They never belong to a certain object like in cpp or python. f(x) = 2*x mymap(f, x) = f(x) mymap(f, 2) # 4 mymap(identity, 2) # 2 # Because functions are first class, julia offers a convenient anonymous/lambda function notation. x –> 2*x # this is a function without a name mymap(x –> 2*x, 2) # 4 mymap(x –> x^3, 2) # 8 mymap((x, y = 4) –> x^y, 2) # 16 # Larger lambda functions can be defined by using ‚function‘ keyword but skipping the name. function (x) x^2 end # To return multiple values you can use a tuple. f(x, y) = (2*x, 3*y) f(3, 3) # (6, 9) # You can use the splice operator ‚…‘ to define arbitrary number of arguments. varargs(x…) = x varargs(1) # (1,) tuple with one element ≠ 1 varargs(1, 2) # (1, 2) varargs(1, 2, 3, 4, 5) # (1, 2, 3, 4, 5) # In a similar way you can split the arguments into a function call with ‚…‘ f(x, y) = x + y f((1,2)…) # 3 # when calling a function and using keyword arguments you can ether use a semicolon or a comma. # f(x, y; a = 1) or f(x, y, a = 1) # An important aspect is that you can specify the type of the arguments for a function and by this dispatch on the types. # Julia will dispatch on the types of all arguments. myfunc(x, y) = "generic" myfunc(x::String, y::String) = "both are strings" myfunc(x::Number, y) = "x is a number" myfunc(1, 3) # "x is a number" myfunc((3,4), 3) # "generic" myfunc("a", "s") # "both are strings" # It is important to know, that julia will always deduce the type of all arguments # and compile/call the function which matches the types (called a method). # This allows julia to produce very efficient code. ################################################### # Ranges ################################################### # A useful type in julia is the range type. # You can define a range with the ‚:‘ operator or with the range function 1:10 typeof(1:10) # UnitRange{Int64} 1:2:10 # 1:2:9; start at 1 and go in steps of 2 until ≤ 10 range(1, 10; step = 1) # 1:1:10 range(1, 10; step = 0.1) # 1.0:0.1:10.0 range(1, 9; length = 101) # 1.0:0.08:9.0 range(1, step = 1, length = 10) # 1:1:10 0.0 : –0.01 : -π # 0.0:-0.01:-3.14 ################################################### # Control Flow ################################################### # Every block in julia starts with a keyword and ends with ‚end‘. # conditions are defined by in the following way a = 3 if a > 2 println("larger") end # larger a = 1 if a > 2 println("larger") else println("smaller") end # smaller a = 2 if a > 2 println("larger") elseif a < 2 println("smaller") else println("equal") end # equal # The trinary operator is also available. 2 > 1 ? true : false # true # You can use ! to invert the condition. !(2 > 1) ? true : false # false # Finally, you can use lazy && (and) and || (or) for conditional execution 2 > 1 && (d = true) # true d # true 0 > 1 || (d = false) # false d # false 0 > 1 && (d = 45) # false (here, the d = 45 was not performed, as the first condition was wrong, this is the why it is called "lazy") d # false # We can do a simple for loop (iterating over a certain variable). # You can use ‚in, ‚=‘ or ‚∈‘ in the for loop definition. # The values to iterate over can be arrays, ranges, generators, strings, … for i in 1:10 println(i) end # a while loop executed as long as the condition is true function easy_while() i = 1 while i < 10 println(i) i += 1 end end easy_while() # NOTE: in julia for and while introduce a new local scope. # To access variables outside the loop in the global scope you have to use ‚global‘. # However, inside a function you can access variables outside the loop! x = 0 for i ∈ 1:10 global x += i end x # 55 # but function for_loop() x = 0 for i ∈ 1:10 x += i end return x end for_loop() # 55 # you can use ‚continue‘ or ‚break‘ inside a for loop to manipulate the flow for i in 1:10 if i == 2 continue end if i == 5 break end println(i) end # prints 1, 3 and 4 # You can always use ‚begin‘ and ‚end‘ to enclose code (useful in Atom/VS code to call a whole code block). begin a = 1 b = 2 end # You can introduce local scopes with ‚let‘ x = 0 let x = 0 for i ∈ 1:10 x += i end @show x # x = 55 end # 55 x # 0 (the global variable was not changed) ################################################### # Unicode Characters and Syntactic Sugar ################################################### # In julia you are allowed to use (nearly) any UTF8 character. # In the REPL you can start to type ‚\‘ and the corresponding latex name like \alpha # and then press TAB to auto-complete the the unicode character α. # In Atom/VS Code/Emacs (and others?) you have extensions for inserting unicode characters. π # π = 3.1415926535897… α = 2 Σ = sum Σ([1, 2, 3]) # 6 a +² b = a^2 + b^2 # you can define arbitrary infix operators by appending some subscripts/superscripts to them. 3 +² 4 # 25 f ⊕ g = x –> f(x) + g(x) # apply f and g on x and take the sum f(x) = 2x g(x) = x + 3 (f ⊕ g)(4) # 15 # function concatenation (f ∘ g)(4) # 14; the same as f(g(4)) # result piping g(4) |> f # 14 |
And here is a working implementation of forward auto-differentiation, i.e., numerically exact computer differentiation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | struct Dual{T <: Number} <: Number x::T dx::T end Dual(x::Number, y::Number) = Dual(promote(x, y)…) Base.convert(::Type{Dual{T}}, x::Dual{T}) where T = x Base.convert(::Type{Dual{T}}, x::Dual) where {T <: Number} = Dual(convert(T, x.x), convert(T, x.dx)) Base.convert(::Type{Dual{T}}, x::Number) where {T <: Number} = Dual(convert(T, x), zero(x)) Base.promote_rule(::Type{Dual{T}}, ::Type{Dual{U}}) where {T <: Number,U <: Number} = Dual{promote_type(T, U)} Base.promote_rule(::Type{Dual{T}}, ::Type{U}) where {T <: Number,U <: Number} = Dual{promote_type(T, U)} Base.:+(u::Dual, v::Dual) = Dual(u.x + v.x, u.dx + v.dx) Base.:-(u::Dual) = Dual(-u.x, -u.dx) Base.:-(u::Dual, v::Dual) = u + -v Base.:*(u::Dual, v::Dual) = Dual(u.x * v.x, u.dx * v.x + v.dx * u.x) Base.:inv(u::Dual) = Dual(1 / u.x, -u.x / u.dx^2) Base.:/(u::Dual, v::Dual) = u * inv(v) Base.abs(a::Dual) = Dual(abs(a.x), a.dx * sign(a.x)) Base.exp(a::Dual) = Dual(exp(a.x), a.dx * exp(a.x)) Base.log(a::Dual) = Dual(log(a.x), a.dx / a.x) Base.sqrt(a::Dual) = Dual(√(a.x), a.dx / (2 * √(a.x))) Base.:^(a::Dual, b::Dual) = exp(b * log(a)) Base.sin(a::Dual) = Dual(sin(a.x), a.dx * cos(a.x)) Base.cos(a::Dual) = Dual(cos(a.x), a.dx * -sin(a.x)) autodiff(f, x) = f(Dual(x, one(x))).dx Base.adjoint(f::Function) = x –> autodiff(f, x) d(f::Function) = x –> autodiff(f, x) Base.:^(f::Function, ::Val{0}) = identity Base.:^(f::Function, ::Val{N}) where N = f^(N – 1) ∘ f Base.:^(f::Function, n::Integer) = ^(f, Val(n)) # examples of usage f(x) = 2 * x g(x) = x^3 (d)(f)(3) # df/dx at 3 (d)(g)(3) # dg/dx at 3 (d^2)(g)(3) # d^2g/dx^2 at 3 # or even f‚(3) # df/dx at 3 g‘(3) # dg/dx at 3 g“(3) # d^2g/dx^2 at 3 |
Git – Version Control
Git, basically nothing more to say here. The best version control system I have ever seen. I use it for LaTeX projects, letters, code, tutorials. Nevertheless, I usually use it from within and IDE, which directly brings me to the next topic.
VS Code – My IDE and Text Editor
Tested: Atom, KDevelop, Sublime Text, Emacs, Vim, Kate, Code::Blocks, Brackets
Nothing was harder to find for my than a good text editor/IDE for my workflow. After a lot of testing and searching I finally found the solution. VS Code brings everything I need for any type of editing. This main list includes:
- integrated git
- integrated terminal
- integrated julia code execution
- syntax highlighting
- LaTeX tools and synced preview
- spell and grammar checking
- customizable everything
- free
- fast
Be sure to use the unbranded version instead of the proprietary Microsoft branded one.
LaTeX – Markup Language
For everything written I finally ended where I first have started – LuaLaTeX. I was very impressed by pandoc and the possibility to use it to convert to e-book and online formats but at the end of the day nothing than LaTeX was flexible enough to realize my ideas in the way I wanted them. Once you get in touch with LaTeX, you will eventually find yourself writing simple letters with it, not just because you can but more because it will always work and produce high quality results.
Further software
Photo Editor | DarkTable and Gimp |
Audio Editor | Ardour |
Bibliography | Zotero with Better BibTeX Plugin |
System | Arch Linux with KDE Plasma |