1

I am trying following code, where foreach and string_codes are working separately:

7 ?- string_codes("acid", D).
D = [97, 99, 105, 100].

8 ?- string_codes(S,  [116, 101, 115, 116]).
S = "test".


15 ?- foreach(member(S, ["test", "acid"]), writeln(S) ).
test
acid
true.

But not together:

14 ?- foreach(member(S, ["test", "acid"]), string_codes(S, X) ).
false.

17 ?- foreach(member(X,[[116, 101, 115, 116], [97, 99, 105, 100]]), string_codes(S, X)).
false.

Only first letter is printed with this code:

77 ?- foreach(member(X, [[97], [98],[99]]), (string_codes(S,X), writeln(S))).
a

Where is the problem and how can it be solved?

Edit: maplist works only one way:

74 ?- maplist(string_codes, ["test","acid"], L).
L = [[116, 101, 115, 116], [97, 99, 105, 100]].

73 ?- maplist(string_codes, L, [97, 98,99]).
ERROR: string_codes/2: Type error: `list' expected, found `97' (an integer)

Actually, each number should be a list:

75 ?- maplist(string_codes, L, [[97], [98],[99]]).
L = ["a", "b", "c"].

How can I convert a list of numbers into a list of lists?

I am trying:

tolistlist([H|T],[[H]|Outl]):-
    writeln([[H]]),
    tolistlist(T,Outl).
tolistlist([],[]).

It does produce list of numbers in that pattern but still does not work:

[[115],[116]]
ERROR: string_codes/2: Type error: `character_code' expected, found `[116]' (a list)
105 ?- 
rnso
  • 23,686
  • 25
  • 112
  • 234
  • 1
    Use `maplist/3` instead. – mat Jul 08 '16 at 11:56
  • 1
    `string_codes/2` operates on a list of numbers (character codes). So, of course, `maplist(string_codes, L, X)` expects `X` to be a list of character code lists. Can you give an example of the kind of list of numbers you want to convert to a list of lists? If all you want is to convert `[97, 98, 99]` to `[[97], [98], [99]]` then that is easily itself done with `mapllist`: `code_as_list(C, [C]), maplist(code_as_list, Lin, Lout)`. – lurker Jul 08 '16 at 12:19
  • It is producing [[116,101,115,116]] and not [[116],[101],[115], [116]]. My original list is [ [1,2,3], [4,5,6] ... ]. I am trying a function above. – rnso Jul 08 '16 at 12:24
  • 1
    What is producing that? It's unclear what it is you are trying to do. What are you given, and what do you want to get. `L = [[1,2,3], [4,5,6], ...]` is not a valid set of character codes. But if they were, you would just use, `maplist(string_codes, Strings, L)`. – lurker Jul 08 '16 at 13:06
  • I want to get strings from codes: maplist(string_codes, S, Codelist). – rnso Jul 08 '16 at 13:13
  • Yes, it works. Please see here: http://stackoverflow.com/questions/38261865/longest-common-substring-using-recursion-and-dp – rnso Jul 08 '16 at 13:31

1 Answers1

3

foreach/2 actually does work as described in the documentation:

True if conjunction of results is true. Unlike forall/2, which runs a failure-driven loop that proves Goal for each solution of Generator, foreach/2 creates a conjunction. Each member of the conjunction is a copy of Goal, where the variables it shares with Generator are filled with the values from the corresponding solution.

This means that

foreach(member(S, ["abc", "test"]), string_codes(S, X))

is equivalent to the conjunction:

string_codes("abc", X), string_codes("test", X)

Clearly, this is false since X cannot both be the string code list for "abc" and "test". You could use forall/2 here. forall(member(S, ["abc", "test"]), string_codes(S, X)) succeeds, but won't display X. You could write it as:

forall(member(S, ["abc", "test"]), (string_codes(S, X), writeln(X))).

But then the display of X is just a side-effect and not captured.

This leaves you with maplist/3 as @mat suggested:

?- maplist(string_codes, ["abc", "def"], ListOfCodeLists)
ListOfCodeLists = [[97, 98, 99], [100, 101, 102]].

Which does work in reverse:

?- maplist(string_codes, ListOfStrings, [[97, 98, 99], [100, 101, 102]]).
ListOfStrings = ["abc", "def"].

Here, string_codes is operating on each list of codes as its second argument: string_codes(X, [97, 98, 99]) produces "abc" and string_codes(X, [100, 101, 102]) produces "def".

lurker
  • 56,987
  • 9
  • 69
  • 103
  • 1
    No! The documentation **does not** say that the failure driven loop is the same! In fact, it says: *Using forall/2 .. is preferred over the classical failure driven loop ... Also, unexpected failure of the side effect causes the construct to fail. Failure makes it evident that there is an issue with the code, while a failure driven loop would succeed with an erroneous result.* – false Jul 08 '16 at 15:22
  • 1
    @false thanks for catching that. I'll correct my answer later today when I'm at a computer. – lurker Jul 08 '16 at 15:52