How To Read This Book (Do Not Be Afraid)
Contents
How To Read This Book (Do Not Be Afraid)#
This book takes no prisoners: it will expose you to various arcane spells (otherwise known as computer programming code) that invoke untold magical powers (which is to say, get the computer to do stuff…).
In part, the content may look quite technical; and in places, it is quite technical; but DON’T PANIC: it is still intended to be read as a story, even if you skip over the bits where the arcane squiggles, runes and glyphs make your head go fuzzy, and your eyes go blurry, and you just want to run away, terrified.
If you skim through the book, you will notice several very striking stylistic elements.
In the first case, there is straightforward text, such as this.
There are also some bits of text broken out into stylised boxes, such as the text below:
Note
Content appearing in stylised boxes might represent “an aside”, or perhaps a note or a warning about the preceding, or following, content.
As well as “pure text”, the document includes programming code. DO NOT BE AFRAID…
If you are well versed in story traditions, you may find it makes sense to think of programming code as a set of wishes requested of a fairy godmother, or magical incantations uttered by a genie, demon or other computer spirit that will perform some sort of task on your behalf.
The following element is a code cell (code spell..). When the code cell is “run” (when the code spell is cast, or the code wish made in the cell is granted) the instructions represented by any code contained within in will be followed by the computer.
If the instructions create something useful, it can be provided as an offering back to us and displayed as an “output” of the code cell directly below that code cell.
We can also get the code to talk back to us, recalling the days before computers had screens and only had access to a line printer:
# Areas like this contain programming code
# Some lines start with a # and are known as "comments"
# They are not instructions to the computer...
# ...they are an aside to you the reader, you the listener,
# to help explain a plot point, or characteristic of the
# evil king that need to better understand his actions
# Then, there is the code
# The actual incantation that instructs the demon computer
# to do something...
# The programming language I will be using is one called Python
print("Once upon a time...")
# This magical statement, when invoked or "executed", DOES SOMETHING
# So read on....
# The above code has been executed,
# and the outcome will be displayed below...
# So what do you see there?
Once upon a time...
Did you see what just happened?
When you ask it, the computer will do what you told it. But be careful how you present your request, because if you don’t phrase your instructions in exactly the right way, any wrongness will be exactly what the computer will do…
In many stories, the words used to represent a spell may look like a made up nonsense that make no sense to you, the teller, let alone the audience. It can be the same with programming code. If the code in this book makes no sense to you, the reader of this text, don’t worry. You should still come away with a sense of the sorts of things we can ask a computer to do, as well the sorts of things it will do in response to our commands.
But just as a wish may have unforeseen consequences if you don’t phrase it exactly right, so too might code take you to places you hadn’t intended to go to if you are careless with it.
Even amidst the mumbo jumbo gobbledeygook of a made up spell, a listener may spot certain recognisable elements in a charm, such as the name of the person who will fall in love with a supplicant who has gone to ask the cunning woman who lives at the edge of the forest for help. It’s the same with code: amidst the cryptic commands, you will often be able to recognise certain words or elements in there, and from that make some sort of sense about what is being manipulated, and possibly how. The address of a web page, for example, which is to say, a “URL”. Or a search term that forms part of a query: “wazza wayza oono wayza ‘the golden palace’”.
So there will be code. And there will be incantations. Nothing is hidden. All the tools and databases and collections of books, all the ways of searching them, are constructed from the code contained within these pages.
Stories Not Theatre#
At this point you may be wondering why there is such a focus on code to work with story data sources. Why should I put you through all this pain rather than just making a website that makes that lets you search through various story collections using a simple web based search form. And why is there a reliance on making cryptic search queries rather than just letting you enter words in a search box.
That’s because user interfaces are hard to produce, hard to maintain, hard to get right, and often limiting in what they allow the user to do. They also need hosting somewhere (which costs money, and time to set up). And securing against attack (because people are forever trying to take over other peoples’ computers so they can use them to attack yet other people, or hijack them to mine for that cryptic treasure known as bitcoin.
As far as user interfaces go, the designer always has to make certain decisions about what they think the user is likely to want to do. Someone else then typically makes various decisions about how to support that behaviour, decisions that lead to a particular user interface and system architecture. And then someone else — the programmer, the developer — has to find a way to implement the outcome of those decisions in code. And someone else has to make it look pretty and easy to use on the screen.
By sticking with code, we are focusing on the bare bones of the story. This is not theatre. We don’t have the set designers making the user interface and the teams of people interpreting the story so that it can be told in a theatrical way. We’re just trying to get the basic story sorted out, in its rawest of forms.
Some Tricks to Help You Recognise Code Tropes and Archetypes#
When telling a folk tale or a fairy tale from a particular tradition, we rely on tropes and archetypes. In Germanic fairy tales, the evil witch who lives in the forest, the trolls and giants of Scandinavian tales, the dragon-serpents of Eastern and Eastern European fairy tales, and so on.
In a story, we invoke archetypes we can rely on to perform certain certain roles:
Once, there was a king…
Sometimes, we need to take the shortcut further:
Once, there was an evil king…
Sometimes, we situate the king:
Once, in a land far far away, there was an evil king…
All these techniques allow us to invoke, and draw on, a folk memory of certain expectations and beliefs about what a particular character is like, how it will behave, and what sorts of things we might imagine it to do, even if we are never explictly told about them.
Note
In a far off land, was a king, an evil king…
As storytellers, we use such constructions to invoke a character that we can use in the rest of the story. We can be reasonably confident that we don’t need to go into a lot of detail, nor a long and complicated back story, to make sure that the audience knows what sort of character the king is.
They just know. Through the work of other stories and storytellers, and other tales told many times before. And we can tap directly into that knowledge and just get on with the story.
It’s the same with code:
from IPython.display import YouTubeVideo
# You might already have an expectation about what `YouTubeVideo` might let us do,
# or what sort of character it is...?
Having invoked the character, we can get it do something:
Every so often, the vizier would pass the evil king a note that caused the king to behave in a particular way.
You can also make notes in code, and put them onto pieces of paper we can both pass around and refer to by name:
# Let's make a note of the URL of a particular video on YouTube
# and associate it with something we can refer to by name
video_url = "https://www.youtube.com/watch?v=KdnGPQaICjk"
The video_url
is a label by which we can refer to the web address of a particular YouTube video.
The YouTubeVideo
thing we previously “imported”, which is to say, brought into the story, takes the unique identifier (or “ID code”) of a Youtube video. In the above case, that would be the value KdnGPQaICjk
. The YouTubeVideo
command then returns a video player that will play that particular video and returns it as a thing than can be embedded as an “output” of the code cell.
To get the ID code, we want the part of the web address that relates to the ID code, which is to sat, the part after the =
sign. To get it, we can “split” the URL on the =
character into two pieces: the first piece is the text before the =
, and the second piece, which is also the last piece, is the text after the =
.
# We can extract the ID of the video by splitting
# the URL on the "=" and taking the last (-1) piece
video_id = video_url.split("=")[-1]
display(f"Video ID is: {video_id}")
# Now pass the message to the king for him to read
YouTubeVideo(video_id)
'Video ID is: KdnGPQaICjk'
Defining Our Own Shortcuts, Spells and Incantations#
Sometimes, we need to package up a bit of the story so that we can reuse it. Or we need to teach the audience something they can do for us.
When the man gets on the horse with the fairy queen, you say:
And they rode,
and they rode,
and they merrily, merrily rode,
and they rode for a night and a day.
It’s the same with code:
rhyme = """
And they rode,
and they rode,
and they merrily, merrily rode,
and they rode for a night and a day.
"""
def man_gets_on_horse(action):
"""Do this when the man gets on the horse."""
print(action)
For example:
man_gets_on_horse(rhyme)
And they rode,
and they rode,
and they merrily, merrily rode,
and they rode for a night and a day.
Again, and Again, and Again, and Again…#
Sometimes, we want to do the same thing several times.
You may recall the three heads on the well who each made the same request?
So does the following piece of code:
three_heads_refrain = """
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by."""
for head in ["first_head", "second_head", "third_head"]:
print(f"And the {head} said:\n{three_heads_refrain}\n\n")
And the first_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
And the second_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
And the third_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
We can make it easier to repeat the refrain by putting that code into another reusable function:
# A function is like a multi-step spell we've made up
# and given a name so that we can invoke it more easily.
# The spell can use various different ingredients that
# are passed to it when its name is invoked
def say_refrain(refrain):
"""Repeat the refrain."""
# The named spell contains one or more instructions
# that are carried out whenever the function's name is invoked.
for head in ["first_head", "second_head", "third_head"]:
print(f"And the {head} said:\n{refrain}\n\n")
The """triple quoted text"""
at the start of the spell is actually a “note-to-self” that can remind us what the spell does:
help(say_refrain)
Help on function say_refrain in module __main__:
say_refrain(refrain)
Repeat the refrain.
To invoke the spell at another time, all we have to do is say the following in a code cell:
say_refrain(three_heads_refrain)
Call and Response#
If you’ve even been to a storytelling club or story festival, you’re probably familiar with the idea of “cric-crac”, a call and response technique used by the storyteller - who calls out “cric” - to keep an audience - who respond with “crac” - engaged, particularly during a long story, or between tales.
In code, we can use a simple spell component that gives us a basis for simple, and direct, call-response behaviours:
# The curly brackets, {}, defines a "dictionary"
# which contains one or more "key:value" pairs.
# Provide the key, and it returns the value
cric_crac = {"cric": "crac"}
cric_crac["cric"]
'crac'
If You Bring Me the Head of a Dragon, You May Marry the Princess…#
Let’s go back to the three heads.
You might recall that each of the heads gave a different gift to the good natured heroine.
That is, the gift given by each head was conditional on which head gave the gift.
We can create an incantation that will also perform different actions based on what we are currently doing or talking about.
Here’s the set-up…
heads_question = 'What shall we give her for treating us so kindly?'
heads_response = {"first_head": "She shall be beautiful",
"second_head": "She shall have a sweet voice",
"third_head": "She shall become queen."}
What do you think might happen next?
print(heads_question,"\n")
for head in ["first_head", "second_head", "third_head"]:
print(f"- {heads_response[head]}")
What shall we give her for treating us so kindly?
- She shall be beautiful
- She shall have a sweet voice
- She shall become queen.
In the same story, the three heads also had a different set of decisions available for the spiteful maid.
heads_other_response = {"first_head": "She shall be struck with leprosy",
"second_head": "She shall have a harsh voice",
"third_head": "She shall become a poor peasant."}
So what happens if we have several characters?
# The [] structure lets us create a list of items
maids = ["good maid", "blackbird", "spiteful maid",]
# Was "maids" a sensible name for that list?
# Maybe "characters" would have been better...
How might the three heads behave differently towards them?
Let’s pick one:
# We can select the n'th item from a list
# although you should note the the first item is the [0]'th,
# the second item is at index value [1], etc
maid = maids[2]
# Which one did we pick?
maid
'spiteful maid'
We can construct an incantation that behaves differently depending upon some tested condition:
# We need to select the appropriate set of responses
# depending on which maid appears
if maid == "good maid":
response = heads_response
elif maid == "spiteful maid":
response = heads_other_response
# So what's the outcome here?
print(f"For the {maid}, use the following response:\n",
response)
For the spiteful maid, use the following response:
{'first_head': 'She shall be struck with leprosy', 'second_head': 'She shall have a harsh voice', 'third_head': 'She shall become a poor peasant.'}
A Long Story is Often Made From Simpler Parts#
Many longer stories are actually quite formulaic in their structure. They are often split into “chapters” or distinct phases, and each separate phase or part might have its own, often repeating, structure.
And as with story, so with code.
So let’s put several of those pieces we’ve sketched and tried out previously in slightly more elaborate code story incantation:
# Make an ordered list of the heads
# that we can call on later
heads = ["first_head", "second_head", "third_head"]
# Now let's see what happens for each of the
# characters in our tale...
for maid in maids:
print(f"(The {maid} appears...)\n")
say_refrain(three_heads_refrain)
if maid == "good maid":
response = heads_response
elif maid == "spiteful maid":
response = heads_other_response
else:
print("Nothing happened...\n")
# do nothing more this time round
# go back to the top if there
# are more characters to consider
continue
print("Something happened...\n")
say_refrain(f'-"what a {maid}..."')
for head in heads:
print(f"And the {head} said: {response[head]}")
# The \n character is an end-of-line character
# but you had perhaps already started to suspect
# that's what it might be for yourself..?
print("\n")
(The good maid appears...)
And the first_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
And the second_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
And the third_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
Something happened...
And the first_head said:
-"what a good maid..."
And the second_head said:
-"what a good maid..."
And the third_head said:
-"what a good maid..."
And the first_head said: She shall be beautiful
And the second_head said: She shall have a sweet voice
And the third_head said: She shall become queen.
(The blackbird appears...)
And the first_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
And the second_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
And the third_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
Nothing happened...
(The spiteful maid appears...)
And the first_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
And the second_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
And the third_head said:
Wash me and comb me,
And lay me down softly.
And lay me on a bank to dry,
That I may look pretty,
When somebody passes by.
Something happened...
And the first_head said:
-"what a spiteful maid..."
And the second_head said:
-"what a spiteful maid..."
And the third_head said:
-"what a spiteful maid..."
And the first_head said: She shall be struck with leprosy
And the second_head said: She shall have a harsh voice
And the third_head said: She shall become a poor peasant.
And if we were so minded, we could take that chunk of code and put it in its own function, called minimal_three_heads()
, perhaps.
And then, whenever we wanted to tell that tale, we could just call out: “By the magic of code, I demand that you tell me the minimal_three_heads()
story.
And it would…
Running the code for yourself
If you would like to make the wishes and invoke the spells described in this chapter from the book version of the chapter, the easiest way is to click on the rocket (“launch menu”) icon in the tool bar at the top of the book page and select the Live Code
option.
A status button will appear at the top of the content area of the page and display a series of progress messages as the book tries to summon a genie from a far off land.
As soon as the genie has been summoned, you can scroll down to the code cell areas of the book and, as if by magic, they will have been transformed to cells that look a bit like the following:
If you click the run button in a cell, the incantation will be invoked.
When the Live Code mode is enabled, you can also edit the content of the code cells - so if you want the three heads to say something different, you can put words into their mouths by changing the appropriate part of the spell.
The changes you make will not be saved: when you reload the page, the original code will reappear. To access the live code mode again, you will also have to perform the correct ritual again, which is to say: click the rocket and select the appropriate menu option again.
Note that you need to call the various parts of the charm in the correct order: there’s no point trying to cross the stream until you’ve found the axe to cut down the tree to make the bridge.
Running the code using an interactive notebook editor
As well as executing the code in a situated fashion “inline” in the book, you can also execute the code inside an interactive editing environment. See the section Invoking the Incantations Contained in This Book for a tale about how you might achieve that…
So what are you waiting for..? You know you want to give it a go… Click that rocket!
And that’s pretty much it for what code can do…
But as you have seen, we also have the ability to create our own story functions, as well as reusing ones created and shared by other code-storytellers. And this means that we can quite quickly create what seem to be impossibly complex tales, pretty much off the top of our heads, using our own, made up, recipes, and some perhaps not-so-simple bundles of code developed incrementally by hundreds of other story-coders over tens of years.
In the pages that follow, the code described is intended to move a story along, to get from here to there, to where the next thing becomes possible. And as a hero may collect various magical gifts whose usefulness only becomes apparent later in a storied quest, so too might we come across things that look at little peculiar, at first, until we realise how we might be able to make use of them later on.