Listing the contents of a table in a readable way

The below code works, but how does one display the output in a readable and grammatically-correct fashion?

So, not a bunch of names with no commas but, “Kitchen, Living Room, Foyer, and Lawn.” Especially since I intend to add/remove entries which might make that output look something like, “Kitchen and Living Room”.

Kevin is a person in the Library. 

Table of Kevin Destinations
destination
Kitchen
Living Room
Foyer
Lawn

Instead of asking Kevin about "rooms":
	repeat with N running from 1 to the number of rows in the Table of Kevin Destinations:
		say "[destination in row N of the Table of Kevin Destinations]".

If you store the destinations in a list instead of a table, you can get the format you want by simply ‘saying’ the list. Have a look at 21.3 in the documentation for details.

If the values need (or you especially want them) to be in a table for some reason, you could either convert the table to a list on the fly at the moment you want to print it out, then say the list – or you could use a custom routine to print the table contents nicely. I’ve made a demo that shows such a routine.

In the following demo code, I’ve stored the rooms both in a table and in a list. Then I print the rooms out both ways, first using a routine that nicely formats the contents of the table, second by just saying the value of the list. This is so you can see how each method can be programmed.

I didn’t want to program any conversation, so in the demo, you just ‘jump’ to get the printouts.

"Two Ways"

Kevin is in the Library. 

Kitchen is a room.
Living Room is a room.
Foyer is a room.
Lawn is a room.

Table of Kevin Destinations
destination
Kitchen
Living Room
Foyer
Lawn

DESTINATION-LIST is a list of rooms that varies.

When play begins:
	now DESTINATION-LIST is {Kitchen, Living Room, Foyer, Lawn};

Instead of jumping:[asking Kevin about "rooms":]
	say "Method 1: Making a nice output from the contents of a table:[paragraph break]";
	let REMAINING be the number of rows in the Table of Kevin Destinations;
	repeat through the Table of Kevin Destinations:
		say destination entry;
		decrement REMAINING;
		if REMAINING is 1:
			say " and ";
		otherwise if REMAINING is 0:
			say ".";
		otherwise:
			say ", ";
	say "[line break]Method 2: Saying the contents of a list:[paragraph break]";
	say "[DESTINATION-LIST].";

Test me with "jump".

-Wade

1 Like

I started out with a table because that’s what I’m more familiar with, but sounds like I need to spend more time with lists. Awesome, thanks!

Sometimes a table will do just as well as a list, and vice versa, so it can be hard to instinctively pick one over the other. But often what happens is you go along and then you end up in a specific situation (like you did!) where you discover the other format could make something you want to do easier.

-Wade

One thing that tables do better than lists by default is choosing a random value from them – you can just:

choose a random row in the Table of Kevin Destinations;

But there isn’t really an equivalent for lists. But you can fix that by defining this:

To decide what K is a random member of (list - list of values of kind K):
	let the count be the number of entries in the list;
	let the index be a random number between one and the count;
	decide on entry index of the list.

And now you can:

let target be a random member of the list of Kevin Destinations;

Or:

let target be a random member of { Kitchen, Living Room, Foyer, Lawn };

Another non-list-based approach to this sort of thing (that I suspect I’ve mentioned before) is to use adjectives (“descriptions”). It technically could be a bit slower than the list-based approaches (especially if you have a lot of rooms), but unless you’re targeting tiny micros then it’s unlikely to be noticeable:

A room can be Kevin-abiding.
Kitchen, Living Room, Foyer, and Lawn are Kevin-abiding.
Definition: a room is Kevin-free if Kevin is not in it.

... let destination be a random Kevin-abiding Kevin-free room;
... let Kevin's rooms be list of Kevin-abiding rooms;

Map regions can also be used for this:

Kevin Abode is a region.
Kitchen, Living Room, Foyer, and Lawn are in Kevin Abode.
Definition: a room is Kevin-free if Kevin is not in it.

... let destination be a random Kevin-free room in Kevin Abode;
... let Kevin's rooms be list of rooms in Kevin Abode;

The downside of this is that map regions can’t overlap or intersect (without being a strict subset). But since regions are internally implemented as a list, it’s faster than using a general adjective.

2 Likes