Reactors and Posns
Reactors
my-reactor =
reactor:
init: init-posn,
to-draw: crime-scene,
on-tick: solve-case,
on-key: move-glass,
stop-when: found-it
end
- The
init-posn
is the posn that we want to start our magnifying glass at. Remember that we want ours to start out at a random position!
- The
to-draw
function (crime-scene
) should take in a posn
so that it knows where to draw the magnifying glass! It should also return (output) a posn
to pass along to on-tick
so that we know where we last left off.
- The
on-tick
function (solve-case
) is run at every “time tick”, which is how Pyret measures time (think of it as every split second). solve-case
takes in a posn
from crime-scene
so we know where the magnifying was last seen. Then, we can update that posn
to keep the magnifying glass continuously moving. This updated posn
is given back to to-draw
so that our update is reflected in the animation.
- The
on-key
function (move-glass
) is called every time a key is pressed. It takes the output posn
from to-draw
(so that it knows where we left off) and moves it according to the key press. E.g., if the left
arrow is pressed, on-key
should take the magnifying glass’ posn
and shift it to the left. It returns the updated posn
. Again, this updated posn
is given back to to-draw
so that our update is reflected in the animation.
- The
stop-when
function (found-it
) takes in a posn
and returns a boolean
. If that boolean
is true
, it tells our reactor that our animation is over and that it should stop! If it’s false
, it will continue updating posn
's with on-tick
and on-key
and continue updating the animation with to-draw
.
Posns and Datatypes
data Posn:
| posn(x :: Number, y :: Number)
end
What is a datatype? You’re already familiar with a few… int
and string
are examples of datatypes you’ve already used! But what if the kind of data that you’re working with in your program is not well-described by a type that Pyret has built-in for you? Let’s say that you’re building a house. Every function that helps to build the house (maybe build-foundation
, lay-bricks
, shingle-roof
) has to know the x- and y-locations where you’d like to build something. Instead of passing the x- and y-values as separate inputs to each of these functions, you can store both locations together in a new datatype (calling it Position, or Posn for short)! Much like the way a variable of type int
“knows” its value, a Posn also knows its value. BUT in this case, the value just happens to have two separate pieces of information, the x- and y-location. In this way, we see that we can simplify and module our code to use and store data effectively.
By defining a posn
datatype, you are telling the program, “This is something that will appear later in my program, and I want a way to build the same thing multiple times with different characteristics.” So, when you make a posn
in your program, you are building the same structure each time: a variable of type posn
! The difference between the posn
variables you make are the x, y
values entered as parameters (inputs).
A slightly more complicated example
Let’s say you want to build a new data type that represents an animal. What kind of information do you need to know about an animal? Maybe how much it weighs, if it has hair and what color it is?
Here is how we would declare an animal data type:
data Animal:
| animal(has-hair :: Boolean, weight :: Number, color :: String)
end
To create an Animal, we would write:
poodle = animal(true, 20, "black")
And to find out if this poodle
we just created has hair, we can write poodle.has-hair
and the result of this line of code will be the Boolean true
because our poodle, as we defined it, has hair!
Confused? Ask a TA! This is a challenging concept, and it may take a little while for this idea to sink in. Don’t worry if it doesn’t make sense yet, it will with time and practice!
Reactors and Posns
Reactors
init-posn
is the posn that we want to start our magnifying glass at. Remember that we want ours to start out at a random position!to-draw
function (crime-scene
) should take in aposn
so that it knows where to draw the magnifying glass! It should also return (output) aposn
to pass along toon-tick
so that we know where we last left off.on-tick
function (solve-case
) is run at every “time tick”, which is how Pyret measures time (think of it as every split second).solve-case
takes in aposn
fromcrime-scene
so we know where the magnifying was last seen. Then, we can update thatposn
to keep the magnifying glass continuously moving. This updatedposn
is given back toto-draw
so that our update is reflected in the animation.on-key
function (move-glass
) is called every time a key is pressed. It takes the outputposn
fromto-draw
(so that it knows where we left off) and moves it according to the key press. E.g., if theleft
arrow is pressed,on-key
should take the magnifying glass’posn
and shift it to the left. It returns the updatedposn
. Again, this updatedposn
is given back toto-draw
so that our update is reflected in the animation.stop-when
function (found-it
) takes in aposn
and returns aboolean
. If thatboolean
istrue
, it tells our reactor that our animation is over and that it should stop! If it’sfalse
, it will continue updatingposn
's withon-tick
andon-key
and continue updating the animation withto-draw
.Posns and Datatypes
What is a datatype? You’re already familiar with a few…
int
andstring
are examples of datatypes you’ve already used! But what if the kind of data that you’re working with in your program is not well-described by a type that Pyret has built-in for you? Let’s say that you’re building a house. Every function that helps to build the house (maybebuild-foundation
,lay-bricks
,shingle-roof
) has to know the x- and y-locations where you’d like to build something. Instead of passing the x- and y-values as separate inputs to each of these functions, you can store both locations together in a new datatype (calling it Position, or Posn for short)! Much like the way a variable of typeint
“knows” its value, a Posn also knows its value. BUT in this case, the value just happens to have two separate pieces of information, the x- and y-location. In this way, we see that we can simplify and module our code to use and store data effectively.By defining a
posn
datatype, you are telling the program, “This is something that will appear later in my program, and I want a way to build the same thing multiple times with different characteristics.” So, when you make aposn
in your program, you are building the same structure each time: a variable of typeposn
! The difference between theposn
variables you make are thex, y
values entered as parameters (inputs).A slightly more complicated example
Let’s say you want to build a new data type that represents an animal. What kind of information do you need to know about an animal? Maybe how much it weighs, if it has hair and what color it is?
Here is how we would declare an animal data type:
To create an Animal, we would write:
poodle = animal(true, 20, "black")
And to find out if this
poodle
we just created has hair, we can writepoodle.has-hair
and the result of this line of code will be the Booleantrue
because our poodle, as we defined it, has hair!Confused? Ask a TA! This is a challenging concept, and it may take a little while for this idea to sink in. Don’t worry if it doesn’t make sense yet, it will with time and practice!