singleton variables in prolog

后端 未结 3 1302
甜味超标
甜味超标 2021-02-07 00:03

I was testing my new version of SWI prolog and keep coming across the error :singleton variable.

Example:

member(X,[X|T]).

member(X,[X|         


        
3条回答
  •  野的像风
    2021-02-07 00:26

    You have a bug here:

    member(X,[X|T]) :- member(X,T).
    

    What you're actually saying (as opposed to what you think you're saying) is that member/2 holds if X is at the head of the list and present in the tail of the list. This predicate will only ever be true for the first N copies of the same thing at the beginning of a list, so it's a very strange thing to say!

    ?- member(X, [a,a,c]).
    X = a ;
    X = a ;
    false.
    
    ?- member(X, [b,a,a]).
    X = b ;
    false.
    

    Now, you could correct the bug and still have a singleton warning by doing something like this:

    member(X, [Y|T]) :- member(X, T).
    

    But this is neither as good as the conventional definition with two heads or @CapelliC's version (+1) with an explicit OR. I think you should wait until you understand Prolog a little better before putting much stock in your sense of Prolog code aesthetics. If you stick with it for a while you'll come to appreciate this warning as well as the use of anonymous variables.

    What makes singleton variables useless in Prolog is that they're named but nothing is known about them and they have no effect on the rest of the computation. The underscore highlights that absolutely anything could go in there without affecting the meaning. What makes

    member(X, [X|T]).
    

    true is that the X is position 1 is the same as the X at the head of the list in position 2. Lists must either be empty or have a head and a tail, but what's in the tail is not relevant here, what matters is that X is also the head. The T could be the rest of the list, or it could be an improper list, or it could be a breadbox or lightning or the smell of the air on a spring day. It has no bearing on the truth of member(X, [X|T]).

    The singleton warning tells you "you've reserved a name for something here, but you never call anything by that name." The first thing I do when I get this message and it isn't an obvious typo is replace the name with _ and see if my code still makes sense. If it doesn't, I have a logic error. If it does, it was probably unnecessary.

提交回复
热议问题