0

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.

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
milvala
  • 311
  • 2
  • 13
  • Can you include the source code you used and the commands you entered? Your error is obvious but what you did to do it is not. We need that to help answer your question. In other words I can put into source code just `List =2.` and get `No permission to modify static procedure (=)/2'` and say you are using `=` wrong, you need to use [is/2](http://www.swi-prolog.org/pldoc/man?predicate=is/2) but that will just have you asking us more questions. – Guy Coder Jul 27 '17 at 20:56
  • I added some more information about the approaches I used; I hope my question has become clearer. – milvala Jul 27 '17 at 21:04
  • 1
    `am I missing something very simple` are you aware that in Prolog variables are immutable? Can you include your member predicate. – Guy Coder Jul 27 '17 at 21:09
  • So, if I understand correctly, it is not possible to declare a certain list containing elements in the program, and then check by querying the program if an element is part of that list? I see that `member(a,[a,b,c,d])` returns `true`, as expected, but I fail to see why it does not work with `member(a,List1)` if I put `List1=[a,b,c,d]` in the program? – milvala Jul 27 '17 at 21:14
  • You would have to do something like `mylist([a,b,c,d]).` at the top and then when you need it, `mylist(List1), ...`. – Daniel Lyons Jul 27 '17 at 21:19
  • I do not see how this is possible then in the aforementioned YouTube link? Is that simply due to a different Prolog version then? – milvala Jul 27 '17 at 21:21
  • 1
    You do realize that you are asking multiple questions and that each one should be a separate question at SO? I will answer the few I see so far because these are all common beginner mistakes and then if there are more I might have you ask a separate question. – Guy Coder Jul 27 '17 at 21:22
  • 1
    Since @WillNess has answered I won't duplicate his work. – Guy Coder Jul 27 '17 at 21:35
  • @WillNess Don't worry, I am not here to collect points but to help others. I am glad to see milanv here and asking questions, I hope he sticks with Prolog for a while and doesn't give it up after a course on it. – Guy Coder Jul 27 '17 at 21:39
  • @GuyCoder great. It wasn't about points, but wasted effort. :) – Will Ness Jul 27 '17 at 21:40
  • @milanv: If you find an extremely closely related or even identical question, yet find the answer insufficient, please ask for clarification of that existing answer. Almost all beginners run into the same exact questions, and opening new topics for each slight variation would result in an endless stream of identical Prolog questions. – mat Jul 28 '17 at 11:17

1 Answers1

1

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.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • Thanks, this already clarifies a lot. I am still wondering, however, how would you query if a specific element is part of a certain list? I see how you can query a list to know all its elements by using a variable, but how to check for one specific element? I thought that this would be possible with `?- List1 = [1,2,3,4], member(1,List1).` but this returns false. – milvala Jul 27 '17 at 21:35
  • no, it does not return false. – Will Ness Jul 27 '17 at 21:38
  • 1
    it returns `List1 = [1, 2, 3, 4]` and waits for a keypress. I then press `;` , and *then* it says `false`. I could have pressed `.` and that would have been it. – Will Ness Jul 27 '17 at 21:39
  • @WillNess You might want to add to you answer what `?-` means and how it relates to `top-level` and source code. I see many new people not getting this until utter frustration sets in. It's so obvious to us, but to a new programmer not use to working with a `top-level` and source code and bounding back and forth it is a new world to them. – Guy Coder Jul 27 '17 at 21:41
  • @WillNess My bad, it indeed returns List1 after which I can terminate with `.` . I was just looking for a way to see if an existing list contained a specific element instead of returning all the elements in the list, but I cannot seem to find a way to. Is the predicate `member` not the right way in this case? (thanks for your patience by the way). – milvala Jul 27 '17 at 21:44
  • 1
    but it does not "return all elements in a list". That would be the result of a query `member(A, [1,2,3,4])`. Try it. Your query, `List1=[1,2,3,4], member(1,List1)` "returns" just *once*. It wants to say "yes" to you. But it also must show all *instantiations* that your query had done. So it shows you the one for `List1`. – Will Ness Jul 27 '17 at 21:46
  • Okay, thank you! I did not realize that the fact that it simply returned `List1 = [1,2,3,4]` meant that the query was successful and the digit 1 is indeed part of that list. I thought that there had to be some kind of `yes` or `true` to show for it. – milvala Jul 27 '17 at 21:49