Один очень чистый способ сделать это - использовать DCG, например the answer from CapelliC. Как и он, используя изящную library(pio)
Ульриха Neumerkel, например as found in SWI-Prolog, вы могли бы объединить DCG и phrase_from_file/2
для следующего решения:
:- use_module(library(pio)).
... --> []|[_], ... .
file_pattern_pos(File, Pattern, Pos) :-
phrase_from_file((...,
lazy_list_character_count(Pos),
Pattern,
...
),
File).
Это взято дословно из примера кода в documentation to phrase_from_file/2
, просто добавил lazy_list_character_count//1
. В отличие от другого ответа DCG, он генерирует все решения при обратном отслеживании. Так с этим файлом:
$ cat banana.txt
banana
Antananarivo
вы получаете от верхнего уровня:
?- file_pattern_pos("banana.txt", "ana", Pos).
Pos = 1 ;
Pos = 3 ;
Pos = 10 ;
Pos = 12 ;
false.
Чтобы составить список всех позиций одного символа:
?- bagof(P, file_pattern_pos("banana.txt", "a", P), Ps).
Ps = [1, 3, 5, 10, 12, 14].
Это решение хорошо , потому что к нему легко добраться, просто просмотрев пример кода из документации до phrase_from_file/2
.Однако в приведенных ниже замечаниях были указаны две проблемы:
- Вопрос об эффективности;
- Использование
lazy_list_character_count//1
означает, что вы не можете использовать это с помощью phrase/2
.
Вопрос эффективности может быть решена, как указано в комментарии:
... --> [].
... --> [_], ... .
Другой проблемой является более серьезным. В конце концов, возможно, необходимо подсчитать количество потребляемых символов. Например:
span(N) --> span_(0, N).
span_(N, N) --> [].
span_(N0, N) --> [_],
{ N1 is N0 + 1
},
span_(N1, N).
Теперь мы можем написать, с верхнего уровня:
?- phrase_from_file((span(Pos), "ana", ...), "banana.txt").
Pos = 1 ;
Pos = 3 ;
Pos = 10 ;
Pos = 12 ;
false.
Или, используя phrase/2
:
?- phrase((span(P), "ana", ...), "banana").
P = 1 ;
P = 3 ;
false.
Операция 'is/2' требует, чтобы все переменные, которые вы вычисляете справа, были созданы. В этом случае 'POS1' не имеет значения, поэтому Prolog не может вычислить' POS1 + 1'. – lurker
Я просто переместил это утверждение на последнее, и он сработал: POS - POS1 +1 спасибо alot <3 любая идея, как использовать, чтобы функция взяла подстроку вместо 1 символа tho? –
Прежде чем что-либо предпринять: удалите предупреждения, которые вы определенно получаете! – false