Write a function that accepts wrapped constants, but only one level of depth

I want to write a function (apologies, probably not using the correct term here) wubble

that is true for specific constants and true for those constants if it is to be wrapped in another constant, but only one level! Examples:

% are supposed to be TRUE:
?- wubble(foo).
?- wubble(bar).
?- wubble(wrapper(foo)).
?- wubble(wrapper(bar)).

% are suppoed to be FALSE:
?- wubble(not_in_knowledge_base).
?- wubble(wrapper(wrapper(foo))).

      

A naive (at least in my brain) implementation looks like this:

wubble(foo).
wubble(bar).

wubble(wrapper(wrapper(_))) :- !, fail.
wubble(wrapper(X)) :- wubble(X).

      

And this works with the queries above. However, I cannot list all the valid ones X

for wubble

using this implementation:

?- wubble(X).
X = foo
X = bar

      

So, this is missing X = wrapper(foo)

and X = wrapper(bar)

. Is it possible to fix my implementation somehow?

+3


source to share


2 answers


You can separate facts from rules:



wubble_(foo).
wubble_(bar).

wubble(X) :- wubble_(X).
wubble(wrapper(X)) :- wubble_(X).

      

+4


source


One solution in this particular case, as the OP pointed out, is this:

wubble(foo).
wubble(bar).

wubble(wrapper(X)) :- wubble(X), ((X = wrapper(_), !, fail); true).

      

Since he also asked for an explanation of this pattern, here's my best shot:

Considering the above knowledge base, the request type wubble(X).

looks at it from the top down to the facts or the heads of the rules, which are combined with the objective wubble(X)

. If he finds a fact, for example, the wubble(foo)

goal will simply succeed by combining X

with the internal term of the fact, in this case foo

. After that, we can tell Prolog to go back to the last selection point (a node in the depth-first search tree that Prolog creates during this process), which in this case was given by the original target wubble(X)

and made it look like other solutions to that target. If we do this here, we get the fact for the second constant wubble(bar)

, of course.

Now for the fun part. If we go back again, the only way left to achieve the goal wubble(X)

is to satisfy the antecedent of your rule. Now release it mechanically. This may be surprising, but it wubble(wrapper(X))

combines with wubble(X)

; you should think of these X

es as independent. As in the case of a request wubble(X)

and a rule definition wubble(wrapper(X)) :- ...

, X

is only a local name. Indeed, these two variables are independent, unlit variables in this situation, and since the unchanged variable is merged with basically everything, we have X = wrapper(X)

and thus the head of the rule matches our request. Perhaps we should call them X1

, and X2

to request and rule accordingly.

Now the tail of the rule is a conjunction, so we first try to satisfy the first goal wubble(X)

, which creates a new selection point. Now the process starts in the main: we search the knowledge base from top to bottom for things that combine with what we find first wubble(foo)

. So X2

now unified with foo

, and we check if the second part of the join ends, now with X2 = foo

, what does it do because foo \= wrapper(_)

. Therefore, since both conjunction goals were achieved with help X2 = foo

, our original goal succeeds with also X1 = wrapper(X2) = wrapper(foo)

.



Backtracking from this basically brings us back to the second selection item created by the first union target in the rule. We then find X2 = bar

which is tested again with the second part of the conjunction and our original target succeeds with X1 = wrapper(bar)

.

Then we come back to the rule again; we combine X2 = wrapper(X3)

, our new goal is wubble(X3)

creating a new point of choice, and this succeeds with the help X3 = foo

, and the second part is also tested. So now we go one level and we have X2 = wrapper(foo)

. This does not satisfy the second part of the conjunction! It runs !, fail

, so our original goal wubble(X1)

, which we have unified X1 = wrapper(X2) = wrapper(wrapper(foo))

, fails this time. But not only that, we're also shorthand, which eliminates the point of selection of the first recursive call kipple

and everything below, so we don't even try to use X3 = bar

or X3 = wrapper(X4)

.

So we will return to our starting point of choice for the goal wubble(X1)

; but there are no additional suggestions in the database, so we're done.

Now I understand that it can be difficult to follow in text form, so here is my attempt at rendering the search tree:

Search for three queries <code> wubble (X) </code>
      <br>
        <script async src=
. Red means cut ... cuts well." data-src="/img/d27bf8d4610898e5dab2c6054a2ff70f.png" class=" lazyloaded" src="https://fooobar.com//img/d27bf8d4610898e5dab2c6054a2ff70f.png">

+2


source







All Articles