You can always use a list as an argument I guess? You can also use a dict as an argument, then you can name your arguments? This is especially useful for “option lists”.
Yes. I have a database base of rules that I’d like to index and match. Some are automatically generated, some are hand written. There rules have datastructure heads. I’d like to deep index the on the heads. While its possible to use lists, we’d end with situations like:
[[_,_,[noun,_,_,_,_,_,_] | _, ], B ] :-
f(B)
… now, if asked to manually add a ‘_’ to the inner list for 60 same-same but different rule head – seems like a PITA, as it is for datastructures without wildcards.
For dicts, I don’t think they can be indexed in the head that way
Dicts are a sensible solution to this which we possibly should support by default. It connects to ECLiPSe handling of tag{key:value, …}. In ECLiPSe such a term is mapped at read time to tag(A1, A2, …), where a declaration controls the arity and argument order for tag(…). If we create such a mapping and expand it in e.g., term_expansion/2, you can write e.g.
transform{pos:noun} :-
As with any language it is typically a good idea to avoid many arguments. In many cases you can get away using just a few and using (e.g.,) a dict for additional (mostly) read-only arguments.
I think this is worth adding, one of the reasons I often use dicts is to allow for “future-proof” data structures that won’t break when we want to add a new field. This is the main use case I have for dicts.
However, it is always a pain that unification requires all keys to be present. Some way of partial unification in the head would be very useful.
Mostly for my own reference, ECLiPSe calls these a struct. See http://eclipseclp.org/doc/tutorial.pdf, section 4.1 Structure Notation. The declaration is e.g.,
:- local struct(book(author, title, year, publisher)).
It is unclear how we should handle export/import of struct declarations. That probably needs to be part of general export/import of macro expansion. The idea would be that any term (dict) book{...} translates to a book/4 term. Any key other than the named four keys results in an error.
I think this could be a useful library that also improves the compatibility with ECLiPSe.
which can easily be converted in to the eclipse syntax for compatibility reasons. I am assuming all the dict predicates would work without a problem with the struct’s; the only difference is that partial unification would be allowed.
Export/import
What is the main disadvantage that you see from just declaring it in the module/2 directive? e.g. like:
a 50% slowdown for pattern matching, which seems reasonable.
it doesn’t seem possible to use dicts as heads (and so its not straightforward to map back and forth between compound terms and dicts):
tree(tok{a:1}, []). % Fine
tok{a:1}. % Type error: `callable' expected, found `tok{a:_2052,b:_2056}' (a dict)
One nice benefit of dicts over compound terms that we can write:
tok{x:1,y:2}=F{x:1,y:2}.
whereas for compound terms, this kind of functor unification is an error, and we need to write:
f(1,2)=..[F,1,2]
(I.e. we cannot directly use unification here and so some automated translations may need extra work). Is this intentional - can we rely upon this dict functor name unpacking in the future? I remember reading somewhere there dict as compound terms under the hood, but we shouldn’t rely upon that.
As you have the same set of keys (only one) deep indexing may kick in. That won’t work in general, but will do the job on some scenarios.
In the end a predicate is defined by the name and arity of the callable head term. As is, dicts are compounds (not guaranteed for the future), but the name is not the tag name but the hidden C’dict’ atom and the arity is 2*|Keys|+1. So, that doesn’t lead to anything useful.
Yes, that is part of how dicts are defined. Its syntax, unification and dict predicates are stable. Just the fact that they are compounds (and thus you can use the compound predicates on them) is not guaranteed.
What ECLiPSe does though is a read-time rewrite of dict syntax to a compound term based on the struct/1 declaration. That way, the dicts only exists as a syntactical shorthand for a compound with named arguments. That comes with limitations (you can not dynamically add keys to a dict), but allows using them for dealing with named arguments. We can provide ECLiPSe behavior as a library, providing both scenarios.
The two could be joined. The dict syntax merely provides a convenient syntax for creating records. It also provides a convenient way to access fields as in (e.g.)