I have this data (the data is read from csv and it has to look like this, aka. a list of terms, rather than as plain terms defined in database):
Rows = [row('A', 150), row('B', 300), row('C', 50)].
Now I wish to filter them by value, what I wish to do is like this (directly as query):
?- findall(Row, (member(row(Name, Value), Rows), Value > 50), Filtered).
However this won't work and gives:
?- Rows = [row('A', 150), row('B', 300), row('C', 50)],
findall(Row, (member(row(Name, Value), Rows), Value > 50), Filtered).
Rows = [row('A', 150), row('B', 300), row('C', 50)],
Filtered = [_, _].
At the moment the only way to do it is to put them inside a file:
% Code.pl
% Have to provide this as a predicate
filter(Row, Rows) :-
Row = row(_, Value),
member(Row, Rows),
Value > 50.
% Also wanted to declare the following
% Neither works:
% data = [row('A', 150), row('B', 300), row('C', 50)].
% Rows = [row('A', 150), row('B', 300), row('C', 50)].
Then I can do:
?- Rows = [row('A', 150), row('B', 300), row('C', 50)], findall(Row, filter(Row, data), Filtered).
# Or alternatively, wished to do:
?- findall(Row, filter(Row, data), Filtered).
On the other hand, while drafting this example I came across this problem:
% Wanted to put data directly inside code file, then query directly
% Neither works:
% data = [row('A', 150), row('B', 300), row('C', 50)].
% Rows = [row('A', 150), row('B', 300), row('C', 50)].
I have two questions regarding syntax:
- How to put the data directly inside the code file (for the purpose of this example), as a list of terms?
- For the query, is there anyway to achieve what I wanted without having to put everything inside a script file? I.e.
Rows = [row('A', 150), row('B', 300), row('C', 50)], findall(Row, (member(row(Name, Value), Rows), Value > 50), Filtered).
Remark:
- The title of this question looks like asking exactly what I am asking but not really: Prolog, read a csv file and make a predicate. findall and I don't know why their examples look so complicated
Either as a fact:
then
rows(Rows), or as individual facts:and then a findall to gather those up.
Your findall line does not declare what
Rowis:so you could fix it as Paulo Moura answers, or you could do:
Or you could use
include/3with a test predicate:or yes, you could do that inline with a lambda: