Search code examples
prologswi-prolog-for-sharing

SWI-Prolog (SWISH): No permission to modify static procedure `(=)/2'


During some playing around with different list predicates in SWI-Prolog (SWISH), I was trying to check if an atom a was part of the list List1 which I defined in the program as List1 = [a,b,c,d].

I formulated my query as member(a, List1)., expecting something along the lines of a simple 'yes' (just as it shows in this youtube video at 59:25), but instead I got a warning

Singleton variables: [List1]

and an error

No permission to modify static procedure `(=)/2'

From what I understand from looking this up online, the warning is not that important here. I do not understand, however, why I get an error message while a is clearly a member of List1.

I tried this in two different ways:

1) By adding List1 = [a,b,c,d]. to the program and querying with member(a,List1). (which resulted in the error above);

2) By passing List1 = [a,b,c,d] directly to the interpreter and then using the same query ( member(a,List1). ), which resulted in an endless amount of results where a shifted positions in the Head of the list, like so:

List1 = [a|_1186]
List1 = [_1062, a|_1070]
List1 = [_1062, _1068, a|_1076]
List1 = [_1062, _1068, _1074, a|_1082]
List1 = [_1062, _1068, _1074, _1080, a|_1088]

Is this something about the specific Prolog version I am using, or am I missing something very simple?

EDIT

I was aware that a similar question was posed here , but I did not manage to fully understand the answer (nor the question) as it was immediately going about things as dynamic which I have not yet encountered in Prolog. I was looking for a more general, more 'high-level' answer which I have found by posing this question.


Solution

  • I defined in the program as List1 = [a,b,c,d].

    This is not what it does. What it does is define a predicate =/2:

    2 ?- write_canonical( (List1 = [a,b,c,d]) ).
    =(_,[a,b,c,d])

    (The ?-, or 2 ?- that you see there, is the interactive prompt of a Prolog system; SWI Prolog in my case. Whatever goes on that line after it is what I have typed; and then on the next line we see the system's response).

    Of course this tramples over the already existing built-in definition for = as the unification predicate. And hence the error which says precisely that. And yes, it is important.

    To "define" a list in Prolog, we can define a predicate

    8 ?- [user].
    p([1,2,3,4]).
    

    such that we can then query

    9 ?- p(List1).
    List1 = [1, 2, 3, 4].
    

    and work further with List1,

    10 ?- p(List1), member(A,List1).
    List1 = [1, 2, 3, 4],
    A = 1 ;
    List1 = [1, 2, 3, 4],
    A = 2 ;
    List1 = [1, 2, 3, 4],
    A = 3 ;
    List1 = [1, 2, 3, 4],
    A = 4.
    

    We could also just directly specify the list as a sub-goal of our query,

    11 ?- List1 = [1,2,3,4], member(A,List1).
    List1 = [1, 2, 3, 4],
    A = 1 ;
    List1 = [1, 2, 3, 4],
    A = 2 ;
    List1 = [1, 2, 3, 4],
    A = 3 ;
    List1 = [1, 2, 3, 4],
    A = 4.
    

    making use of the predicate =/2, as opposed to redefining it, which is forbidden.


    The above answers your 1). As for 2), you aren't telling us the whole truth. What you appear to have done, was to first make a query

    12 ?- List1 = [a,b,c,d].
    List1 = [a, b, c, d].
    

    which is fine and dandy; and then make another query,

    13 ?- member(a,List1).
    List1 = [a|_G2181] ;
    List1 = [_G2180, a|_G2184] ;
    List1 = [_G2180, _G2183, a|_G2187] ;
    List1 = [_G2180, _G2183, _G2186, a|_G2190] ;
    List1 = [_G2180, _G2183, _G2186, _G2189, a|_G2193] .
    

    Prolog prompt is not a REPL. We don't make definitions at it. We make queries.