Skip to content

Instantly share code, notes, and snippets.

@mauro3

mauro3/#README Secret

Last active May 21, 2019 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mauro3/6089af612380cb39ca00016d4f632cc2 to your computer and use it in GitHub Desktop.
Save mauro3/6089af612380cb39ca00016d4f632cc2 to your computer and use it in GitHub Desktop.
Julia-Intro
From
https://github.com/JuliaComputing/JuliaBoxTutorials/tree/master/introductory-tutorials/intro-to-julia/short-version
lightly adapted.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Getting to know Julia\n",
"\n",
"\n",
"This notebook is meant to offer a crash course in Julia syntax to show you that Julia is lightweight and easy to use -- like your favorite high-level language!\n",
"\n",
"We'll talk about\n",
"- Strings\n",
"- Data structures\n",
"- Loops\n",
"- Conditionals\n",
"- Functions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Strings"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"string1 = \"How many cats \""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"string2 = \"is too many cats?\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"string(string1, string2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"😺 = 10\n",
"println(\"I don't know but $😺 are too few!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note: Julia allows us to write super generic code, and 😺 is an example of this. \n",
"\n",
"This allows us to write code like"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"😺 = 1\n",
"😀 = 0\n",
"😞 = -1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"😺 + 😞 == 😀"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Data structures"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Tuples\n",
"\n",
"We can create a tuple by enclosing an ordered collection of elements in `( )`.\n",
"\n",
"Syntax: <br>\n",
"```julia\n",
"(item1, item2, ...)```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"myfavoriteanimals = (\"penguins\", \"cats\", \"sugargliders\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"myfavoriteanimals[1]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Dictionaries\n",
"\n",
"If we have sets of data related to one another, we may choose to store that data in a dictionary. To do this, we use the `Dict()` function.\n",
"\n",
"Syntax:\n",
"```julia\n",
"Dict(key1 => value1, key2 => value2, ...)```\n",
"\n",
"A good example of a dictionary is a contacts list, where we associate names with phone numbers."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"myphonebook = Dict(\"Jenny\" => \"867-5309\", \"Ghostbusters\" => \"555-2368\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"myphonebook[\"Jenny\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Arrays\n",
"\n",
"Unlike tuples, arrays are mutable. Unlike dictionaries, arrays contain ordered sequences of elements. <br>\n",
"We can create an array by enclosing this sequence of elements in `[ ]`.\n",
"\n",
"Syntax: <br>\n",
"```julia\n",
"[item1, item2, ...]```\n",
"\n",
"\n",
"For example, we might create an array to keep track of my friends"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"myfriends = [\"Ted\", \"Robyn\", \"Barney\", \"Lily\", \"Marshall\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fibonacci = [1, 1, 2, 3, 5, 8, 13]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mixture = [1, 1, 2, 3, \"Ted\", \"Robyn\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also create arrays of other data structures, or multi-dimensional arrays."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"numbers = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rand(4, 3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Loops\n",
"\n",
"### `for` loops\n",
"\n",
"The syntax for a `for` loop is\n",
"\n",
"```julia\n",
"for *var* in *loop iterable*\n",
" *loop body*\n",
"end\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for n in 1:10\n",
" println(n)\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `while` loops\n",
"\n",
"The syntax for a `while` is\n",
"\n",
"```julia\n",
"while *condition*\n",
" *loop body*\n",
"end\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"n = 0\n",
"while n < 10\n",
" n += 1\n",
" println(n)\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conditionals\n",
"\n",
"#### with `if`\n",
"\n",
"In Julia, the syntax\n",
"\n",
"```julia\n",
"if *condition 1*\n",
" *option 1*\n",
"elseif *condition 2*\n",
" *option 2*\n",
"else\n",
" *option 3*\n",
"end\n",
"```\n",
"\n",
"allows us to conditionally evaluate one of our options."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x, y = # Enter two numbers here!\n",
"if x > y\n",
" x\n",
"else\n",
" y\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### with ternary operators\n",
"\n",
"For this last block, we could instead use the ternary operator with the syntax\n",
"\n",
"```julia\n",
"a ? b : c\n",
"```\n",
"\n",
"which equates to \n",
"\n",
"```julia\n",
"if a\n",
" b\n",
"else\n",
" c\n",
"end\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"(x > y) ? x : y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Functions\n",
"\n",
"Topics:\n",
"1. How to declare a function\n",
"2. Duck-typing in Julia\n",
"3. Mutating vs. non-mutating functions\n",
"4. Some higher order functions\n",
"\n",
"### How to declare a function\n",
"\n",
"#### First way: with `function` and `end` keywords"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"f (generic function with 1 method)"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function f(x)\n",
" x^2\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Second way: with `=`"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"f2 (generic function with 1 method)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f2(x,y,z) = x^2 + y^2 +\n",
" z^2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Third way: as an anonymous function"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f3 = x -> x^2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Calling these functions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f(42)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f2(42)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f3(42)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Duck-typing in Julia\n",
"*\"If it quacks like a duck, it's a duck.\"* <br><br>\n",
"Julia functions will just work on whatever inputs make sense. <br><br>\n",
"For example, `f` will work on a matrix. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"A = rand(3, 3)\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f(A)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"On the other hand, `f` will not work on a vector. Unlike `A^2`, which is well-defined, the meaning of `v^2` for a vector, `v`, is ambiguous. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"v = rand(3)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f(v)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Mutating vs. non-mutating functions\n",
"\n",
"By convention, functions followed by `!` alter their contents and functions lacking `!` do not.\n",
"\n",
"For example, let's look at the difference between `sort` and `sort!`."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 3\n",
" 5\n",
" 2"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v = [3, 5, 2]"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 2\n",
" 3\n",
" 5"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sort(v)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 3\n",
" 5\n",
" 2"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`sort(v)` returns a sorted array that contains the same elements as `v`, but `v` is left unchanged. <br><br>\n",
"\n",
"On the other hand, when we run `sort!(v)`, the contents of v are sorted within the array `v`."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 2\n",
" 3\n",
" 5"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sort!(v)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 2\n",
" 3\n",
" 5"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Some higher order functions\n",
"\n",
"#### map\n",
"\n",
"`map` is a \"higher-order\" function in Julia that *takes a function* as one of its input arguments. \n",
"`map` then applies that function to every element of the data structure you pass it. For example, executing\n",
"\n",
"```julia\n",
"map(f, [1, 2, 3])\n",
"```\n",
"will give you an output array where the function `f` has been applied to all elements of `[1, 2, 3]`\n",
"```julia\n",
"[f(1), f(2), f(3)]\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"map(f, [1, 2, 3])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we've squared all the elements of the vector `[1, 2, 3]`, rather than squaring the vector `[1, 2, 3]`.\n",
"\n",
"To do this, we could have passed to `map` an anonymous function rather than a named function, such as"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x -> x^3"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"via"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"map(x -> x^3, [1, 2, 3])"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"and now we've cubed all the elements of `[1, 2, 3]`!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### broadcast\n",
"\n",
"`broadcast` is another higher-order function like `map`. `broadcast` is a generalization of `map`, so it can do every thing `map` can do and more. The syntax for calling `broadcast` is the same as for calling `map`"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 1\n",
" 4\n",
" 9"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"broadcast(f, [1, 2, 3])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"and again, we've applied `f` (squared) to all the elements of `[1, 2, 3]` - this time by \"broadcasting\" `f`!\n",
"\n",
"Some syntactic sugar for calling `broadcast` is to place a `.` between the name of the function you want to `broadcast` and its input arguments. For example,\n",
"\n",
"```julia\n",
"broadcast(f, [1, 2, 3])\n",
"```\n",
"is the same as\n",
"```julia\n",
"f.([1, 2, 3])\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Float64,1}:\n",
" 0.2431975046920718\n",
" 3.0410757253368614\n",
" 8.720584501801074 "
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f.([1, 2, 3]) .+ sin.([4,5,6])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice again how different this is from calling \n",
"```julia\n",
"f([1, 2, 3])\n",
"```\n",
"We can square every element of a vector, but we can't square a vector!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To drive home the point, let's look at the difference between\n",
"\n",
"```julia\n",
"f(A)\n",
"```\n",
"and\n",
"```julia\n",
"f.(A)\n",
"```\n",
"for a matrix `A`:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Int64,2}:\n",
" 1 2 3\n",
" 4 5 6\n",
" 7 8 9"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = [i + 3*j for j in 0:2, i in 1:3]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Int64,2}:\n",
" 30 36 42\n",
" 66 81 96\n",
" 102 126 150"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f(A)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As before we see that for a matrix, `A`,\n",
"```\n",
"f(A) = A^2 = A * A\n",
"``` \n",
"\n",
"On the other hand,"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Int64,2}:\n",
" 1 4 9\n",
" 16 25 36\n",
" 49 64 81"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B = f.(A)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"contains the squares of all the entries of `A`.\n",
"\n",
"This dot syntax for broadcasting allows us to write relatively complex compound elementwise expressions in a way that looks natural/closer to mathematical notation. For example, we can write"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Int64,2}:\n",
" 3 6 9\n",
" 12 15 18\n",
" 21 24 27"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"C = A .+ 2 .* f.(A) .÷ A"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"instead of"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"broadcast(x -> x + 2 * f(x) / x, A)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"and this will still compile down to code that runs as efficiently as `C`!"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"### Exercises\n",
"\n",
"#### 6.1 \n",
"Write a function `add_one` that adds 1 to its input."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"add_one (generic function with 1 method)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"add_one(x) = x+1"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"deletable": false,
"editable": false,
"hide_input": true,
"nbgrader": {
"checksum": "253b17dc2f3d3a58042fbc36042a0fd5",
"grade": true,
"grade_id": "cell-5119b9e9623c1cb7",
"locked": true,
"points": 1,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"@assert add_one(1) == 2"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"deletable": false,
"editable": false,
"hide_input": true,
"nbgrader": {
"checksum": "4e05440e19cd3606df11186d41d562bf",
"grade": true,
"grade_id": "cell-50f83d27187a2064",
"locked": true,
"points": 1,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"@assert add_one(11) == 12"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 6.2 \n",
"Use `map` or `broadcast` to increment every element of matrix `A` by `1` and assign it to a variable `A1`."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Int64,2}:\n",
" 2 3 4\n",
" 5 6 7\n",
" 8 9 10"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A1 = map(x->x+1, A)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"#### 6.3 \n",
"Use the broadcast dot syntax to increment every element of matrix `A1` by `1` and store it in variable `A2`"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Int64,2}:\n",
" 4 5 6\n",
" 7 8 9\n",
" 10 11 12"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A2 = A1 .+ 2"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"deletable": false,
"editable": false,
"hide_input": true,
"nbgrader": {
"checksum": "3e3d797962df904deed0e7ee7782b69a",
"grade": true,
"grade_id": "cell-f3bd5479679a8fe1",
"locked": true,
"points": 0,
"schema_version": 1,
"solution": false
}
},
"outputs": [
{
"ename": "AssertionError",
"evalue": "AssertionError: A2 == [3 4 5; 6 7 8; 9 10 11]",
"output_type": "error",
"traceback": [
"AssertionError: A2 == [3 4 5; 6 7 8; 9 10 11]",
"",
"Stacktrace:",
" [1] top-level scope at In[25]:1"
]
}
],
"source": [
"@assert A2 == [3 4 5; 6 7 8;9 10 11]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.1.0",
"language": "julia",
"name": "julia-1.1"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.1.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment