On Thu, 16 Jan 1997 22:03:07 -0800, Gordon William Tisher

Quote:

>Hi there

>I'm just in the process of learning prolog, and I was wondering if y'all

>could help me out with a question I had. My apologies if this is basic.

>Here's what I'd like to do: how can I build arbitrary rules to assert

>that contain unbound variables that are named at "run time", so when the

>rule is asserted, it works correctly.

>Is this even possible?

>Thanks

>Gordon Tisher

Hello all

If I correctly understand the problem I can propose there ways solve

it. You can choose one that fit for you task better.

1. Each time you need the rule you construct it with =.. operator.

The illustration of this technique is in source code at end of

posting.

2. After fail the variables became unbound, but to process further

there must be success. In one prolog book (in Shapiro may be)

predicate 'not' was advised to use.

% This is an example from my program. (tested with Amzi)

% Note: the original predicate was more efficient because

% of 'ifthenelse' predicate. The goal was unified only once for

% each element.

%

% Each X - element of 'List', unified in goal 'XGoal',

% Then 'XGoal' tested,

% If success X is put in list 'ListGoal',

% else in list 'ListNotGoal'.

%

% split(+goal(Element, Goal), +List, -/+ListGoal, -/+ListNotGoal)

% List - initial list of elements

% ListGoal - elements of list that conforms Goal.

% ListNotGoal - all other elements.

split(G, [X|List], ListGoal, ListNotGoal ) :-

not (not (goal(X, XGoal) = G, XGoal)),

!,

ListGoal = [X | NextListGoal],

!,

split(G, List, NextListGoal, ListNotGoal).

split(G, [X|List], ListGoal, ListNotGoal ) :-

not (goal(X, XGoal) = G, XGoal),

!,

ListNotGoal = [X | NextListNotGoal],

!,

split(G, List, ListGoal, NextListNotGoal).

split(_, [], [], []).

even(X) :- 0 is (X mod 2).

odd(X) :- 1 is (X mod 2).

% example: split list of integers on even and not even integers

split_even(X, Y, Z) :- split(goal(Elem, even(Elem)), X, Y, Z).

% ready to use example

t2 :- split_even([1,2,4,2,3,4123,1234,4124412,112,112], X, Y),

write(X), nl, write(Y), nl.

3. In file util.pro that come with Amzi logic explorer there is

predicate (I have not tested this)

% newcopy/2 - Makes a copy of a term with new variables. This

% allows you to manipulate the copy without unifying the

% variables of the original.

%

newcopy(X, Y) :-

assert(tmp(X)),

retract(tmp(Y)).

Happy programming,

Mikle.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Author: Mikle Pervakov

% File: listeval.pro

% Date: 2-Jan-1997

% Task: For each element of given list calculate the number

% (which is given by the predicate EvalAtom(+Goal,

-Value)

% and return the sum of the numbers

% Tested: Amzi 16-bit Logic Explorer

% Predicates: list_eval(+List, +EvalAtom, -Value)

% list_recursive_eval(+List, +EvalAtom, -Value)

%

% Main achievment: Now it is possitble to pass predicate as

parameters.

%

% It is possible to specify different predicates for

% evaluation of list items.

% May be it will be good to give specific prefix for the

% evaluation predicate ('eval_' for example)

%

% Possible defect: predicate Goal can fail.

% I have not check what will be in this case

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Apply predicate EvalAtom/2(Item, Value) to each element of the list

% and sum the returned values

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

list_eval(List, EvalAtom, Value) :-

list_eval(List, EvalAtom, 0, Value).

list_eval([], _, Result, Result).

list_eval([X | List], EvalAtom, CurrValue, Result) :-

Goal =.. [EvalAtom, X, Value], % construction of the goal

Goal,

NextValue is CurrValue + Value,

!,

list_eval(List, EvalAtom, NextValue, Result).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Apply predicate EvalAtom/2(+Item, -Value) to each element of the

list

% and sum the returned values

% If the element is list, then we make a recursive call of

% evaluation predicate

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

list_recursive_eval(List, EvalAtom, Value) :-

list_recursive_eval(List, EvalAtom, 0, Value).

list_recursive_eval([], _, Result, Result).

list_recursive_eval([[] | List], EvalAtom, CurrValue, Result) :-

!,

list_recursive_eval(List, EvalAtom, CurrValue, Result).

list_recursive_eval([[X|Y] | List], EvalAtom, CurrValue, Result) :-

!,

list_recursive_eval([X|Y], EvalAtom, 0, XValue),

NextValue is CurrValue + XValue,

!,

list_recursive_eval(List, EvalAtom, NextValue, Result).

list_recursive_eval([X | List], EvalAtom, CurrValue, Result) :-

!,

Goal =.. [EvalAtom, X, Value], % construction of the goal

Goal,

NextValue is CurrValue + Value,

!,

list_recursive_eval(List, EvalAtom, NextValue, Result).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Examples of using of list_eval predicate %

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Evaluate the length of list (only for demonstration purposes,

% do not use this one in your programs)

length(List, Length) :- list_eval(List, eval_length, Length).

eval_length(_, 1).

% Evaluate number of elements in list and sublists, ignoring

% empty lists

flat_length(List, Length) :- list_recursive_eval(List, eval_length,

Length).

% Evaluate the sum of elements of the list, where the elements

% can be arbitrary arithmetic expressions

sum(List, N) :- list_eval(List, eval_calculate, N).

eval_calculate(X, Y) :- Y is X.

% Evaluate the sum of squares of elements of the list, where

% the element can be arbitrary arithmetic expressions

squares(List, N) :- list_eval(List, eval_square, N).

eval_square(X, Y) :- Y is X * X.

% Ready for use test examples

t1 :- list_recursive_eval([1,[[],2,3],4,5], eval_calculate, N),

write(N).

t2 :- squares( [1,2,3,4,5], N), write(N).

t3 :- sum([5+3, 18*2, 12/6], N), write(N).

t4 :- list_recursive_eval([1,[2,3],4], eval_calculate, N), write(N).