Say you have recipes in prolog saved as
step(meal name, stepnumber, stepexaplanation, ingredients (list) , utensils).
So for every meal name
you have multiple steps with all the explanations to make the meal. How would you then make a function that calls getStepText(X,Y,Z).
? So if you ask:
?- getStepText('pancakes',2,Y).
It will return the text of the second step for the meal pancakes.
step('pancakes', 1, 'mix butter and sugar in a bowl', [butter, sugar], [bowl]).
step('pancakes', 2, 'add eggs', [eggs], []).
step('pancakes', 3, 'mix flour and bakingpowder', [flour, baking_powder], []).
getStepText(Dish,Num,Text):-
step(Dish, Num, Text, _, _).
?- getStepText('pancakes',2,Y).
Y = 'add eggs' ;
false.
If you are using SWI Prolog you can use the inbuild predicate findall/3
to find all of your steps. Don't forget to sort them.
getSteps(X,S):-
findall(N,step(X,N,_,_,_),Bag),
sort(Bag,S).
?- getSteps('pancakes',Y).
Y = [1, 2, 3] ;
false.
If you don't want to use findall/3
you can define a helper predicate getSteps/3
. This predicate assumes all steps are incremental and start with 1.
getSteps(X,S):-
getSteps(X,S,1).
getSteps(X, [], N):-
\+ step(X, N, _, _, _).
getSteps(X, [N|T], N):-
step(X, N, _, _, _),
NN is N+1,
getSteps(X, T, NN).
?- getSteps('pancakes',Y).
Y = [1, 2, 3] ;
false.
Explanation: you basically run a counter N
from 1 (set when calling) until you can't find any step with the current number N
. The first rule tests for the end: if you don't have a step for the current N
"return" the empty list []
.
Otherwise when you find a step with the number N
, try to find the steplist T
for the next value NN
(which is N+1
) and - once found - put N
on top of the list T
.