Plists (maps / dicts) in Dialog

Dynamic Predicates limited to two parameters got me thinking about ways to represent map-like datastructures in Dialog. (Since that’s the data structure I think most programmers would normally reach for to solve problems like the one in that post.)

Anyways, here’s a snippet of Dialog that implements “plists” – which IIUC is a common way to solve this sort of problem in Lisp, where they’ve suffered from having only lists to work with for much longer. Effectively: you have lists of even length, alternating between keys and values, and a handful of helper predicates that make manipulating those lists not extremely tedious.

Still getting the hang of Dialog, so it may not be the ideal version, but perhaps interesting still…

3 Likes

This looks quite interesting, ill definitely have to mess aroundcwitg this a bit when i get the chance. I’m curious if your first predicate can handle nested plists or if $v would onpy matvh the whole list? If it could not find a nestd $v do you thinkbit would be possible to create a predicate whoch handles noth the case where $v is nested or not nested, or would seperate predicates be needed for both cases?

As-is, looking up a key grabs the entire corresponding value. So, for example,

($plist = [#k1 100 #k2 [#k3 70]])
(plist $plist key #k2 has value $out)
$out

prints [#k3 70]. So a plist can contain a plist, and the lookup works just like it would for any other value. Sort of like a dict in python or an object in javascript, I guess.

(But of course that’s just what I happened to implement! This sort of datastructure is pretty flexible… if you’re looking for some other behaviour we can probably come up with something.)

1 Like

I’m currently in the process of porting Graham nelson’s Curses to Dialog, based on various forms of release 16’s disassembly. I needed to implement Inform 6’s tasks, which in Curses are defined as constants to reference the task name and in turn refer to an array of scores. This can be represented as a map, hence my reply in this topic.

I’ve implemented this using Dialog’s ingenious unification. Instead of using constants, the names, and thus indices, are defined as rules.

When queried, these can be quite powerful as they not only provide an index based on the rule definition, but also the name based on the index for a reverse lookup.

As an example, here’s my award rule, as well as the top 3 achievements from Curses:

(score @hamburg 1)
(score @torch 2)
(score @joshua 3)

%% The task list
(global variable (taskScores [3 7 7]))

%% The award rule, which does the lookup
(award $taskName)
	(score $taskName $index)
	(taskScores $list)
	(nth $list $index $points)
	(increase score by $points)

If the index is known, we could look up the name as well:

	(score $taskName 2)
%% $taskName is now @torch

Hope this is useful and showcases another way of implementing maps.

To modify this further, we could have sublists for $taskScores, and append to it when a task is done. Or, better yet, have a second list with the task indexes and if the list contains an index, the task is done. Of course this is outside the scope of this topic, I’m mentioning it for completeness’s sake only.

I really like how Dialog makes one think outside the box, even though when porting a reasonably huge game like Curses, it can be a bit frustrating at times :relaxed:

1 Like