views:

157

answers:

3

Hi, I'm trying to format a result from a program but getting an hard time.

I wanted to give something like this as result:

Res = do(paint(x) do(clean(a), do(repair(b) , initialState)))

basically, I want to concatenate successive terms to initialState atom but, it doesn't work with atom_concat since the other terms to concatenate aren't atoms and also I wanted to add the ) everytime I pass through the "do" function.

So it would be something like: Res = initialState.

When do function was called, I would have a function like

concatenateTerm(Pred, Res, Res).

Pred beeing repair(b) for instance and obtain the result: res = do(repair(b), initialState).

Is this possible to be done?

Thanks

A: 

@d0pe, there is no results in prolog (they exists in Mercury and Erlang, I guess) there is only named values which specified/unified in head and probably unified later in body. Doing Temp = Res, concatenateTerm (Pred,Temp, Res) will fail in most cases because Temp = Res, Res = do(Pred, Temp) will produce infinitely recursive term do(Pred, do(Pred, do(Pred, ...))) (when appropriate extension is available). I guess that this isn't what you want.
But now I understand that you want to modify Res - that's incorrect understanding of Prolog. There is no variables, you should use next approach Res0 = initialState, Res1 = do(repair(b), Res0), Res2 = do(clean(a), Res1), Res3 = do(paint(x), Res2).

Probably your rule will look something like (see examples of monkey+bananna in prolog):

solve(FinalState, finish, FinalState). % our initial state is our goal

solve(InitState, do(Action, Future), FinalState):-
  action(InitState, Action, NewState),
  solve(NewState, Future, FinalState).
ony
I believe @d0pe just asked how to _construct a term_ to _format some output_... why are you (rather confusingly) talking about infinitely recursive terms and modifying bound variables?
sharky
@rati, and I did respoinded how to *construct a term*. recursive terms and modifying bound variables is mentioned because of "So it would be something like:" and `Res = initialState, concatenateTerm(Pred, Res, Res), Pred = repair(b)` and expecting `Res = do(repair(b), initialState)` which is looks like @d0pe thing that concatenateTerm should take "first" `Res` concatenate `repair(b)` to it and return it as "second" `Res`.
ony
+1  A: 

If I understand you correctly you need to do something like:

Res0 = initialState,
do(repair(b), Res0, Res1),
do(clean(a), Res1, Res2),
do(paint(x), Res2, Res3),

where you final result is in Res3. Remember prolog procedures don't "return" anything and input and output values must be passed through arguments.

Why do you want to concatenate successive terms to the atom initialState? Thi is not the prolog way. It would be much more natural in prolog to build a structure which is modified each time.

rvirding
As well as prolog doesn't "return" it also doesn't "modify" (except special cases related with dynamic predicates, but replacing some predicates is also a bad approach). The only thing that can look as "modifying" (but actually is not) is using partially-bound variables, parts of which is bound at some steps to probably another partially-bound variable (ex. `Res3 = do(paint(x), Res2), Res2 = do(clean(a), Res1), Res1 = do(repair(b), Res0), Res0 = initialState` or `member((red=blue),X), member((blue=red),X)`). But anyway in your example you have no *concatenation* of terms, only call to `do/3`
ony
+1  A: 

I agree with @rvirding in that you may just need to construct a PROLOG term as your result, instead of trying to construct an atom. Even if you attempt the latter (which is indeed possible), you can usually convert from atoms to terms and back again using utility functions (such as atom_to_term/3 or term_to_atom/2 in SWI-PROLOG), if need be.

Anyway, a simple predicate to take a whole list of your 'state' terms and output such a term as you've described earlier could look like this:

build_do_term([X,Y], do(X,Y)) :- !.
build_do_term([X|Xs], do(X,Rem)) :-
    build_do_term(Xs, Rem).

Calling this predicate on the state terms (of which there must be at least two):

?- build_do_term([paint(x), clean(a), repair(b), initialState], Rem).
Rem = do(paint(x), do(clean(a), do(repair(b), initialState))).

...which reflects the behaviour you've described as being after. If you don't want to build the term all at once from a list, you can still use the do/2 term construction method as used in build_do_term/2 above in your own code to construct the appropriate do/2 term as necessary.

sharky
@rati, how did you guessed that @d0pe already *concatenated* terms in list `[paint(x) | [clean(a) | [... |[]]..]` which is exactly the same problem as *concatenation* with `do/2`?
ony
I wasn't guessing or assuming anything about the code @d0pe is working with. The purpose of using the list structure here as input to `build_do_term/2` is to illustrate, in a simple manner, how a PROLOG predicate could be implemented to construct the (supposedly) necessary `do/2` term, as described, as a guide, since d0pe wanted something like `concatenateTerm/3`. I think this is clear from my last statement in the post... :-\
sharky