Получить индекс аргумента термина в Прологе

Мне нужно получить индекс аргумента термина в Прологе. Predicate arg / 3, похоже, делает противоположное тому, что мне нужно:

arg(Index, Term, Value).

arg/3 завершается ошибкой, если Index является переменной, поэтому получить индекс данного значения и термина невозможно. Вы знаете какой-нибудь другой способ добиться этого (я не могу использовать внешние библиотеки)?

Пример ожидаемого поведения:

?- arg_(Index, regs(a,b,c), c).
Index = 3

person Daniel G.    schedule 10.05.2020    source источник


Ответы (1)


Не все реализации Prolog, кажется, ведут себя так, как SWI-Prolog, когда индекс является переменной. Его поведение может быть расширением стандарта.

Вот что делает GNU Prolog 1.4.5:

| ?- arg(Index,s(a,b,c,d),V).
uncaught exception: error(instantiation_error,arg/3)
| ?- arg(Index,regs(a,b,c),c).
uncaught exception: error(instantiation_error,arg/3)

Так что вам придется самостоятельно возвращаться к действительным индексам. Вы можете использовать functor/3, чтобы узнать, сколько существует аргументов:

| ?- Term = regs(a,b,c), functor(Term, _Functor, Arity).

Arity = 3
Term = regs(a,b,c)

yes

И многие прологи (включая GNU Prolog) имеют предикат between/3 для перечисления целых чисел в диапазоне:

| ?- between(1, 4, N).

N = 1 ? ;

N = 2 ? ;

N = 3 ? ;

N = 4

(1 ms) yes

Итак, в целом вы можете:

| ?- Term = regs(a,b,c), functor(Term, _Functor, Arity), between(1, Arity, Index), arg(Index, Term, Value).

Arity = 3
Index = 1
Term = regs(a,b,c)
Value = a ? ;

Arity = 3
Index = 2
Term = regs(a,b,c)
Value = b ? ;

Arity = 3
Index = 3
Term = regs(a,b,c)
Value = c

yes
person Isabelle Newbie    schedule 11.05.2020
comment
Это стандартное поведение! - person false; 11.05.2020