What is never equal to itself?

2019-07-14 18:18发布

Is there value in Prolog that is not equal to itself? I write answer to some question about min of tree and this answer also says that if tree is empty min is null. Sounds good idea first but now when I think it sounds like bad idea.

It is kinda OK if null <> null, no problem. But in Prolog I see null is just atom so....

?- null = null.
true.

?- null == null.
true.

?- dif(null, null).
false.

How can I make some term in Prolog that always say:

?- dif(Something, Something).
true.

But if it is any other thing and not this term that is the null thing still say false.?

Or if this is not how I should think in Prolog then how should I think about not true. and also not false. but "neither true nor false because something is missing"?

1条回答
Deceive 欺骗
2楼-- · 2019-07-14 19:19

Just for fun, not really the answer you're looking for, taking the question title quite literally:

?- _ == _ .
false.

But dif/2 is not fouled (hint: each occurrence of the anonymous variable represents a different variable):

?- dif(_, _).
true.

Now, seriously. Starting with your tree minimum predicate example, there's a trivial alternative: the predicate can simply fail when the tree is empty. A better alternative may be to use optional or expected term libraries. The concepts behind these libraries are found in several programming languages, where they provide a better alternative to null. You have both libraries in Logtalk, which you can use with most Prolog systems. See:

and

You use one library or the other depending on your interpretation of "missing" meaning something that is optional (absence of a value is fine) or expected (absence of a value is an error). For example, assume that in your particular application it makes sense to use 0 as the minimum value of an empty tree when doing a specific computation (e.g. the sum of the minimums of a set of trees). If the tree minimum predicate returns an optional term reference, Ref, instead of an integer, you could do e.g.

...,
optional(Ref)::or_else(Minimum, 0),
Sum1 is Sum0 + Minimum,
...

This is a cleaner solution compared with using an if-then-else construct:

...,
(   tree_minimum(Tree, Minimum) ->
    Sum1 is Sum0 + Minimum
;   Sum1 is Sum0
),
...

It also allows you to use different defaults for different computations. For example:

...,
optional(Ref)::or_else(Minimum, 1),
Product1 is Product0 * Minimum,
...

More important, it doesn't mask that you're processing an empty tree in the same way that a default value would do. For example, the following code will only write the minimum values of non-empty trees:

print_tree_minimums(Refs) :-
    meta::map(print_tree_minimum, Refs).

print_tree_minimum(Ref) :-
    optional(Ref)::if_present(write).

or, using a lambda expression:

print_tree_minimums(Refs) :-
    meta::map([Ref]>>(optional(Ref)::if_present(write)), Refs).

This answer is getting long and I don't want to transform it into a general discussion of the pros and cons of optionals and expecteds. But descriptions on both concepts and libraries is easy to find. E.g.

https://en.wikipedia.org/wiki/Option_type

https://youtu.be/NhcHwkUPX7w

查看更多
登录 后发表回答