Commits: 2
Edits to day 3
index 5780836..8309bf5 100644
--- a/content/day-3.txt
+++ b/content/day-3.txt
@@ -5,7 +5,7 @@
= Connecting the Dots
=
=| Note
- So far we have been writing the code of our program without thinking too much about about what it means. Today we are going to learn about
+ So far we have been writing the code of our program without thinking too much about what it means. Today we are going to learn about
=
= | List
= - Values and names
@@ -48,7 +48,7 @@ Let's start with values. The simplest way to create a value is to literally type
=
=These expressions ({Code|2} and {Code|"Hello!"}) are called /literals/, because their values are literally what they look like. The value of {Code|2} is simply {Code|2}! When you enter them, the REPL evaluates and prints their value (which in this case is very easy) and type (the text after {Code|:}). We will get to types later.
=
-Some value literals are simple, like numbers and strings. On day 1 we discussed lists. You can also type them literally, like this:
+Some value literals are simple, like numbers and strings. Some are complex. Previously we have touched the subject of lists. You can also type them literally, like this:
=
=| Terminal
= > [ 1, 2, 5, 77, 2 ]
@@ -72,9 +72,9 @@ or contain only one element:
= ["Hello"] : List String
=
=| Note
- Notice that a list with one element is not the same as the element itself, just like the box with one egg is not the same as an egg alone.
+ Notice that a list with one element is not the same as the element itself, just like the box with one egg is not the same as an egg alone. Also an empty list is not nothing, just like an empty box of eggs is not nothing. It may be a major disappointment when you are about to make some pancakes, but it's still a thing.
=
-Now let's focus our attention to *names*. You can give any value a name.
+Now let's focus our attention to *names*. If you have a value, you can give it a name.
=
=| Terminal
= > kittens = 2
@@ -91,13 +91,13 @@ From now on you can refer to this value either literally or by it's name:
= > 2
= 2 : number
=
-The effect will be exactly the same - you will get a value back. So we see that there are at least two ways of getting values: by literally expressing them or refering to them by names given to them previously. In a composite value of a list, you can mix the two ways together:
+The effect will be exactly the same - you will get a value back. So we see that there are at least two ways of getting values: by literally expressing them or referring to them by names given to them previously. In a composite value of a list, you can mix the two ways together:
=
=| Terminal
= > [ 1, kittens, 3 ]
= [1,2,3] : List number
=
-A function is a special kind of a value. Let's create a named function like this:
+A *function* is a special kind of a value. Let's create a named function like this:
=
=| Terminal
= > fun something = something ++ " is fun!"
@@ -114,12 +114,14 @@ Above we applied the function (by calling it's name: {Code|fun}) to a literal va
=| Note
= Imagine a machine that paints eggs. You put an egg into the machine and on the other side you get a painted egg. The egg is a thing and the painted egg is also a thing. But so is the machine!
=
+ Alternatively you can think of functions as parametrized values. The value you get depends on what value you provide to it. Eggs can have different sizes . An egg painting machine would give you different painted eggs depending on what egg you put in it.
+
=Now we see that we can get a value in three ways: (1) by literally expressing it, (2) by calling it's name and (3) by applying a function to another value.
=
-Not every function can be applied to any value. You can add two numbers (like {Code|2} and {Code|5} in {Code|2 + 5}), but you can't a number to a string ({Code|2 + "Hello!"} - try it and see an error!). The system that governs what function can be applied to what value is called a *type system* and it plays important role in Elm programming.
+Not every function can be applied to any value. You can add two numbers (like {Code|2} and {Code|5} in {Code|2 + 5}), but you can't add a number to a string ({Code|2 + "Hello!"} - try it and see an error!). The system that governs what function can be applied to what value is called a *type system* and it plays important role in Elm programming.
=
=| Note
- Again, imagine a machine that paints eggs. If you try to put a carrot in that machine, the dumb machine would make a mess of your carrot and probably jam. But a smart machine would sound a low pitch buzz and simply refuse to take the carrot. That way a smart machine avoids making a mess and possibly damaging itself. The Elm's type system is what makes your functions smart. It stops you from putting a carrot into the egg painting machine!
+ Again, imagine a machine that paints eggs. If you try to put a carrot in that machine, the dumb machine would make a mess of your carrot and probably get jammed. But a smart machine would sound a low pitched buzz and simply refuse to take the carrot . That way a smart machine avoids making a mess and possibly damaging itself. The Elm's type system is what makes your functions smart. It prevents you from putting a carrot into the egg painting machine!
=
=Every value in Elm has a type. You can see the type in the REPL - after evaluating the expression it shows it's value and the type, like here:
=
@@ -141,7 +143,7 @@ Composite values like lists have composite types. For example here the type is {
= > [ "Hello", "Good bye" ]
= ["Hello","Good bye"] : List String
=
-This means that it's a list of strings. That means that all the elements of this list are of type {Code|String}. When talking about lists you have to tell that it's a list and what is the type of it's element. Only this can be considered a fully specified type. Compare:
+This means that it's a list of strings. All the elements of this list are of type {Code|String}. When talking about lists you have to tell that it's a list and what is the type of it's element. Only this can be considered a fully specified type. Compare:
=
=| Terminal
= > [ 1, 2, 3 ]
@@ -150,13 +152,13 @@ This means that it's a list of strings. That means that all the elements of this
=This is a list of numbers. It's easy to see - all the elements are numbers, just as previously they were strings. All the elements of a list must be of the same type. If you try mixing the types, Elm will refuse to build your program. Try:
=
=| Terminal
- > [ 1, 2, 3, "Hello" ]
+ > [ 1, 2, 3, "Carrot" ]
= -- TYPE MISMATCH ----------------------------------------------------------- elm
=
= The 4th element of this list does not match all the previous elements:
=
- 7| [ 1, 2, 3, "Hello" ]
- ^^^^^^^
+ 7| [ 1, 2, 3, "Carrot" ]
+ ^^^^^^^^
= The 4th element is a string of type:
=
= String
@@ -180,7 +182,7 @@ What's the type of an empty list? Let's see:
=A list of {Code|a}. Obviously {Code|a} is not a type. This means that the type of the elements cannot be determine yet. This is signaled by the lowercase term where the type should be: {Code|a} instead of the capitalized {Code|String}.
=
=| Note
- Notice that the {Code|number} (type of value {Code|15} for example} is also lowercase. That's because it's also not a concrete type! Elm has two concrete types for numbers: {Code|Int} that can represent an integer number (1, 2, 3, 0, -122 etc.) and {Code|Float} that can represent a number with a fraction, (like 1.2, -3.5, 44.2). Because fraction part can be 0 (e.g. 1.0, 2.0, 0.0, -122.0 - so called whole numbers), it's not possible to tell if {Code|2} is an {Code|Int} or a {Code|Float}. We will see some of the implications of this later.
+ Notice that the {Code|number} (type of value {Code|15} for example) is also lowercase. That's because it's also not a concrete type! Elm has two concrete types for numbers: {Code|Int} that can represent an integer number (1, 2, 3, 0, -122 etc.) and {Code|Float} that can represent a number with a fraction, (like 1.2, -3.5, 44.2). Because fraction part can be 0 (e.g. 1.0, 2.0, 0.0, -122.0 - so called whole numbers), it's not possible to tell if {Code|2} is an {Code|Int} or a {Code|Float}. We will see some of the implications of this later.
=
=Above I said that every value has a type and also that a function is a value on it's own. Let's try the following in REPL:
=
@@ -188,7 +190,7 @@ Above I said that every value has a type and also that a function is a value on
= > fun
= <function> : String -> String
=
-We have asked the REPL to evaluate the value referenced by name {Code|fun}. In response the value is display as {Code|<function>}. That's because there is no simple way to represent the value of a function as text. Let's focus our attention on the type (part after the colon {Code|:}). It is {Code|String -> String}. This means that the type is a function (we recognize it by the arrow symbol). What's before the arrow is a type of the value that goes into the function (called the /argument of the function/). The type of the argument is {Code|String}. That shouldn't be a surprise. Remember how we have used the function before to produce the value:
+We have asked the REPL to tell as the value referenced by name {Code|fun}. In response the REPL display the value as {Code|<function>}. That's because there is no simple way to represent the value of a function as text. Let's focus our attention on the type (part after the colon {Code|:}). It is {Code|String -> String}. This means that the type is a function (we recognize it by the arrow symbol). What's before the arrow is a type of the value that goes into the function (called the /argument of the function/). The type of the argument is {Code|String}. That shouldn't be a surprise. Remember how we have used the function before to produce the value:
=
=| Terminal
= > fun "Learning Elm"
@@ -198,7 +200,7 @@ The part expressed as {Code|"Learning Elm"} is a {Code|String} (we recognize it
=
=The part after the arrow symbol is the type that the function returns. It is also {Code|String}. That also should not surprise us, since {Code|"Learning Elm is fun!"} is also a {Code|String}.
=
-Not every function returns the same type as it takes. For example function {Code|String.fromInt} takes a value of type {Code|Int} and returns a value of type {Code|String}. It's type is therefor {Code|Int -> String}. We read it as: /type of String.fromInt is a function from Int to String/. Let's see it in action:
+Not every function returns the same type as it takes. For example the function {Code|String.fromInt} takes a value of type {Code|Int} and returns a value of type {Code|String}. It's type is therefor {Code|Int -> String}. We read it as: /type of String.fromInt is a function from Int to String/. Let's see it in action:
=
=| Terminal
= > String.fromInt 10
@@ -218,7 +220,7 @@ But what if we want to say that a certain number (say, {Code|232}) is fun? We ha
=
=We had to put the {Code|String.fromInt 232} expression in parentheses, so that Elm understands that value {Code|232} is to be passed to {Code|String.fromInt} function, instead of the {Code|String.fromInt} being passed to {Code|fun} (which would not work anyway, since {Code|fun} takes values of type {Code|String}, not {Code|Int -> String}).
=
-Alternatively we can use the pipe operator which looks like this: {Code|\|>}. It has the advantage that the code that the transformations that happen first are on the left side and ones that happen later on the right, so we can read our code left to right instead of inside out. Here is how it would look like:
+Alternatively we can use the pipe operator which looks like this: {Code|\|>}. It has the advantage that the transformations that happen first are on the left side and ones that happen later on the right. We can read our code left to right instead of inside out. Here is how it would look like:
=
=| Terminal
= > 232 |> String.fromInt |> fun
@@ -239,6 +241,70 @@ Now it's more apparent that the value {Code|232} is passed to the function {Code
=
= Stay tuned {Icon|name=radio}
=
+Let's look at our code and try to identify some literal values, names and functions:
+
+| Code
+ module Main exposing (main)
+
+ import Element
+ import Svg
+ import Svg.Attributes
+
+
+ main =
+ Svg.svg
+ [ Svg.Attributes.viewBox "-100 -100 200 200"
+ ]
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.transform "translate(80)"
+ , Svg.Attributes.fill "skyblue"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "orange"
+ , Svg.Attributes.transform "rotate(72) translate(80)"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "red"
+ , Svg.Attributes.transform "rotate(144) translate(80)"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "lime"
+ , Svg.Attributes.transform "rotate(216) translate(80)"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "maroon"
+ , Svg.Attributes.transform "rotate(288) translate(80)"
+ ]
+ []
+ ]
+ |> Element.html
+ |> Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+
+Then let's consider where we have a repetitive code that we could turn into a named function.
+
+
=Let's take a deeper look at how we give attributes to an SVG element.
=
=We've already seen a few example of SVG attributes. The radius of our dot ({Code|circle}) is an attribute.Draft the rest of the syntax section
index 8309bf5..67e6def 100644
--- a/content/day-3.txt
+++ b/content/day-3.txt
@@ -228,20 +228,28 @@ Alternatively we can use the pipe operator which looks like this: {Code|\|>}. It
=
=Now it's more apparent that the value {Code|232} is passed to the function {Code|String.fromInt}, and whatever comes on the other end is passed to the {Code|fun} function. We don't need parentheses in this case.
=
-| Note
- TODO: But where does the functions come from? Modules.
-
+But what are functions good for? They are very good for making similar values that depend on some parameters. If you have to repeat similar code many times to get similar, but slightly different results, try using a function.
=
+| Note
+ Just like machines for painting eggs are useful if you have a lot of eggs to paint. If you only need one or two painted eggs, then it's probably better to just get them painted. But if you have thousands, maybe it's worth to build a machine for it.
=
+We don't have to create all the functions that we need. There are thousands of them already defined and we can use them by importing modules. We already did that. First you import a module like this:
=
+| Terminal
+ > import String
=
+And then use any name that it exposes, like this
=
=| Note
= *We are still working on this content.*
+| Terminal
+ > String.fromInt 10
+ "10" : String
=
= Stay tuned {Icon|name=radio}
+If the name comes from an imported module, you need to prefix it with the name of the module, like we did above.
=
-Let's look at our code and try to identify some literal values, names and functions:
+Let's look at our code and try to recognize some literal values, lists, names and functions. Here is how it should look after day 2:
=
=| Code
= module Main exposing (main)
@@ -302,7 +310,24 @@ Let's look at our code and try to identify some literal values, names and functi
= , Element.height Element.fill
= ]
=
-Then let's consider where we have a repetitive code that we could turn into a named function.
+Take your time. Here are some hints to help you:
+
+| List
+ #. We import three modules. Their names are to the right of the {Code|import} keyword.
+
+ #. Literal values are numbers and quoted texts. In our code there are only string literals so try to find all texts in quotes ({Code|"like this"}). I<>count 26 of them.
+
+ #. Then there are 13 lists, 5 of them empty and 8 with elements. Some lists are nested in other lists!
+
+ #. Names are given to values wherever you see a {Code|=} sign. The name is on the left and the value is below and slightly to the right. In our code we are giving only one name and it's value is quite complex. In fact the whole program is about computing this value. Try to find it.
+
+ #. Functions are called wherever you see a name that have any expression to the right (or below and right) of it (like: {Code|fun "learning Elm together"}), or that stand to the left of the {Code|\|>} (pipe operator; like: {Code|"learning Elm together" \|> fun}). The expression to the right of the function (or left of pipe) is called /the argument/. Sometimes an argument is a complex expression. Some functions take more than one argument (e.g. {Code|Svg.svg} takes 2 and the second one is very complex), and sometimes one is on the right and the other comes through the pipe 🤕. There is a lot of functions called here (36 to be precise) and most are prefixed with a name of the module that exposed them to us.
+
+ #. Interestingly there are only two names exposed by a module that do not refer to a function. Try to find them!
+| Note
+ *We are still working on this content.*
+
+ Stay tuned {Icon|name=radio}
=
=
=Let's take a deeper look at how we give attributes to an SVG element.