1
0
Fork 0
mirror of https://gitlab.rlp.net/mobitar/julia_course.git synced 2024-11-16 13:28:10 +00:00

Done structs

This commit is contained in:
Mo8it 2022-04-01 03:38:43 +02:00
parent 485aa0079c
commit d11adbf45d

View file

@ -20,56 +20,145 @@ Julia as a functional language does not have classes like in object oriented lan
Using structs, you can define your own types. Structs use type composition. This means that you combine types into a new one.
In Julia, type annotations DO NOT lead to any performance boosts. Structs build an exception! If you are writing a struct, you have to use type annotations with concrete types (not abstract)!
In Julia, type annotations DO NOT lead to any performance boosts. Structs build an **exception**! If you are writing a struct, you have to use type annotations with **concrete types** (not abstract)!
"""
# ╔═╡ 3e3e324d-5650-4f81-87cf-fb0f6f55d9d1
# You should not use a struct for a 2D vector. Use Julia's vectors! This is only for demonstration.
struct Vec2d
x::Float64
y::Float64
end
# ╔═╡ 2ab6f97f-8eed-4b86-9eb6-1de88e6c846d
vec_2d = Vec2d(1.0, 1.0)
# Define a variable with this type.
# The order of the arguments is important!
# The first argument sets the first field (here `x`).
# The second argument sets the second field and so on.
vec_2d = Vec2d(1.0, 2.0)
# ╔═╡ c9be354a-d5ef-4c94-ad2f-c2035dc9323f
# Access a field
vec_2d.x
# ╔═╡ 48d31ed6-c5b7-4510-9c49-de8a3a8a0fa7
vec_2d.y
# ╔═╡ 377a9100-efd8-479c-b9f6-68584c886800
# It is a new type
typeof(vec_2d)
# ╔═╡ 9940a716-1109-46f9-a88a-29a7a996412d
md"""
## Structs with abstract types
"""
# ╔═╡ 0e62a7b2-0636-4018-b005-0ae674fec45e
# Wow, we did reach infinity ♾️
# This is because of the limits of Float64
Vec2d(factorial(big(1000)), 2.0)
# ╔═╡ 70bb19db-3d97-4ae1-92d8-552574aa53c3
md"""
You might think this problem can be fixed by changing the type of the fields from `Float64` to something like `Real`. This will work, but it does harm performance!
**One more important performance tip: Don't use structs with abstract field types (or no types)!**
"""
# ╔═╡ 6046417c-460b-4b0c-8423-4d6c4c18731f
# Bad usage of abstract field types
struct BadVec2d
x::Real
y::Real
end
# ╔═╡ 3e21d34f-3758-427f-85c0-7c457f3f0904
# It does work, but it is bad for performance
bad_vec2d = BadVec2d(factorial(big(1000)), 2.0)
# ╔═╡ 4a07f5e3-2413-49c4-824c-b9c844695052
# The type does not say anything about what the fields type is.
typeof(bad_vec2d)
# ╔═╡ 9008b1c4-ad76-4d4f-b6c5-001a77543b97
# Better for performance:
# Use this syntax to let the type be derived from an abstract type
struct BetterVec2d{T<:Real}
x::T
y::T
end
# ╔═╡ 830dd737-4fdc-42c7-b105-d0622b055db1
# This works too and it is good for performance
big_vec2d = BetterVec2d(factorial(big(1000)), big(1))
# ╔═╡ f91b0c58-bc44-414a-b357-145d8c4339d2
# You see that a concrete type was choosen!
typeof(big_vec2d)
# ╔═╡ 169de33e-cff8-4419-be18-0f487c185ad7
# The concrete type of the fields is determined on construction
typeof(BetterVec2d(1.0, 2.0))
# ╔═╡ 3f1b8df9-104b-42c3-97ee-11782f9f744f
# This will not work. Both fields has to have the same type.
# BetterVec2d(1.0, 1)
# ╔═╡ a053b367-f7f2-440e-b9e0-4987b491c256
struct MixedVec2d{T1<:Real, T2<:Real}
x::T1
y::T2
end
# ╔═╡ 1eab61c9-74e1-4540-9750-6ec8448e4950
# This works
mixed_vec2d = MixedVec2d(1.0, 1)
# ╔═╡ 4a24f24b-d872-4cd8-bf76-49a0496e4ea6
# Two different concrete types for the fields
typeof(mixed_vec2d)
# ╔═╡ c9f68fcf-2b20-43b1-839a-59805357c6d3
md"""
## Mutation
By default, structs are not mutable!
If you want to be mutable, you have to use the keyword `mutable`.
"""
# ╔═╡ f8b27d41-448a-4329-986f-e65e0b3e77d6
# This will not work because the struct is immutable by default
# vec_2d.x = 42.0
# ╔═╡ da9e39a5-0ee3-4f6c-8cb1-abb3ebf3a01e
# Defining a mutable struct
mutable struct MutVec2d
x::Float64
y::Float64
end
# ╔═╡ d16ac12a-c772-4fee-a309-5b4a2708d08e
begin
mut_vec = MutVec2d(1.0, 2.0)
# Mutating a field
mut_vec.x = 42.0
mut_vec
end
# ╔═╡ d635a63b-44d9-4bfc-a873-ef537cdbdb09
md"""
## Structs from abstract types
To use the features of mutliple dispatch, define an abstract type and derive structs from it.
"""
# ╔═╡ 10c380fd-80e6-4cb7-b50e-1a7998ec00c5
# Defining an abstract type
abstract type Student end
# ╔═╡ 58de483d-c2b5-4252-b6da-64bd8bfac1ac
# Defining a struct derived from the abstract type `Student`
struct MathStudent<:Student
name::String
hobby::String
@ -79,10 +168,11 @@ end
struct PhysicsStudent<:Student
name::String
hobby::String
favorite_particle::String
favorite_particle::String # Some additional field
end
# ╔═╡ b535fd1d-695d-49fb-8a6a-2f2f0053a6f6
# Define a function that works on all students
function print_name(student::Student)
println(student.name)
@ -90,17 +180,19 @@ function print_name(student::Student)
end
# ╔═╡ 63f32169-b98c-4212-bbd9-4c601266f209
# Define a method that works only with math students
function print_information(math_student::MathStudent)
println("Math student: $(math_student.name)")
println("hobby: $(math_student.hobby)")
println("Hobby: $(math_student.hobby)")
return
end
# ╔═╡ cb49717b-0584-430e-a30c-c4d02cf55eb2
# Define a method that works only with physics students
function print_information(physics_student::PhysicsStudent)
println("Physics student: $(physics_student.name)")
println("hobby: $(physics_student.hobby)")
println("Hobby: $(physics_student.hobby)")
println("Favorite particle: $(physics_student.favorite_particle)")
return
@ -124,10 +216,70 @@ print_information(math_student)
# ╔═╡ bc8ef92b-1c68-4c9d-948a-6196dcd2b378
print_information(physics_student)
# ╔═╡ d8a2ae5c-b42a-4673-9a95-24cfc69ea3e7
# ╔═╡ 06805ff8-f4bc-4779-baa9-2801a44407b6
md"""
# Writing documentation
## Constructors
You can either define new constructors for a struct or overwrite the default constructor.
"""
# ╔═╡ d1937187-15b0-46e7-9589-05d2349aa93a
# `begin` blocks are only needed in Pluto notebooks
begin
struct ComputerScienceStudent<:Student
name::String
hobby::String
end
# Defining an additional constructor to the default constructor
function ComputerScienceStudent(name)
return ComputerScienceStudent(name, "Programming")
end
end
# ╔═╡ 721e268d-b7c5-4ea8-b4d7-2bab6e2a6fb0
# Using the default constructor
ComputerScienceStudent("John", "Tennis")
# ╔═╡ 0f76bd6b-906f-49b3-8a36-9e02feb750b9
# Using the additional constructor
ComputerScienceStudent("Selina")
# ╔═╡ 513a4b3f-5b12-4d65-9321-0c883f12a1eb
mutable struct BiologyStudent<:Student
name::String
hobby::String
# Overwriting the default constructor
# You have to use the keyword `new`
function BiologyStudent(name)
return new(name, "Observing animals")
end
end
# ╔═╡ 3063d330-c411-431e-9e7a-eb3f5cd3ee7b
# This will not work because the default constructor is overritten!
# BiologyStudent("Kate", "Swimming")
# ╔═╡ 9e621eb5-a163-4a7a-abd5-85bdf9469692
# The new default constructor
BiologyStudent("Kate")
# ╔═╡ 44511b7e-a38a-450f-9a55-b6b6a4d3edd5
# This is the default constructor now
begin
biology_student = BiologyStudent("Kate")
# The struct has to be mutable
biology_student.hobby = "Swimming"
biology_student
end
# ╔═╡ eddfd543-091b-4a32-8124-a67687dcf457
md"""
Why would you want to overwrite the default constructor?
It is useful if you want to enforce checking fields before construction.
"""
# ╔═╡ c24c04e4-b131-11ec-2c1b-7de12fe0c324
@ -187,11 +339,6 @@ md"""
## `DifferentialEquations.jl`
"""
# ╔═╡ b621819d-6ce3-41e1-9e61-3ad0a2c9b016
md"""
## `Intervals.jl`
"""
# ╔═╡ 0174178f-3ed9-4890-8482-714cb51a635d
md"""
## `ProgressMeter.jl`
@ -202,6 +349,11 @@ md"""
## `NaturallyUnitful.jl`
"""
# ╔═╡ 097b1b98-8b98-4160-bf31-d982f21ab8d6
md"""
## `Symbolics.jl`
"""
# ╔═╡ 2430f309-be28-4bc2-9692-92489c31f7b2
md"""
# Resources
@ -424,18 +576,31 @@ uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
"""
# ╔═╡ Cell order:
# ╠═c7256818-f2ab-4f8a-be6f-1d2c97dca981
# ╟─c7256818-f2ab-4f8a-be6f-1d2c97dca981
# ╠═3e3e324d-5650-4f81-87cf-fb0f6f55d9d1
# ╠═2ab6f97f-8eed-4b86-9eb6-1de88e6c846d
# ╠═c9be354a-d5ef-4c94-ad2f-c2035dc9323f
# ╠═48d31ed6-c5b7-4510-9c49-de8a3a8a0fa7
# ╠═377a9100-efd8-479c-b9f6-68584c886800
# ╟─9940a716-1109-46f9-a88a-29a7a996412d
# ╠═0e62a7b2-0636-4018-b005-0ae674fec45e
# ╟─70bb19db-3d97-4ae1-92d8-552574aa53c3
# ╠═6046417c-460b-4b0c-8423-4d6c4c18731f
# ╠═3e21d34f-3758-427f-85c0-7c457f3f0904
# ╠═4a07f5e3-2413-49c4-824c-b9c844695052
# ╠═9008b1c4-ad76-4d4f-b6c5-001a77543b97
# ╠═830dd737-4fdc-42c7-b105-d0622b055db1
# ╠═f91b0c58-bc44-414a-b357-145d8c4339d2
# ╠═169de33e-cff8-4419-be18-0f487c185ad7
# ╠═3f1b8df9-104b-42c3-97ee-11782f9f744f
# ╠═a053b367-f7f2-440e-b9e0-4987b491c256
# ╠═1eab61c9-74e1-4540-9750-6ec8448e4950
# ╠═4a24f24b-d872-4cd8-bf76-49a0496e4ea6
# ╟─c9f68fcf-2b20-43b1-839a-59805357c6d3
# ╠═f8b27d41-448a-4329-986f-e65e0b3e77d6
# ╠═da9e39a5-0ee3-4f6c-8cb1-abb3ebf3a01e
# ╠═d16ac12a-c772-4fee-a309-5b4a2708d08e
# ╟─d635a63b-44d9-4bfc-a873-ef537cdbdb09
# ╠═10c380fd-80e6-4cb7-b50e-1a7998ec00c5
# ╠═58de483d-c2b5-4252-b6da-64bd8bfac1ac
# ╠═4024358d-f673-45f1-a12a-00a5554622e3
@ -448,7 +613,15 @@ uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
# ╠═bc43e76c-3a9b-4f3f-9f88-28f2f7f868d1
# ╠═0a2619e4-9eed-4eb3-a411-c616ee840062
# ╠═bc8ef92b-1c68-4c9d-948a-6196dcd2b378
# ╠═d8a2ae5c-b42a-4673-9a95-24cfc69ea3e7
# ╟─06805ff8-f4bc-4779-baa9-2801a44407b6
# ╠═d1937187-15b0-46e7-9589-05d2349aa93a
# ╠═721e268d-b7c5-4ea8-b4d7-2bab6e2a6fb0
# ╠═0f76bd6b-906f-49b3-8a36-9e02feb750b9
# ╠═513a4b3f-5b12-4d65-9321-0c883f12a1eb
# ╠═3063d330-c411-431e-9e7a-eb3f5cd3ee7b
# ╠═9e621eb5-a163-4a7a-abd5-85bdf9469692
# ╠═44511b7e-a38a-450f-9a55-b6b6a4d3edd5
# ╟─eddfd543-091b-4a32-8124-a67687dcf457
# ╟─c24c04e4-b131-11ec-2c1b-7de12fe0c324
# ╠═279d81e7-77d5-4855-bf45-a1a613265f65
# ╠═62e2481a-3fa1-4f2f-a7b6-7879c675701d
@ -460,9 +633,9 @@ uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
# ╠═eb836cdc-de12-430c-a6f3-1524ebd28865
# ╠═7e75da58-f110-41cb-ab19-79376370965f
# ╠═6b417e5d-01c2-4b06-9708-62c422a6b64b
# ╠═b621819d-6ce3-41e1-9e61-3ad0a2c9b016
# ╠═0174178f-3ed9-4890-8482-714cb51a635d
# ╠═d29338b3-3c25-4ae4-90d0-1176538c635e
# ╠═097b1b98-8b98-4160-bf31-d982f21ab8d6
# ╠═2430f309-be28-4bc2-9692-92489c31f7b2
# ╟─c7e76680-571e-427d-a564-8819df8b3750
# ╟─00000000-0000-0000-0000-000000000001