simple-toys.skb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. (section
  2. :title [Opening the toy box]
  3. (p [Let's build ourself a little toy box for us to play around with.
  4. Enter the following at your Guile REPL:])
  5. (frame
  6. (prog :line #f
  7. "(define toy-box '(robot teddy-bear doll-with-comb toy-soldier))"))
  8. (p [If we forget what's inside our toy box, we can always look inside it.])
  9. (frame
  10. (prog :line #f
  11. "scheme@(guile-user)> toy-box
  12. ;; => (robot teddy-bear doll-with-comb toy-soldier)"))
  13. (p [Our friend ,(code "toy-box") here is a variable, and the information
  14. it references is called a "list", and lists are at the heart of
  15. Scheme (and indeed Lisp, which stands for "list processing", which
  16. Scheme is a variant of).
  17. We can verify that it is indeed a list:])
  18. (frame
  19. (prog :line #f
  20. "scheme@(guile-user)> (list? toy-box)
  21. ;; => #t"))
  22. (p [And indeed it is!])
  23. (p [Of course, the fun of the toy box is not the box itself, but the toys.
  24. So, let's pull out the first toy from the box:])
  25. (frame
  26. (prog :line #f
  27. "scheme@(guile-user)> (car toy-box)
  28. ;; => robot"))
  29. (p [That looks like the toy closest to the top of our box indeed.
  30. But why is that command called ,(code "car")?
  31. We weren't trying to pull a toy car from the box!
  32. "car" is a term with some history in lisps (it stands for
  33. "Content Address Register") but that history is not important
  34. to us at the very moment.
  35. For now, every time you see ,(code "car"), you can think of it as meaning
  36. "first".])
  37. (p [Of course, there are more toys in the box than just that robot.
  38. What's under the robot in the box?])
  39. (frame
  40. (prog :line #f
  41. "scheme@(guile-user)> (cdr toy-box)
  42. ;; => (teddy-bear doll-with-comb toy-soldier)"))
  43. (p [Another strange command... ,(code "cdr")!
  44. ,(code "cdr") is prounounced "could-er" (and also is a historical name,
  45. standing for "Content Decrement Register", which is again not
  46. important at the moment).
  47. For now, every time you see ,(code "cdr"), you can think of it as
  48. meaning "rest", giving you the rest of the list.])
  49. (p [We can see that at the top of the list returned with "cdr"
  50. is a nice looking teddy-bear.
  51. Can we pull that off the top?
  52. Indeed, we can by nesting the commands!])
  53. (frame
  54. (prog :line #f
  55. "scheme@(guile-user)> (car (cdr toy-box))
  56. ;; => teddy-bear"))
  57. (p [Horray!
  58. What a nice looking teddy-bear.])
  59. (p [One thing we can notice from the above is that we nested the call to
  60. cdr inside the call to car.
  61. We can understand how this works by doing the substitution
  62. manually:])
  63. (frame
  64. (source :language scheme
  65. (prog :line #f
  66. (string-join
  67. '("(car (cdr toy-box))"
  68. ";; Substitute in toy-box"
  69. "(car (cdr '(robot teddy-bear doll-with-comb toy-soldier)))"
  70. ";; Pull out the rest of the list via cdr"
  71. "(car '(teddy-bear doll-with-comb toy-soldier))"
  72. ";; Pull the first item off the top with car"
  73. "'teddy-bear")
  74. "\n"))))
  75. (p [This is how a lot of Guile/Scheme/Lisp looks:
  76. expressions nested inside other expressions.
  77. The parentheses help you understand the beginning and end of an
  78. expression.
  79. For much of the programming you will do with Guile, you can figure
  80. out what's going on by doing the substitutions in your head like
  81. above.
  82. (Not everything works via substitution, but discussing that is
  83. beyond the scope of this tutorial!)])
  84. (p [(There are other, easier to read ways to pull out items from a list
  85. (or toys from a toybox).
  86. We will get to them later.)])
  87. (p [What if we want to add a toy to our toybox?
  88. Luckily we have a little friend named ,(code "cons"), which is used
  89. to construct (or add to) lists.
  90. Let's cons a new toy to our toybox now!])
  91. (frame
  92. (prog :line #f
  93. "scheme@(guile-user)> (cons 'bouncy-ball toy-box)
  94. ;; => (bouncy-ball robot teddy-bear doll-with-comb toy-soldier)"))
  95. (p [It's so nice to see that bouncy-ball with its toy friends!
  96. But wait, this is surprising:])
  97. (frame
  98. (prog :line #f
  99. "scheme@(guile-user)> toy-box
  100. ;; => (robot teddy-bear doll-with-comb toy-soldier)"))
  101. (p [Huh?
  102. When we ran cons, we got back a new list of toys that included
  103. our bouncy-ball, but when we look back inside of toy-box, we
  104. see it isn't there!
  105. This is on purpose (and is actually a feature): when we used cons,
  106. we got back a new list with our old list attached at the end.
  107. It didn't change our old list to do this... changing our old list
  108. mean that we "mutated" it.
  109. (code "toy-box") is a variable, and it still points at our original toy box
  110. list.])
  111. (p [Suppose we did want to actully change what toy-box means and have
  112. it point to something else.
  113. We could do this.
  114. Guile has a command named ,(code [set!]) which will let you
  115. change the value of a variable we already defined.
  116. Let's try it:])
  117. (frame
  118. (prog :line #f
  119. "scheme@(guile-user)> (set! toy-box (cons 'bouncy-ball toy-box))
  120. scheme@(guile-user)> toy-box
  121. ;; => (robot teddy-bear doll-with-comb toy-soldier)"))
  122. ;; TODO: Move this part to part two of the intro to procedures bit?
  123. (p [This seems rather convenient!
  124. And sometimes, it is.
  125. Unfortunately, assignment and mutation can sometimes cause unexpected
  126. and unpleasant surprises for us.
  127. Imagine we were running a program with many friends running around our
  128. playground at once.
  129. Our friend Jessica may hear that there's a robot in the box from her
  130. friend Aaron, and so she may go to retrieve it, but in-between that
  131. maybe we took the toy out of the box to play with, and Jessica will
  132. become very confused when she opens the box and doesn't see the
  133. robot.
  134. (Maybe she will even think that Aaron lied to her, though of course, we
  135. really didn't mean to cause that kind of mistake, we just wanted
  136. our robot!)
  137. Computer programs run into these same kinds of issues and often times
  138. have less ideas on what to do when things unexpectedly change around
  139. them than even we might, and this can lead to all sorts of problems.
  140. We won't go into details, but procedures that might cause tricky behavior
  141. like this are said to have "side effects", and in Guile (and Scheme
  142. generally) the convention is to label these with an exclaimation mark.
  143. So when you see the explaination mark at the end of ,(code "set!")
  144. remember that someone is shouting, "this has a side effect, be careful!"])
  145. (p [The good news though is that Guile provides both datastructures that do
  146. and don't require visible side effects.
  147. When it comes to lists, you can mutate them, but unless you really need
  148. to, you probably don't want to or have to!])
  149. (p [We'll come back to lists a bit more towards the end of the chapter.
  150. For now, there are some other fun types of data to play with.]))
  151. (section
  152. :title [Simple types of toys]
  153. (p [So far we've worked with two types of data: lists and symbols.
  154. Of course, there are a lot of other types of data out there!
  155. But since we've seen symbols, let's start with them.
  156. (We'll get more into lists (and other ways to group information
  157. together)later.)])
  158. (p [All the toys that were in our box were symbols.
  159. We can create a symbol very easily:])
  160. (frame
  161. (prog :line #f
  162. "scheme@(guile-user)> 'race-car
  163. ;; => race-car"))
  164. (p [Symbols are used to stand in for ideas.
  165. Sometimes lisp programmers use them as "keys" to look up information,
  166. and lisp programs are technically themselves made mostly out of
  167. lists and symbols!
  168. You can test if two symbols are the same with ,(code "eq?"):])
  169. (frame
  170. (prog :line #f
  171. "scheme@(guile-user)> (eq? 'apple 'apple)
  172. ;; => #t
  173. scheme@(guile-user)> (eq? 'apple 'orange)
  174. ;; => #f"))
  175. (p [Hey wait, what are those ,(code "#t") and ,(code "#f") things?
  176. Good question!
  177. These are called "booleans".
  178. In Guile, ,(code "#t") stands for "true" and ,(code "#f") stands
  179. for "false".
  180. Though you should know: in Guile everything that isn't ,(code "#f")
  181. is considered to be true!])
  182. (p [It would be nice if we could work with numbers.
  183. For example, we might like to be able to count how many toys are
  184. in our toy box.])
  185. (frame
  186. (prog :line #f
  187. "scheme@(guile-user)> (length toy-box)
  188. ;; => 4"))
  189. (p [The number we got back is an integer, in other words a whole number
  190. (which can be positive or negative).
  191. It's fun to play with integers!])
  192. ;; @@: Mixing comments and the ";; => foo" style is clearly not nice,
  193. ;; as evidenced here...
  194. (frame
  195. (prog :line #f
  196. ";; Since Guile uses lisp-style \"prefix notation\", we write
  197. ;; \"8 + 2\" like (+ 8 2)
  198. scheme@(guile-user)> (+ 8 2)
  199. ;; => 10
  200. ;; Multiplication looks similar:
  201. scheme@(guile-user)> (* 6 10)
  202. ;; => 60
  203. ;; We can include multiple arguments to add or multiply many things at once:
  204. scheme@(guile-user)> (+ 1 2 3)
  205. ;; => 6
  206. ;; And of course we can combine together math expressions
  207. scheme@(guile-user)> (* (+ 1 2 3) 10)
  208. ;; => 60"))
  209. (p [Integers aren't the only kinds of numbers... Guile also has "rational"
  210. numbers (like fractions) and floating point numbers, or "inexact"
  211. numbers.
  212. Unlike in some other languages, Guile tries to keep numbers exact until
  213. you need to convert them to an inexact form.
  214. This makes Guile very nice for all sorts of number games!])
  215. (frame
  216. (prog :line #f
  217. ";; Floating point (inexact) numbers
  218. scheme@(guile-user)> .4
  219. ;; => 0.4
  220. ;; We can enter rational numbers by hand
  221. scheme@(guile-user)> 2/3
  222. ;; => 2/3
  223. ;; If we divide, we get back rational numbers
  224. scheme@(guile-user)> (/ 2 3)
  225. ;; => 2/3
  226. ;; ... unless we choose to convert them to inexact form!
  227. scheme@(guile-user)> (exact->inexact (/ 2 3))
  228. ;; => 0.6666666666666666"))
  229. (p [There are more number types available in Guile, but we'll let
  230. you read the manual to find out more about them.])
  231. (p [It would be nice to be able to describe our toys to someone.
  232. What can we use?
  233. It would be awkward to use symbols to say a whole sentence.
  234. We would like to be able to say something using a data type
  235. more befitting our words.
  236. Of course, words and sentences are made of letters, and in
  237. Guile, we call those "characters".
  238. Here is a list of characters:])
  239. (frame
  240. (prog :line #f
  241. "scheme@(guile-user)> '(#\\a #\\b #\\c #\\d #\\e #\\f #\\g)
  242. ;; => (#\\a #\\b #\\c #\\d #\\e #\\f #\\g)"))
  243. (p [Well, talking to our friends letter by letter sounds very painful.
  244. Luckily, we have a nice type that deals with text called
  245. "strings", which "string together" a series of characters.
  246. And they are very easy to use!])
  247. (frame
  248. (prog :line #f
  249. "scheme@(guile-user)> \"abcdefg\"
  250. ;; => \"abcdefg\"
  251. scheme@(guile-user)> (string->list \"abcdefg\")
  252. ;; => (#\\a #\\b #\\c #\\d #\\e #\\f #\\g)
  253. scheme@(guile-user)> \"our teddy bear is very fuzzy\"
  254. ;; => \"our teddy bear is very fuzzy\"
  255. scheme@(guile-user)> (string-join '(\"hop\" \"skip\" \"jump\")
  256. \" and a \")
  257. ;; => \"hop and a skip and a jump\""))
  258. (p [Those are some interesting kinds of toys to play with.
  259. Now it's time to learn how to breathe some life into them.]))