Почему неправильное выражение макроса ifelse все равно оценивается?

Я написал небольшой скрипт m4 (test.m4) для тестирования:

define(`test', `ifelse(`$#', `1', `$1', test(shift($@)))')
test(`arg1', `arg2')

и запустил его с m4 test.m4 -t test -de1. Результат был

m4trace: -1- test -> ifelse(`2', `1', `arg1', test(shift(`arg1',`arg2')))
m4trace: -2- test -> ifelse(`1', `1', `arg2', test(shift(`arg2')))
m4trace: -3- test -> ifelse(`1', `1', `', test(shift(`')))
m4trace: -4- test -> ifelse(`1', `1', `', test(shift(`')))
.
.
.

пока выполнение не было прервано из-за превышения предела рекурсии. Я задавался вопросом, почему это так, потому что на самом деле 1 и 1 должны сравниваться равными, а макрос if else должен оцениваться как `'.

Однако мне пришла в голову новаторская идея поместить [not-equal] в кавычки. отметки, поэтому макрос выглядел так:

define(`test', `ifelse(`$#', `1', `$1', `test(shift($@))')')
test(`arg1', `arg2')

и вуаля, это сработало как чудо (то есть arg2 было напечатано вместе с началом новой строки).
Вывод (с теми же параметрами вызова):

NL
m4trace: -1- test -> ifelse(`2', `1', `arg1', `test(shift(`arg1',`arg2'))')
m4trace: -1- test -> ifelse(`1', `1', `arg2', `test(shift(`arg2'))')
arg2

(NL означает "новая строка").

Мой вывод: несмотря на то, что две сравниваемые строки фактически равны, препроцессор оценивает [not-equal] тем не менее.

Есть ли у этого какая-то конкретная цель? ИМО, это просто неинтуитивно. Или я что-то упускаю?


1 -t test включает трассировку отладки для макроса test. -de добавляет определение вызванного макроса в выходные данные отладки.


person cadaniluk    schedule 23.04.2016    source источник


Ответы (1)


В то время как выражения равны (кроме кавычек), время их выполнения различается (из-за кавычек).

В первом случае макрос test выполняется ВО ВРЕМЯ макроподстановки родительского макроса test. Таким образом, вы испытываете рекурсию: тест внутри теста внутри теста и так далее.

Во втором случае выражение выполняется ПОСЛЕ. Так что у вас нет рекурсии. испытание за испытанием за испытанием.

Это поведение очень хорошо описано в руководстве.

Раздел «16.3 Другие несовместимости»:

В случаях, подобных этому, запрет макросу на сохранение собственного имени был бы бесполезным ограничением. Конечно, это оставляет пользователю GNU m4 больше шансов повеситься!

person akond    schedule 24.04.2016