1
votes

In my Prolog program I have a predicate reg/1 which says if something is a regular expression. I'd like to make the program recognize sequences of regular expressions as a regular expression. So, if reg(a_1), reg(a_2), ..., reg(a_n) are all regular expressions, Prolog should answer yes/true to the query reg(a_1, a_2, ..., a_n). But I don't know how to do it.

What I have done is the following:

reg([H|T]) :- reg(H), reg(T).
reg([X]) :- reg(X).

If, for example, reg(a), reg(b), reg(c) are all in the knowledge base, then Prolog answers yes/true to the query reg([a, b]) or reg([b, a, c]), but I can't ask it something like reg(a, b) or reg(b, a, c), i.e., I can't get rid of the square brackets.

1

1 Answers

3
votes

It is very uncommon in Prolog to use the same structure with varying arities. To show you one such place where they could have been used but are not, consider directives as they are used to declare a predicate dynamic, multifile, or discontiguous. Say, I want to declare a/2 and b/5 dynamic. The following options are possible in ISO-Prolog:

:- dynamic(a/2).
:- dynamic(b/5).

:- dynamic([a/2,b/5]). % using a list

:- dynamic((a/2,b/5)). % using an and-sequence

Additionally, many Prolog systems have declared dynamic/1 a prefix operator (as an implementation specific extension) such that you can write:

:- dynamic a/2.
:- dynamic b/5.

:- dynamic [a/2,b/5].

:- dynamic a/2, b/5.

However, there is no

:- dynamic(a/2,b/5).  % does not work

which would correspond to your idea.


If you really want to use that representation, you will need (=..)/2 for that. I'd say this is a source of many potential bugs.


The only case that comes to mind where a structure with "variable" arity is commonly used are compact representations of sets of variables, as they are used in the implementation of setof/3. Instead of using a list of variables Vs the structure V is used.

term_varvect(T, V) :-
    term_variables(T, Vs),
    V =.. ['.'|Vs].         % some use v instead of '.'

In systems with a limited max_arity you have to handle the overflow case:

term_varvect(T, V) :-
    term_variables(T, Vs),
    catch( V =.. ['.'|Vs],
           error(representation_error(max_arity), _),
           Vs = V).