More lessons
This commit is contained in:
parent
39787ee739
commit
b41fde8f82
8
koans.tm
8
koans.tm
@ -14,6 +14,14 @@ LESSONS := [
|
|||||||
Lesson((./lessons/lesson-03-variables.tm), "Variables"),
|
Lesson((./lessons/lesson-03-variables.tm), "Variables"),
|
||||||
Lesson((./lessons/lesson-04-functions.tm), "Functions"),
|
Lesson((./lessons/lesson-04-functions.tm), "Functions"),
|
||||||
Lesson((./lessons/lesson-05-basic-types.tm), "Basic Types"),
|
Lesson((./lessons/lesson-05-basic-types.tm), "Basic Types"),
|
||||||
|
Lesson((./lessons/lesson-06-arrays.tm), "Arrays"),
|
||||||
|
Lesson((./lessons/lesson-07-optionals.tm), "Optionals"),
|
||||||
|
Lesson((./lessons/lesson-08-tables.tm), "Tables"),
|
||||||
|
Lesson((./lessons/lesson-09-text), "Text"),
|
||||||
|
Lesson((./lessons/lesson-10-structs.tm), "Structs"),
|
||||||
|
Lesson((./lessons/lesson-11-enums.tm), "Enums"),
|
||||||
|
Lesson((./lessons/lesson-12-allocating.tm), "Allocating Memory"),
|
||||||
|
Lesson((./lessons/lesson-13-paths.tm), "File Paths"),
|
||||||
]
|
]
|
||||||
|
|
||||||
enum TestResult(Success(output:Text), Error(err:Text), WrongOutput(actual:Text, expected:Text)):
|
enum TestResult(Success(output:Text), Error(err:Text), WrongOutput(actual:Text, expected:Text)):
|
||||||
|
@ -19,8 +19,4 @@ func main():
|
|||||||
|
|
||||||
# Edit this test so it passes:
|
# Edit this test so it passes:
|
||||||
>> 2 + 2
|
>> 2 + 2
|
||||||
= 9999
|
= ???
|
||||||
|
|
||||||
# For the rest of this tutorial, you won't
|
|
||||||
# be editing any of the tests, you'll be
|
|
||||||
# fixing code so it passes the tests.
|
|
||||||
|
@ -17,17 +17,17 @@ func main():
|
|||||||
d := yes
|
d := yes
|
||||||
|
|
||||||
>> a
|
>> a
|
||||||
= 99
|
= ???
|
||||||
>> b
|
>> b
|
||||||
= 2.718
|
= ???
|
||||||
>> c
|
>> c
|
||||||
= "Hello, world!"
|
= ???
|
||||||
>> d
|
>> d
|
||||||
= no
|
= ???
|
||||||
|
|
||||||
# Text values support interpolation using `$`:
|
# Text values support interpolation using `$`:
|
||||||
name := "Alice"
|
name := "Alice"
|
||||||
greeting := "Hello, $name!"
|
greeting := "Hello, $name!"
|
||||||
|
|
||||||
>> greeting
|
>> greeting
|
||||||
= "Hello, Bob!"
|
= ???
|
||||||
|
37
lesson-templates/lesson-06-arrays.tm
Normal file
37
lesson-templates/lesson-06-arrays.tm
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Arrays
|
||||||
|
|
||||||
|
func main():
|
||||||
|
|
||||||
|
# Arrays are ordered collections of values.
|
||||||
|
# You can define an array using `[...]`:
|
||||||
|
|
||||||
|
nums := [10, 20, 30]
|
||||||
|
|
||||||
|
# Arrays are 1-indexed.
|
||||||
|
>> nums[2]
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Arrays can be empty but must have a type:
|
||||||
|
empty := [:Int]
|
||||||
|
|
||||||
|
>> empty
|
||||||
|
= []
|
||||||
|
|
||||||
|
# You can loop over an array with `for value in array`:
|
||||||
|
sum := 0
|
||||||
|
for num in nums:
|
||||||
|
sum += num
|
||||||
|
|
||||||
|
>> sum
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Array comprehensions let you transform arrays concisely:
|
||||||
|
squares := [n + 1 for n in nums]
|
||||||
|
|
||||||
|
>> squares
|
||||||
|
= [???]
|
||||||
|
|
||||||
|
# You can also get the index with `for index, value in array`:
|
||||||
|
for i, num in nums:
|
||||||
|
>> squares[i] == num * num
|
||||||
|
= yes
|
55
lesson-templates/lesson-07-optionals.tm
Normal file
55
lesson-templates/lesson-07-optionals.tm
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Optional Types
|
||||||
|
|
||||||
|
func main():
|
||||||
|
|
||||||
|
# Any type `T` can be made optional with the syntax `T?`,
|
||||||
|
# meaning it can hold a value or be `none`.
|
||||||
|
|
||||||
|
x := 42?
|
||||||
|
>> x
|
||||||
|
= x
|
||||||
|
|
||||||
|
# You can assign a `none` value to `x` because it has type `Int?`
|
||||||
|
x = none
|
||||||
|
|
||||||
|
# To declare a `none` variable, specify its type:
|
||||||
|
y := none:Int
|
||||||
|
|
||||||
|
>> y
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Some functions return optional values:
|
||||||
|
>> Int.parse("123")
|
||||||
|
= ???
|
||||||
|
>> Int.parse("blah")
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# You can check if a value exists with `if`:
|
||||||
|
n := Int.parse("123")
|
||||||
|
if n:
|
||||||
|
# Inside this condition, `n` is known to be non-none
|
||||||
|
n = add(n, 1)
|
||||||
|
>> n
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Optionals are useful for handling missing data:
|
||||||
|
name := none:Text
|
||||||
|
greeting := if name:
|
||||||
|
"Hello, $name!"
|
||||||
|
else:
|
||||||
|
"Hello, stranger!"
|
||||||
|
|
||||||
|
>> greeting
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Optional values can be converted to non-optional using `or`
|
||||||
|
>> Int.parse("blah") or 0
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# They can also be converted using the `!` operator, which
|
||||||
|
# will give an error if a non-none value is encountered:
|
||||||
|
>> add(Int.parse("123")!, 1)
|
||||||
|
= ???
|
||||||
|
|
||||||
|
func add(x:Int, y:Int -> Int):
|
||||||
|
return x + y
|
42
lesson-templates/lesson-08-tables.tm
Normal file
42
lesson-templates/lesson-08-tables.tm
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Tables
|
||||||
|
|
||||||
|
func main():
|
||||||
|
|
||||||
|
# Tables store key-value pairs.
|
||||||
|
# You can define a table using `{key = value, ...}`.
|
||||||
|
|
||||||
|
scores := {"Alice"=100, "Bob"=200}
|
||||||
|
>> scores
|
||||||
|
= {"Alice"=100, "Bob"=200}
|
||||||
|
|
||||||
|
>> scores["Alice"]
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Accessing a missing key gives `none`
|
||||||
|
>> scores["Zoltan"]
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Tables can be empty but must have key and value types:
|
||||||
|
empty := {:Text,Int}
|
||||||
|
>> empty
|
||||||
|
= {}
|
||||||
|
|
||||||
|
# You can loop over tables:
|
||||||
|
total := 0
|
||||||
|
for name, score in scores:
|
||||||
|
total += score
|
||||||
|
|
||||||
|
>> total
|
||||||
|
= 9999
|
||||||
|
|
||||||
|
# Table keys and values can be accessed as an array:
|
||||||
|
>> scores.keys
|
||||||
|
= [???]
|
||||||
|
|
||||||
|
>> scores.values
|
||||||
|
= [???]
|
||||||
|
|
||||||
|
# Table comprehensions let you create tables concisely:
|
||||||
|
doubled := {k = v * 2 for k, v in scores}
|
||||||
|
>> doubled
|
||||||
|
= {???}
|
34
lesson-templates/lesson-09-text.tm
Normal file
34
lesson-templates/lesson-09-text.tm
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Text
|
||||||
|
|
||||||
|
func main():
|
||||||
|
|
||||||
|
# Text values are sequences of letters.
|
||||||
|
greeting := "Hello"
|
||||||
|
|
||||||
|
>> greeting.length
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Text supports interpolation with `$`:
|
||||||
|
name := "Alice"
|
||||||
|
message := "Hello, $name, your number is $(1 + 2)!"
|
||||||
|
|
||||||
|
>> message
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Multi-line text uses indented quotes:
|
||||||
|
multiline := "
|
||||||
|
line one
|
||||||
|
line two
|
||||||
|
line three
|
||||||
|
"
|
||||||
|
|
||||||
|
# Methods calls use `:`
|
||||||
|
>> multiline:lines()
|
||||||
|
= [???]
|
||||||
|
|
||||||
|
# Common text methods:
|
||||||
|
>> "hello":upper()
|
||||||
|
= ???
|
||||||
|
|
||||||
|
>> "hello":split()
|
||||||
|
= [???]
|
42
lesson-templates/lesson-10-structs.tm
Normal file
42
lesson-templates/lesson-10-structs.tm
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Structs and Methods
|
||||||
|
|
||||||
|
# The keyword `struct` is used to define structures
|
||||||
|
# that hold multiple members:
|
||||||
|
struct Point(x:Int, y:Int):
|
||||||
|
|
||||||
|
# Methods are any function defined inside of the
|
||||||
|
# indented area below a struct definition.
|
||||||
|
|
||||||
|
# There is no implicit `self` argument, only the
|
||||||
|
# arguments you explicitly define.
|
||||||
|
func absolute(p:Point -> Point):
|
||||||
|
return Point(p.x:abs(), p.y:abs())
|
||||||
|
|
||||||
|
# Constants can be declared inside of a struct's namespace:
|
||||||
|
ZERO := Point(0, 0)
|
||||||
|
|
||||||
|
# Arbitrary functions can also be defined here:
|
||||||
|
func squared_int(x:Int -> Int):
|
||||||
|
return x * x
|
||||||
|
|
||||||
|
func main():
|
||||||
|
|
||||||
|
# You can create a struct instance like this:
|
||||||
|
p := Point(x=3, y=4)
|
||||||
|
|
||||||
|
>> p
|
||||||
|
= Point(x=???, y=???)
|
||||||
|
|
||||||
|
>> Point.ZERO
|
||||||
|
= Point(x=???, y=???)
|
||||||
|
|
||||||
|
>> p.x
|
||||||
|
= ???
|
||||||
|
>> p.y
|
||||||
|
= ???
|
||||||
|
|
||||||
|
>> p.sum()
|
||||||
|
= ???
|
||||||
|
|
||||||
|
>> Point.squared_int(5)
|
||||||
|
= ???
|
37
lesson-templates/lesson-11-enums.tm
Normal file
37
lesson-templates/lesson-11-enums.tm
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Enums
|
||||||
|
|
||||||
|
# Enums define a type with multiple possible variants:
|
||||||
|
enum Shape(Circle(radius: Num), Rectangle(width: Num, height: Num), Point):
|
||||||
|
|
||||||
|
# Use `when` to pattern match an enum:
|
||||||
|
func area(shape: Shape -> Num):
|
||||||
|
when shape is Circle(radius):
|
||||||
|
return Num.PI * radius * radius
|
||||||
|
is Rectangle(width, height):
|
||||||
|
return width * height
|
||||||
|
is Point:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
func main():
|
||||||
|
|
||||||
|
# You can create instances of an enum:
|
||||||
|
s1 := Shape.Point
|
||||||
|
|
||||||
|
# Single member enums display without the field names:
|
||||||
|
s2 := Circle(radius=10)
|
||||||
|
>> s1
|
||||||
|
= Circle(10)
|
||||||
|
|
||||||
|
# Multi-member enums explicitly list their field names:
|
||||||
|
s3 := Shape.Rectangle(width=4, height=5)
|
||||||
|
>> s3
|
||||||
|
= Rectangle(width=4, height=5)
|
||||||
|
|
||||||
|
>> s1:area()
|
||||||
|
= ???
|
||||||
|
|
||||||
|
>> s2:area()
|
||||||
|
= ???
|
||||||
|
|
||||||
|
>> "My shape is $s3"
|
||||||
|
= ???
|
42
lesson-templates/lesson-12-allocating.tm
Normal file
42
lesson-templates/lesson-12-allocating.tm
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Heap Allocation with `@`
|
||||||
|
|
||||||
|
func main():
|
||||||
|
|
||||||
|
# By default, values in Tomo are immutable.
|
||||||
|
# To allow mutation, you need to allocate memory using `@`
|
||||||
|
|
||||||
|
nums := @[1, 2, 3]
|
||||||
|
nums[1] = 99
|
||||||
|
|
||||||
|
>> nums
|
||||||
|
= @[???, 2, 3]
|
||||||
|
|
||||||
|
nums:insert(40)
|
||||||
|
>> nums
|
||||||
|
= @[???, 2, 3, ???]
|
||||||
|
|
||||||
|
# Allocated memory is not equal to other allocated memory:
|
||||||
|
a := @[10, 20, 30]
|
||||||
|
b := @[10, 20, 30]
|
||||||
|
>> a == b
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# The `[]` operator can be used to access the value stored
|
||||||
|
# at a memory location:
|
||||||
|
>> a[] == b[]
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Tables also require `@` to allow modifications:
|
||||||
|
scores := @{"Alice"=100, "Bob"=200}
|
||||||
|
|
||||||
|
scores["Charlie"] = 300
|
||||||
|
|
||||||
|
>> scores["Charlie"]
|
||||||
|
= ???
|
||||||
|
|
||||||
|
# Without `@`, attempting to mutate will cause an error:
|
||||||
|
frozen := {"key"="value"}
|
||||||
|
frozen["key"] = "new value" # This should fail
|
||||||
|
|
||||||
|
>> frozen["key"]
|
||||||
|
= "new value"
|
47
lesson-templates/lesson-13-paths.tm
Normal file
47
lesson-templates/lesson-13-paths.tm
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Paths
|
||||||
|
|
||||||
|
func main():
|
||||||
|
|
||||||
|
# Tomo includes a built-in literal type for file paths
|
||||||
|
# A path is inside parentheses and begins with `/`, `~`, `.` or `..`
|
||||||
|
|
||||||
|
file := (/tmp/test-file.txt)
|
||||||
|
>> file
|
||||||
|
= /tmp/test-file.txt
|
||||||
|
|
||||||
|
file:write("first line")
|
||||||
|
>> file:read()
|
||||||
|
= "???"
|
||||||
|
|
||||||
|
file:append("
|
||||||
|
|
||||||
|
second line
|
||||||
|
")
|
||||||
|
|
||||||
|
>> file:exists()
|
||||||
|
= yes
|
||||||
|
|
||||||
|
>> file:lines()
|
||||||
|
= [???]
|
||||||
|
|
||||||
|
# You can iterate over a file by lines:
|
||||||
|
>> upper_lines := [line:upper() for line in file:by_line()]
|
||||||
|
= [???]
|
||||||
|
|
||||||
|
>> file:parent()
|
||||||
|
= /???
|
||||||
|
|
||||||
|
>> file:extension()
|
||||||
|
= "???"
|
||||||
|
|
||||||
|
>> file:parent():child("other-file.txt")
|
||||||
|
= /???
|
||||||
|
|
||||||
|
>> dir := (/tmp/test-*.txt):glob()
|
||||||
|
= [???]
|
||||||
|
|
||||||
|
file:remove()
|
||||||
|
|
||||||
|
>> file:exists()
|
||||||
|
= ???
|
||||||
|
|
Loading…
Reference in New Issue
Block a user