Documentation, Chapter 22 ... Huh? Help Me Understand Please

Of all the things in Inform 7, I find the arrow notation to be the most confusing. It’s the least English-like.
I never learned anything about this in math classes. So I looked it up, as one does. (The manual specifically says “phrase K → L” is meant to be like arrow notation in maths)
I learned that F K → L would be pronounced “The function from K to L” and that K would be the domain and L would be the codomain.
uh … okaaayyyyy … That’s almost kinda starting to make some sense. But also not really.
But how much relevance does this (the maths definition and usage) actually have to programming in Inform 7? What is it for? How would a person use it? Why would a person use it?
That chapter has only ONE code example, and it doesn’t use the arrow notation. It’s not very useful or informative at all really. Most of the descriptions talk about numbers, which isn’t something we often use in IF, so I don’t see those explanations as much help. Is it even something I need to concern myself with?

That’s the “Advanced Phrases” chapter, so unless (until?) you particularly need it for something, I wouldn’t worry about it?

But it doesn’t look like you ever need to write it? It looks like it’s just a way to describe the “kind” of a phrase, in case Inform needs to tell you about that. For instance, Section 22.3 says:

To decide which text is (T - text) repeated (N - a number) times: …

has the kind “phrase (text, number) → text”.

The arrow is just a piece of punctuation that separates the inputs from the output. This notation says that it is a phrase that takes a text and a number as input and gives you a text as output. So you might read it as “phrase from text and number to text” or something like that.

Don’t know if that’s helpful, since I’m sort of just repeating what’s in the docs…?

Only if you want to define a sort of meta-phrase like this:

To decide which Foo is the Bar of (ph - phrase K → L) on (v - value of kind K): […]

You could also make it partially restricted on the types:

To decide which number is the squared result of (ph - phrase K → number) on (v - value of kind K): […]

(Although I’m never 100% certain on the syntax with these things.)

2 Likes

In 14 years of programming with Inform I have never used or seen that syntax used, other than in one chapter of the Standard Rules that contains very low level phrases. And I have also never used those phrases or seen them used. So you’re probably good just skipping that chapter.

1 Like

I’ve seen it used occasionally.

My Benchmarking extension uses it to specify a phrase property of an object:

A test case has a phrase nothing -> nothing called the run phrase.

And Mike Ciul’s Disambiguation Override has this, a helper phrase to use with custom phrases:

To loop over the match list with (func - phrase thing -> nothing): (- LoopOverMatchList({func}); -

It’s possible there are better alternatives in the I7 language than when these extensions were written, I haven’t really thought about it.

Though these aren’t generically typed phrases. I think Graham added support for them for the sake of completeness as he added other more immediately useful patterns from functional programming. Maybe the standard rules uses them? Yes, it does, to implement phrases like this, which in other languages would be called “map”:

To decide what list of L is (function - phrase K -> value of kind L) applied to (original list - list of values of kind K)
	(documented at ph_appliedlist):
	let the result be a list of Ls;
	repeat with item running through the original list:
		let the mapped item be the function applied to the item;
		add the mapped item to the result;
	decide on the result.

Looks like the only functions taking generic phrases are the filter, map, and reduce functions.

The general idea is that it allows you to use constructions at a rather high level of abstraction and generalisation.

The arrow notation gives you a way of referring to a function (phrase) in a fairly general, abstract way, so that you can use it in other code, for example in a “To decide” phrase, which is itself a function.
The neat thing is that you don’t need to specify the actual concrete function (like squaring a number, or taking the square root, or the absolute), but can write the “framework” just with a placeholder, where you treat the function as a variable, so to speak.

That means that you can build a sort of “higher-order” function, for example a function that has another function as an input.

The classical example, which Dannii already mentioned, is “map”, which takes a function (let’s call it F) and a list as an input and applies it to each element of the list (and returns the resulting list). Map doesn’t care what the function F is and what the list is, as long as F’s input type and the type of the elements in the list match.
So, for a list of numbers, the function F could be squaring, taking the root, abs, and so on.

For an actual (though fairly specialized) “end-user” example, take a look at these posts from a thread sometime ago: Problems displaying values with units; math with values that have units generally - #3 by StJohnLimbo, Problems displaying values with units; math with values that have units generally - #5 by StJohnLimbo

In the context of Inform, it’s nice to know that the capability is there and to keep it in the back of your mind as another tool in the toolset, but don’t worry much about it. As the others said, it will usually not be necessary.

Side note:
If you are interested in programming in general, I’d recommend to look into the topic in more detail, because the “functional programming” style is quite important and interesting. From a practical perspective, it does have the reputation that it’s harder to understand in the beginning, but that it can contribute to clean code with very few bugs.

This is a nice tutorial for Haskell, one of the best-known functional programming languages, for example: http://learnyouahaskell.com/ (available as a book, but also free online)
Edited to add: Racket would also be a good choice to learn functional programming.

2 Likes

This is a general issue with programming language texts… there are these complicated, powerful constructs with just some little trivial example demonstrating their usage, and you’re left with no clear idea of why and when you’d use such a thing (…until maybe you have a lot of practice with a lot of languages and recognize the shape of the thing and have experience with when it’s used.) And that’s because for these complicated, powerful constructs, a substantial example could take 30 pages to explicate and programming language texts have a lot of ground to cover.

This construct doesn’t seem to have been used widely. I’d been going to cite Dannii’s Benchmarking… grepping through my collection of I7 source, outside of the Standard Rules I’m only seeing Benchmarking, Scope Caching, Constraint Solver, Glimmr Canvas Animation, and Scroll Thief. That last demonstrates one interesting possibility:

Table of Spell Durations
subject (an object)	enchantment (a spell)	duration (a number)	end effect (a phrase object -> nothing)

A table column can hold phrases, giving a relatively quick and easy way to specify distinct complex behavior for some other thing. Multiple things could have the same end effect phrase, and the phrase for a given thing could be re-assigned during play.

That could let you do things that could be really hairy and involve lots of conditionals to try to do otherwise.

2 Likes

True, but I’ve the feeling using rules (which can also be stored in tables) is usually simpler and less obscure than using phrases. (In the Scroll Thief example, where it’s a phrase taking a single object and returning nothing, an object-based rule should do the same job as well as a phrase.) If the phrase took several arguments, it might be another story (although we might get away by using rules and some global variables).

Regarding the chapter 22, I agree with others. It describes very powerful and useful programming concepts, but which are rarely necessary in Inform except in some low-level cases.

I remember understanding it vaguely the first time I read it but having no idea how it could be useful. When I reread it years later, but after gaining a mathematical and programming background, I could connect it with the same concepts in other programming languages, but I still haven’t had to use it.

2 Likes

I have used it to allocate a phrase as a property:

An animal has a phrase animal -> text called size. The size of an animal is usually determined by weighing. The size of the rat is determined by measuring. The size of the partridges is determined by estimation.

To decide what text is the rough dimensions of (A - an animal)(this is determined by estimation):
	if A is the partridges, decide on "about 12 pennyweight";
	decide on "fairly average-sized".

To decide what text is the dimensions of (A - an animal)(this is determined by weighing):
	if A is the rat, decide on "small";
	decide on "average-weight".
	
To decide what text is the extent of (A - an animal)(this is determined by measuring):
	if A is the rat, decide on "12 inches long- that with the tail!";
	decide on "[A]-length".

To say heft of (A - an animal): say "[size of A applied to A]". [Now we can write either [size of the noun applied to the noun] or just [heft of the noun]]

The description of an animal is usually "[The item described] [are] [heft of the item described].".
2 Likes