One of the frequent excuses for coders to avoid using the message printing
mechanism is that they require defining tokenization rules for the messages
and that is too much work when they can just call
write/1 instead. We can
try to argue about laziness but the coders do have a point. To easy the pain
of using the message printing mechanism, Logtalk defines a set of
that can be used without defining any
message_tokens//2 tokenization rules.
The first example is when you want to print a message when execution is at
a given point in the code. The
@/1 meta-message allows you to write:
| ?- logtalk::print_message(comment, core, @'Phase 1 completed'). % Phase 1 completed yes
Another common example is printing the a variable binding, which usually translates to print a pair identifying the variable and its binding:
| ?- logtalk::print_message(comment, core, answer-42). % answer: 42 yes
But sometimes we need to write a complex term using a specific format. In
that case, we can use the
Format+Arguments meta-message. For example:
| ?- logtalk::print_message(comment, core, 'Position: <~d,~d>'+[42,23]). % Position: <42,23> yes
Also common is printing a list of items, with or without a title:
| ?- logtalk::print_message(comment, core, [arthur,ford,marvin]). % - arthur % - ford % - marvin yes | ?- logtalk::print_message(comment, core, names::[arthur,ford,marvin]). % names: % - arthur % - ford % - marvin yes
Worth mentioning that a message term is only interpreted as a meta-message
when the user doesn’t define a
message_tokens//2 tokenization rule for it.
Thus, no conflicts if the user decides to use a message term that would be
otherwise interpreted by default as a meta-message.
A second complain is that the goals are verbose. Sure, we can use implicit
message sending to the built-in
logtalk object using the directive to
shorten the goals a bit. For example:
:- uses(logtalk, [ print_message/3 ]). enterprise :- print_message(comment, core, @('Entering the Neutral Zone...')), ..., print_message(comment, core, @('Looking for Romulans...')), ....
But we still need to write the message kind and component arguments. Not conceding defeat, predicate aliases to the rescue:
:- uses(logtalk, [ print_message(comment, core, @Message) as log(Message) ]). enterprise :- log('Entering the Neutral Zone...'), ..., log('Looking for Romulans...'), ....
Do you happen to have some existing code using e.g.
format/2 for writing messages
that you want to port to the message printing mechanism? Note that you can write:
:- uses(logtalk, [ print_message(comment, core, Format+Arguments) as format(Format, Arguments) ]). enterprise(Zone, Enemy) :- format('Entering the ~w...', [Zone]), ..., format('Looking for ~w...', [Enemy]), ....
In this case, all
format/2 goals will be compiled as
goals. You could use similar aliases for other output predicates, simplifying the
port by minimizing the changes required.
Format+Arguments meta-message exemplified above requires Logtalk
3.37.0 or a later version.