2016-07-08 1 views
0

Я пытаюсь следующий код, где Еогеасп и string_codes работают отдельно:Foreach не работает в Прологе

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. 

но не вместе:

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. 

только первая буква печатается с этим кодом:

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

Где проблема и как ее решить?

Edit: MapList работает только один путь:

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) 

На самом деле, каждый номер должен быть список:

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

Как я могу преобразовать список номеров в список списков?

Я пытаюсь:

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

Он производит список номеров в этой модели, но по-прежнему не работает:

[[115],[116]] 
ERROR: string_codes/2: Type error: `character_code' expected, found `[116]' (a list) 
105 ?- 
+1

Используйте вместо этого "maplist/3'. – mat

+1

'string_codes/2' работает с списком чисел (коды символов). Итак, конечно, 'maplist (string_codes, L, X)' ожидает, что 'X' будет списком списков кодов символов. Можете ли вы привести пример списка номеров, который вы хотите преобразовать в список списков? Если вы хотите только преобразовать '[97, 98, 99]' в '[[97], [98], [99]]', то это легко делается с помощью 'mapllist':' code_as_list (C, [C ]), maplist (code_as_list, Lin, Lout) '. – lurker

+0

Он производит [[116, 101, 115, 116]], а не [[116], [101], [115], [116]]. Мой первоначальный список - [[1,2,3], [4,5,6] ...]. Я пытаюсь выполнить функцию выше. – rnso

ответ

3

foreach/2 фактически делает работу, как описано в documentation:

Истинно, если результат результатов верен. В отличие от forall/2, в котором работает сбойный контур, который доказывает цель для каждого решения генератора, foreach/2 создает соединение. Каждый член конъюнкции является копией цели цели, где переменные, которые он разделяет с Генератором, заполняются со значениями из соответствующего решения.

Это означает, что

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

эквивалентно конъюнкции:

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

Очевидно, что это неверно, так как X не могут быть оба списка строк кода для "abc" и "test". Здесь вы можете использовать forall/2. forall(member(S, ["abc", "test"]), string_codes(S, X)) преуспевает, но не отображает X. Вы могли бы написать:

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

Но тогда отображение X является лишь побочным эффектом и не учитываются.

Это оставляет вас с maplist/3, как @mat предложил:

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

Который делает работу в обратном направлении:

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

Здесь string_codes работает в каждом списке кодов в качестве второго аргумента: string_codes(X, [97, 98, 99]) производит "abc" и string_codes(X, [100, 101, 102]) производит "def".

+1

Нет! В документации ** не говорится о том, что цикл с ошибкой одинаковый! Фактически, он говорит: * Использование forall/2 .. является предпочтительным по сравнению с классическим циклом, зависящим от отказа ... Кроме того, непредвиденный сбой побочного эффекта приводит к сбою конструкции. Несовершенство делает очевидным, что есть проблема с кодом, в то время как сбойный цикл будет успешным с ошибочным результатом. * – false

+1

@false спасибо за это. Я исправлю свой ответ позже сегодня, когда я за компьютером. – lurker

Смежные вопросы