I brought out a deck of Realtalk playing cards that I had printed on cardstock (all four suits, numbered 2 through 7), and we played some games:
- Detect when a four-of-a-kind is on the table.
- Draw an arrow from red cards to black cards of the same number.
- Draw an arrow from each card to the next card of the same suit.
- Detect a straight (a sequence of ascending cards) and label the head of the straight (e.g "Straight of 5 clubs").
Konlin diverged for a bit and started trying to make a blackjack game.
All matches
I had originally conceived the playing cards in order to introduce "all matches", and we did that now:
- How many cards are on the table? How many of each suit?
- What is the sum of the numbers on the cards?
- etc
I introduced both "With all /matches/" and "When /all xs/", but should have just stuck with the former.
Cards + logic gates
I tried to tie the cards back to the logic gates from last time, to make the point about how Realtalk activities can blend together. I brought out the Clocks they had made, and had them write a rule that would turn every card into a clock, with a duty cycle based on the card number (e.g. a "3" should be active 30% of the time).
Shawn and Konlin did it differently (Shawn's was active 0.3 sec out of 1 sec, and Konlin's was active 1 sec out of 3.3 sec), so I wished for a clock period and they had to respect my wish, along with defaulting to 1 sec when there was no wish.
Final boss
The last challenge of the day was "Ask for straights". When we put a "2" card on the table, there should be a box to its right asking for the "3". When we put down the "3" in that spot, it should ask for the "4", and so on.
When they completed this challenge, it was almost 5 pm and that seemed like a suitable place to stop.
-- first card of the straight
When /p/ is the (2) of /suit/:
Claim (p) wants the next card.
End
-- check if the next card is to the right
When /p/ wants the next card,
/p/ is the /n/ of /suit/,
/p/ points "right" at /p2/,
/p2/ is the /n2/ of /suit/,
n2 == n + 1:
Claim (p) got the next card.
Claim (p2) wants the next card.
End
-- if the next card is not to the right, ask for it
When /p/ wants the next card,
/nobody/ claims /p/ got the next card,
/p/ is the /n/ of /suit/,
/p/ has width /w/, /p/ has height /h/,
/box/ is a new box on the "right" of /p/ with width /w/ height /h/:
Wish (box) is outlined "green" with stroke width (0.02).
local label = string.format("%d of %s?", n+1, suit)
Wish (box) is labelled (label).
End
I really liked that we started from an empty space and built the world from scratch. Assembling the Dynalamp head was pretty easy and fun. The mic stand may have been a bit tedious but okay, and running cables and positioning lamps is mostly annoying. (The NUC trouble: keyboards initially weren't working because of a bad USB port. We swapped NUCs, and then keyboards appeared not to be working because F1 had no effect, but that was actually because Realtalk was stuck in calibration mode because F1 had been pressed on some other keyboard no longer attached. We eventually got things working after several NUC swaps and port swaps, but it slowed momentum and was embarrassing.)
My main impression after the first day was that I should have gone way slower. I was excited about my clever agenda that attempted to cover everything in a single day. But even with the visualizers, learning Realtalk is hard. I was introducing things like conditional clauses and default matches before they had a solid understanding of normal clauses and matches, or even what parentheses and slashes mean, and they were getting confused. On day two, I tried to go slowly over the fundamentals again. I think there could be a series of introductory games just about statements, matching, and syntax that goes really slowly and makes the basics extremely visible and tangible and fun.
Introducing memories on day one was a mistake. Memories are a great way of representing state within the Realtalk model of computation. But they're really confusing and distracting if you aren't yet fluent in thinking in that model, and especially if you don't yet understand Realtalky ways of physically arranging objects so as to represent most state physically. And especially if you haven't unlearned your imperative programming habits. I was carried away with wanting to make a latch to complete the logic circuits analogy. We should have just stayed with reactive Realtalk and physical state, and seen how far we can go with just that. Later, at some advanced workshop, I could introduce ticking and convergence, and then histories, and then memories.
Likewise for "When /all xs/". Should have just stuck with "With all /matches/", and then brought up /all xs/ much later as a handy shortcut, once aggregation itself was well understood.
Some topics, like memories, came up a bit earlier than intended because people wanted to make things and I was trying to help them along. Konlin in particular would diverge to make things (e.g. the blackjack game) which needed state, so I gave him the tools to make it. But memories are a power tool, and he really wasn't ready. But also, the power tools were only necessary because he was approaching the game in a non-Realtalky way, and the better lesson would have been to help him redesign the game so it was more in-the-world and didn't need virtual state in the first place. But probably the best response would have been "let's come back to this once we understand Realtalk better". I was trying to avoid being strict or discouraging, but in an introductory workshop, "we haven't learned how to approach this yet" may be better than obliging people in going out of their depth.
I found both of them writing code that mutated external variables, e.g.
sum = 0
When /card/ is the /n/ of /suit/:
End
The global declaration should almost certainly be illegal. But even if sum were a local, this code is meaningless and ideally wouldn't be allowed without an "I know what I'm doing" annotation. I think this comes from thinking of When as an imperative "for" loop. There is probably a way of presenting reactivity that avoids this thinking.
There were other assumptions they made about the computational model which surprised me. For example, Konlin was doing things like this, assuming that each page was its own process:
while (true) do
When /p/ is a "page": ... End
sleep(1)
Things like this probably aren't a big deal; they're just grasping for techniques that worked in conventional programming, and they just need to unlearn them.
There were a handful of divergences, which were dutifully caught by the divergence catcher. These were all loops of the form:
When /nobody/ claims xyz:
Claim xyz.
This would have been less disruptive if Shawn and Konlin were working in separate areas, although it wasn't a big deal and was just kind of a goofy moment when it happened.
I had hoped we would keep an ongoing gallery/journal via a whiteboard of photos and printouts, and it sort of worked, at least on day one, but it wasn't as good as it could have been. We should have ritualistically printed and photographed after every segment, and otherwise been more diligent about documenting. It's hard because you get caught up in the work and don't want to take time out.
I can imagine starting a workshop by giving each person a binder/organizer or personal posterboard, initializing it with cheat sheets etc, and then having everyone add to it as they make things.
Most of the time, each of us was continuously patching a single Blank. It would be more Realtalky to be continuously printing and spreading out many objects. We did what we did mostly because it was the lowest friction, and partly because of limited table space. But having the printer nearby was helpful.
I thought the playing cards were really good! They were distinct, tangible, and familiar objects that felt good to hold and arrange, and had natural relationships among themselves. They suggested a lot of Realtalky challenges. Of course, a Realtalk with recognizers would use actual real-life playing cards, not my dorky small squares.
"Ask for straights" was a good final boss. It was difficult but doable, required thinking in Realtalk and making claims to oneself, assessing a physical situation and having physical objects respond to each other, and it felt fun to place down cards and see the reaction.
Both Shawn and Konlin had positive things to say after day one. Konlin said that it may have been his favorite workshop he's ever been to.