2016-04-23 2 views
2

Я написал небольшой скрипт (m4 test.m4) для целей тестирования:Почему «неправильное» выражение макроса ifelse оценивается в любом случае?

define(`test', `ifelse(`$#', `1', `$1', test(shift([email protected])))') 
test(`arg1', `arg2') 

и побежал с m4 test.m4 -t test -de . Выходной сигнал был

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([email protected]))')') 
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].

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


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

ответ

3

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

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

Второй случай делает выражение выполненным ПОСЛЕ УСТРОЙСТВА. Таким образом, у вас нет рекурсии. испытание после испытания после испытания.

This behaviour is very well described in the manual.

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

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

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