remove working files
This commit is contained in:
parent
3c68e58554
commit
0aa02d17a4
@ -1,574 +0,0 @@
|
|||||||
---
|
|
||||||
marp: true
|
|
||||||
---
|
|
||||||
|
|
||||||
# Julia for Data Analysis
|
|
||||||
|
|
||||||
## Chapter 2: Getting started with Julia
|
|
||||||
|
|
||||||
### Bogumił Kamiński
|
|
||||||
|
|
||||||
https://github.com/bkamins/JuliaForDataAnalysis
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Outline
|
|
||||||
|
|
||||||
1. Values
|
|
||||||
2. Variables
|
|
||||||
3. Control flow
|
|
||||||
3.1. Conditional evaluation
|
|
||||||
3.2. Loops
|
|
||||||
3.3. Compound expressions
|
|
||||||
4. Defining functions
|
|
||||||
5. Scoping rules
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Values
|
|
||||||
|
|
||||||
* A *value* is a representation of some entity that is stored in computer's
|
|
||||||
memory and can be manipulated by Julia program.
|
|
||||||
* Every value is a result of evaluation of some Julia expression.
|
|
||||||
* Example values created by evaluation of *literals*:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> 0.1
|
|
||||||
0.1
|
|
||||||
|
|
||||||
julia> "Hello world!"
|
|
||||||
"Hello world!"
|
|
||||||
|
|
||||||
julia> [1, 2, 3]
|
|
||||||
3-element Vector{Int64}:
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Types
|
|
||||||
|
|
||||||
* Each value has a type, which you can check using the `typeof` function.
|
|
||||||
* When you define a function you optionally can define the types of arguments
|
|
||||||
that the function accepts.
|
|
||||||
* Example types of values:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> typeof(0.1)
|
|
||||||
Float64
|
|
||||||
|
|
||||||
julia> typeof("Hello world!")
|
|
||||||
String
|
|
||||||
|
|
||||||
julia> typeof([1, 2, 3])
|
|
||||||
Vector{Int64} (alias for Array{Int64, 1})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Checking memory layout of numbers
|
|
||||||
|
|
||||||
* Numbers in Julia can have different types (e.g. `Int64`, `Float64`, `Int8`).
|
|
||||||
* Each such type can use a different memory layout to represent the same
|
|
||||||
mathematical value.
|
|
||||||
* Examples of representation of *one*:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> bitstring(1)
|
|
||||||
"0000000000000000000000000000000000000000000000000000000000000001"
|
|
||||||
|
|
||||||
julia> bitstring(1.0)
|
|
||||||
"0011111111110000000000000000000000000000000000000000000000000000"
|
|
||||||
|
|
||||||
julia> bitstring(Int8(1))
|
|
||||||
"00000001"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Integer type
|
|
||||||
|
|
||||||
On 64-bit machines integers in Julia by default use 64-bit representation
|
|
||||||
(`Int64` type). As a shorthand you can use `Int` alias type name instead:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> Int
|
|
||||||
Int64
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Container types typically have parameters in Julia
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> typeof([1, 2, 3])
|
|
||||||
Vector{Int64} (alias for Array{Int64, 1})
|
|
||||||
```
|
|
||||||
|
|
||||||
* `Vector{Int64}` tells us that `[1, 2, 3]` is a vector that can store
|
|
||||||
integer numbers; the `Int64` part is a parameter of `Vector`;
|
|
||||||
* `Array{Int64, 1}` is another way to write the same; now we have two parameters:
|
|
||||||
1. element type that our array can store (`Int64`, an integer);
|
|
||||||
2. dimension of our array (`1`, a vector).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Checking if value has some type
|
|
||||||
|
|
||||||
You can check if some value has some type using the `isa` operator:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> [1, 2, 3] isa Vector{Int}
|
|
||||||
true
|
|
||||||
|
|
||||||
julia> [1, 2, 3] isa Array{Int64, 1}
|
|
||||||
true
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Variables
|
|
||||||
|
|
||||||
* You can bind a value to a variable name using the assignment operator `=`:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = 1
|
|
||||||
1
|
|
||||||
|
|
||||||
julia> y = [1, 2, 3]
|
|
||||||
3-element Vector{Int64}:
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
```
|
|
||||||
|
|
||||||
* The process of binding does not involve copying of values.
|
|
||||||
Python also follows this approach.
|
|
||||||
In R this is not the case.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Only values have types in Julia
|
|
||||||
|
|
||||||
You can, in general assign values of different types to the same variable name:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = 1
|
|
||||||
1
|
|
||||||
|
|
||||||
julia> typeof(x)
|
|
||||||
Int64
|
|
||||||
|
|
||||||
julia> x = 0.1
|
|
||||||
0.1
|
|
||||||
|
|
||||||
julia> typeof(x)
|
|
||||||
Float64
|
|
||||||
```
|
|
||||||
|
|
||||||
Although this is allowed it is usually not recommended.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# You can use Unicode characters in variable names
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> Kamiński = 1
|
|
||||||
1
|
|
||||||
|
|
||||||
julia> x₁ = 0.5
|
|
||||||
0.5
|
|
||||||
|
|
||||||
julia> ε = 0.0001
|
|
||||||
0.0001
|
|
||||||
```
|
|
||||||
|
|
||||||
In Julia REPL, VS Code ect., you can easily type such characters:
|
|
||||||
|
|
||||||
```
|
|
||||||
help?> ₁
|
|
||||||
"₁" can be typed by \_1<tab>
|
|
||||||
|
|
||||||
help?> ε
|
|
||||||
"ε" can be typed by \varepsilon<tab>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# The `if` statement
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = -7
|
|
||||||
-7
|
|
||||||
|
|
||||||
julia> if x > 0
|
|
||||||
println("positive")
|
|
||||||
elseif x < 0
|
|
||||||
println("negative")
|
|
||||||
elseif x == 0
|
|
||||||
println("zero")
|
|
||||||
else
|
|
||||||
println("unexpected condition")
|
|
||||||
end
|
|
||||||
negative
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Conditions must be Boolean values
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = -7
|
|
||||||
-7
|
|
||||||
|
|
||||||
julia> if x
|
|
||||||
println("condition was true")
|
|
||||||
end
|
|
||||||
ERROR: TypeError: non-boolean (Int64) used in boolean context
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Be careful with numeric comparisons of floats
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> NaN > 0
|
|
||||||
false
|
|
||||||
|
|
||||||
julia> NaN < 0
|
|
||||||
false
|
|
||||||
|
|
||||||
julia> NaN == 0
|
|
||||||
false
|
|
||||||
|
|
||||||
julia> NaN != 0
|
|
||||||
true
|
|
||||||
|
|
||||||
julia> NaN != NaN
|
|
||||||
true
|
|
||||||
|
|
||||||
julia> 0.1 + 0.2 == 0.3
|
|
||||||
false
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Combining logical conditions with `&&` and `||`
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = -7
|
|
||||||
-7
|
|
||||||
|
|
||||||
julia> x > 0 && x < 10
|
|
||||||
false
|
|
||||||
|
|
||||||
julia> x < 0 || log(x) > 10
|
|
||||||
true
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Short-circut evaluation
|
|
||||||
|
|
||||||
`&&` and `||` evaluate only as many conditions (starting from the leftmost) as
|
|
||||||
is needed to determine the logical value of the whole expression.
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = -7
|
|
||||||
-7
|
|
||||||
|
|
||||||
julia> log(x)
|
|
||||||
ERROR: DomainError with -7.0:
|
|
||||||
log will only return a complex result if called with a complex argument. Try log(Complex(x)).
|
|
||||||
|
|
||||||
julia> x < 0 || log(x) > 10
|
|
||||||
true
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# One-line conditional evaluation using `&&` and `||`
|
|
||||||
|
|
||||||
The codes below use short-circut evaluation:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = -7
|
|
||||||
-7
|
|
||||||
|
|
||||||
julia> x < 0 && println(x^2)
|
|
||||||
49
|
|
||||||
|
|
||||||
julia> iseven(x) || println("x is odd")
|
|
||||||
x is odd
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Ternary operator
|
|
||||||
|
|
||||||
Julia supports the *ternary operator* borrowed from the C programming language.
|
|
||||||
|
|
||||||
```
|
|
||||||
x > 0 ? sqrt(x) : sqrt(-x)
|
|
||||||
```
|
|
||||||
|
|
||||||
is equivalent to writing:
|
|
||||||
|
|
||||||
```
|
|
||||||
if x > 0
|
|
||||||
sqrt(x)
|
|
||||||
else
|
|
||||||
sqrt(-x)
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Conditional statements return a value
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = -4.0
|
|
||||||
-4.0
|
|
||||||
|
|
||||||
julia> y = if x > 0
|
|
||||||
sqrt(x)
|
|
||||||
else
|
|
||||||
sqrt(-x)
|
|
||||||
end
|
|
||||||
2.0
|
|
||||||
|
|
||||||
julia> y
|
|
||||||
2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Example `for` loop
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> for i in [1, 2, 3]
|
|
||||||
println(i, " is ", isodd(i) ? "odd" : "even")
|
|
||||||
end
|
|
||||||
1 is odd
|
|
||||||
2 is even
|
|
||||||
3 is odd
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Example `while` loop
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> i = 1
|
|
||||||
1
|
|
||||||
|
|
||||||
julia> while i < 4
|
|
||||||
println(i, " is ", isodd(i) ? "odd" : "even")
|
|
||||||
global i += 1
|
|
||||||
end
|
|
||||||
1 is odd
|
|
||||||
2 is even
|
|
||||||
3 is odd
|
|
||||||
```
|
|
||||||
|
|
||||||
We use `global` keyword in the loop as we want to update the `i` variable which
|
|
||||||
is in global scope.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Standard `break` and `continue` keywords are supported in loops
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> i = 0
|
|
||||||
0
|
|
||||||
|
|
||||||
julia> while true
|
|
||||||
global i += 1
|
|
||||||
i > 6 && break
|
|
||||||
isodd(i) && continue
|
|
||||||
println(i, " is even")
|
|
||||||
end
|
|
||||||
2 is even
|
|
||||||
4 is even
|
|
||||||
6 is even
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Compound expression using `begin`-`end` block
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = -7
|
|
||||||
-7
|
|
||||||
|
|
||||||
julia> x < 0 && begin
|
|
||||||
println(x)
|
|
||||||
x += 1
|
|
||||||
println(x)
|
|
||||||
2 * x
|
|
||||||
end
|
|
||||||
-7
|
|
||||||
-6
|
|
||||||
-12
|
|
||||||
```
|
|
||||||
|
|
||||||
The value of the compound expression is the value of the last expression
|
|
||||||
inside it (`-12` in our case).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Compound expression using semicolon `;`
|
|
||||||
|
|
||||||
If your code is short you can wrap several expressions in parentheses
|
|
||||||
and separate them using semicolon `;`:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = -7
|
|
||||||
-7
|
|
||||||
|
|
||||||
julia> x > 0 ? (println(x); x) : (x += 1; println(x); x)
|
|
||||||
-5
|
|
||||||
-5
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# You can use the `function` keyword to define a function
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> function times_two(x)
|
|
||||||
return 2 * x
|
|
||||||
end
|
|
||||||
times_two (generic function with 1 method)
|
|
||||||
|
|
||||||
julia> times_two(10)
|
|
||||||
20
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Functions allow positional and keyword arguments separated by `;` with optional default values
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> function compose(x, y=10; a, b=10)
|
|
||||||
return x, y, a, b
|
|
||||||
end
|
|
||||||
compose (generic function with 2 methods)
|
|
||||||
|
|
||||||
julia> compose(1, 2; a=3, b=4)
|
|
||||||
(1, 2, 3, 4)
|
|
||||||
|
|
||||||
julia> compose(1, 2; a=3)
|
|
||||||
(1, 2, 3, 10)
|
|
||||||
|
|
||||||
julia> compose(1; a=3)
|
|
||||||
(1, 10, 3, 10)
|
|
||||||
|
|
||||||
julia> compose(1)
|
|
||||||
ERROR: UndefKeywordError: keyword argument a not assigned
|
|
||||||
|
|
||||||
julia> compose(; a=3)
|
|
||||||
ERROR: MethodError: no method matching g(; a=3)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Passing arguments to functions in Julia
|
|
||||||
|
|
||||||
If you pass a value to a function Julia performs a binding of the function
|
|
||||||
argument name to this value. This feature is called *pass-by-sharing* and means
|
|
||||||
that Julia never copies data when arguments are passed to a function.
|
|
||||||
|
|
||||||
This is a behavior that you might know from Python, but is different from e.g.,
|
|
||||||
R, where copying of function arguments is performed.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Short syntax for creation simple functions
|
|
||||||
|
|
||||||
You can use the assignment operator to create one-line functions:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> times_two(x) = 2 * x
|
|
||||||
times_two (generic function with 1 method)
|
|
||||||
|
|
||||||
julia> compose(x, y=10; a, b=10) = x, y, a, b
|
|
||||||
compose (generic function with 2 methods)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Functions are first class objects in Julia
|
|
||||||
|
|
||||||
You can pass functions as arguments to other functions:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> map(times_two, [1, 2, 3])
|
|
||||||
3-element Vector{Int64}:
|
|
||||||
2
|
|
||||||
4
|
|
||||||
6
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# You can define anonymous functions using the `->` operator
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> map(x -> 2 * x, [1, 2, 3])
|
|
||||||
3-element Vector{Int64}:
|
|
||||||
2
|
|
||||||
4
|
|
||||||
6
|
|
||||||
|
|
||||||
julia> sum(x -> x ^ 2, [1, 2, 3])
|
|
||||||
14
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Julia supports `do` blocks
|
|
||||||
|
|
||||||
If a function takes another function as its first argument you can conveniently
|
|
||||||
define it using a `do` block:
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> sum([1, 2, 3]) do x
|
|
||||||
println("processing ", x)
|
|
||||||
return x ^ 2
|
|
||||||
end
|
|
||||||
processing 1
|
|
||||||
processing 2
|
|
||||||
processing 3
|
|
||||||
14
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# The `!` character in function names
|
|
||||||
|
|
||||||
Often you will see an exclamation mark (`!`) at the end of the function name,
|
|
||||||
e.g., `sort!`. There is a convention that developers are recommended to add `!`
|
|
||||||
at the end of the functions they create if such functions modify their arguments.
|
|
||||||
|
|
||||||
```
|
|
||||||
julia> x = [5, 1, 3, 2];
|
|
||||||
|
|
||||||
julia> sort(x); # returns a new vector; x is not changed
|
|
||||||
|
|
||||||
julia> sort!(x); # changes x in-place
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Variable scoping rules in Julia (simplified)
|
|
||||||
|
|
||||||
The following constructs we have learned till now create a new scope (*local scope*):
|
|
||||||
* functions, anonymous functions, `do`-`end` blocks;
|
|
||||||
* `for` and `while` loops.
|
|
||||||
|
|
||||||
Notably the `if` blocks and the `begin`-`end` blocks do not introduce a new
|
|
||||||
scope. This means that variables defined in such blocks leak out to the
|
|
||||||
enclosing scope.
|
|
Loading…
Reference in New Issue
Block a user