New notation for dict-based "method indicators"?

As SWI-Prolog provides methods on dicts. These are also functions because they evaluate to some term, but functions are generally not understood to be attached to a parent object or evaluated in the context of an object. Some new terminology is hereby proposed:

Call them “methods” (and the call a “dotcall”)

And write the corresponding “method indicator” as

.name/arity (or maybe name./arity),

in a manner analogous to name/arity (predicate indicator) and name//arity (DCG non-terminal indicator).

I note that this object-oriented programming is a bit weakened by the fact that dict tags must also be a module name. Dict tags thus are actually “method bundle names”. If one really wants OO, the classname must be carried inside the dict for some extra infrastructure. That’s probably what Logtalk does.

To be honest, I rarely use this. I wonder how useful the dict methods are considered to be. Anyone here with experience?

I use get_dict/3 a certain amount for conditional lookup. (And in a few cases, for custom versions of get_dict_ex/3 that provide better error messages.)
But most of the time, I use the “.” operator because it’s a more compact notation. (I have to be careful if I use it in the head of a clause, of course).

Function on dicts could use a wiki. :slightly_frowning_face:

1 Like

You could use (//)/2 , because functions on dicts adds two arguments,

Yes, but that’s not a good idea, because the // already indicates “DCG rule”.

It is already sufficiently perverse that one is told both of these:

  • name//arity is syntax for the “non-terminal indicator”, i.e. DCG rules, and means “arity + 2”
  • There is no guarantee that a DCG implementation necessarily be based on two additional arguments.

There should be abstraction.

Actually the official name is “function on dicts” and not dict methods. To become dict methods you would need to show that they can deal with method dispatch and favorably inheritance/overiding, things from object-oriented programming. Can you show that?

I suppose so. But there is no inheritance “out of the box” - all the “dict objects” are on the same level (they really are modules, which are not nested). Inside the module, you sure can dispatch on argument “type” (if it is recognizable to Prolog in-the-head; this means the argument must be tagged at least or you are forced to manually dispatch in the dict-attached predicate/function.

For inheritance of whatever kind, one either has to instrument the dict tag (it can take any term) or add special key-value pairs to the dict. Should not be too hard, but definitely based on convention, not provided by the language.

But it’s probably easier to just use Logtalk if one wants to go that way. It also has objects implemented as modules (“modules are prototypes”). Makes sense.

I’m still in the exploratory phase :smiley:

Inline expressions seems a good use:

:- module(string,[]).

% This is a predicate format/3 written as a function format/2 (maybe there
% needs to be a new descriptor syntax: format///2 ?) taking a dict tagged as
% "string" and two arguments which evaluates to the value of variable Text.

S.format(Msg,Args) := Text :- with_output_to(string(Text),format(Msg,Args)).

and then write inline expressions like:

?- debug(foo),debug(foo,string{}.format("Hello, ~q\n",["World"]),[]).
% Hello, "World"