version: 1 name: Conditionals description: | Learn how to write conditional expressions. objectives: - goal: - | The 4x4 gray square contains 4 `very small rock`s --- so small they cannot be seen! Your goal is to collect all of them and bring them back to your base; you win when you have all 4. There is one rock in each row and column, but otherwise you can't be sure where they are. Your best bet is to sweep over the entire 4x4 square and pick up a `very small rock` any time you detect one. - | The `ishere` command, with type `text -> cmd bool`, can be used for detecting the presence of a specific item such as a `very small rock`. What we need is a way to take the `bool` output from `ishere` and use it to decide whether to `grab` a rock or not. (Trying to execute `grab` in a cell without anything to grab will throw an exception, causing the robot to crash.) - | As you might expect, `if` can be used to write conditional expressions. However, `if` is not special syntax; it is simply a built-in function of type - | if : bool -> {a} -> {a} -> a. - | It takes a boolean expression and then returns either the first or second subsequent argument, depending on whether the boolean expression is true or false, respectively. - | The type variable `a` can stand for any type; `{a}` indicates a *delayed* expression of type `a`. Normally, function arguments are evaluated strictly before the function is called. Delayed expressions, on the other hand, are not evaluated until needed. In this case, we want to make sure that only the correct branch is evaluated. To write a value of type, say, `{int}`, we just surround a value of type `int` in curly braces, like `{3}`. This is why arguments to `build` must also be in curly braces: the type of `build` is `{cmd a} -> cmd robot`. - | TIP: Note that `if` requires a `bool`, not a `cmd bool`! So you cannot directly say `if (ishere "very small rock") {...} {...}`. Instead you can write `b <- ishere "very small rock"; if b {...} {...}`. You might enjoy writing your own function of type `cmd bool -> {cmd a} -> {cmd a} -> cmd a` to encapsulate this pattern. - | TIP: the two branches of an `if` must have the same type. In particular, `if ... {grab} {}` is not allowed, because `{grab}` has type `{cmd text}` whereas `{}` has type `{cmd unit}`. In this case `{grab; return ()}` has the right type. condition: | try { n <- as base {count "very small rock"}; return (n == 4) } { return false} solution: | def tL = turn left end; def tB = turn back end; def x4 = \c. c;c;c;c end; def VSR = "very small rock" end; def ifC = \c.\t.\e. b <- c; if b t e end; def pick = move; ifC (ishere VSR) {grab; return ()} {} end; def pickrow = x4 pick; turn back; x4 move end; build { require "treads"; require "branch predictor"; require "grabber"; require "lambda"; require "scanner"; // #540 turn south; x4 (move; tL; pickrow; tL); tB; x4 move; x4 (give base VSR) } robots: - name: base heavy: true dir: [0,1] display: char: Ω attr: robot devices: - logger - 3D printer - dictionary inventory: - [8, compass] - [8, solar panel] - [8, logger] - [8, treads] - [8, grabber] - [8, scanner] - [8, lambda] - [8, branch predictor] - [8, 3D printer] - [0, very small rock] entities: - name: very small rock display: invisible: true description: - A small rock. It is so small, it is practically invisible. properties: [portable] world: default: [blank] palette: 'Ω': [grass, null, base] '.': [grass] '_': [stone] 'o': [stone, very small rock] '┌': [stone, upper left corner] '┐': [stone, upper right corner] '└': [stone, lower left corner] '┘': [stone, lower right corner] '─': [stone, horizontal wall] '│': [stone, vertical wall] upperleft: [-1, 1] map: | ┌─────┐ │Ω....│ │.o___│ │._o__│ │.___o│ │.__o_│ └─────┘