(Edited 12Sep2021 for terminology)
Sometimes a code writer might want to know more things about a key than what can be learned from the blocks built into Snap! A custom block that tests the Four Truths about a key could be useful.
Snap! has great blocks for checking a couple of things about keyboard key at one moment in time. The hat,
fires at the moment when the key goes down. The predicate block,
tells you whether the key is down at the moment you check it. Very useful, as far as they go.
Some people on the Forum have wished for a block that would detect only the first press of a key. In other words, they want to run some code only once when a key goes down, but not while the key remains held down. They want to avoid a runaway keypress situation like the following:
Oops! I left my finger down on that key too long!
The trick is to test how the key changes from one test of the key to the next test. It wants a test that remembers whether the key was down or up the last time it was tested. Comparing the two test results reveals the Four Truths about a keypress. The key was:
- UP last time; it changed; now it is DOWN. The key went down.
- DOWN last time; it is DOWN now, also. The key remains down.
- DOWN last time; it changed; now it is UP. The key went up.
- UP last time; it is UP now, also. The key remains up.
Code that keeps track of prior test results can be designed to distinguish between Truth #1 and Truth #2. Such code can help to avoid a runaway keypress.
Begin edit of 12Sept2021
How nice it would be to wrap the code neatly inside a single, custom block. That can be done by writing a regular procedure (that is, a custom block) for the specific key to be tested. A "block variable" in the procedure can remember the result of a prior test.
To test several, different keys, you could duplicate the block definition then edit it to change which key is to be tested. The downsides of that approach include increased workload for the code writer and the possibility of errors in the duplicating or editing.
It would be even nicer to have one custom block that made it easy to create blocks that test the Four Truths for different keys of the coder's choice. This sounds like a job for a "higher order procedure". Quoting the Snap! Manual,
A higher order procedure is one that takes another procedure as an input, or that reports a procedure.
In this situation, we want a higher order procedure that not only remembers a test result from one call to the next but also does both of the things that make higher order procedures so special. We want it to:
- take the key [ ] pressed? block as an input, selecting the letter to be tested
- report a (second, different) procedure that
- executes the test,
- compares the result to the previous test,
- determines which of the Four Truths is true (setting the others to false),
- and saves the test result for next time.
That second procedure is the one that actually evaluates the Four Truths. However, it emerges with no name. It is "anonymous". To call it in an intuitive way, we may give it a name. This is done by creating a variable then setting its "value" to be the procedure reported by the higher order procedure.
End edit of 12Sep2021
Here's code using such a block. It operates a "forever loop" but increments the value of x only once each time the "A" key is pressed down.
You can hold the "A" key down as long as you like; the value will not increase. Release the "A" key then press it again. The value of x increases by one. It increments only when the key was up then went down.
Begin edit of 12Sept2021
The blue "sensor" block in there, named "perform key test <key [a] pressed?>" is a "lambda". It specifies which key to test. As a result, the second function that that will be reported out tests only the "A" key.
End edit of 12Sept2021
Test the "A" key by putting the variable into a "call" block. The call block has an input where you can type a message to the function stored inside it. The message can tell the function which one of the four Truths to test:
- went down
- remains down
- went up
- remains up
There is also a message for debugging purposes:
- list all
It would be useful in a "say" block:
The code for this block and the demo shown here is available in a shared project at the following URL: https://snap.berkeley.edu/snap/snap.html#present:Username=codegeezer&ProjectName=keyChangeBlock.