Можно ли жить без препроцессор директив условной компиляции (вроде #if)?
Предположим, что язык о котором идет речь снабжен мощной микросистемой работающей на синтаксическом уровне (т.е. макросами Немерла, или если хотите Лиспа).
Другими словами в языке возможна условная компиляция на основе применения атрибутов и специальных макросов.
Разница с перпроцессорными аналогами заключается только в том, что макросы не могут "рвать" синтаксис. Например, мы не сможем сделать нечто вроде:
#if XXX
class
#else
struct
#endif
MyType
{
}
Но сможет сделать нечто вроде:
[if(XXX)]
class MyType
{
}
[if(!XXX)]
struct MyType
{
}
Откровенно говоря мне всегда не нравился препроцессор. Вот думаю реально ли отказаться от него полностью?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
N>>В Java нет препроцессора, так что, видимо, можно
VD>К сожалению я Яву практически (для реальной работы) не использовал. Интересно не вызывает ли это негативных эмоций у программистов?
Про массовые возмущения не слышал. В Scala его тоже нет, хотя она разрабатывалась с учётом опыта Java.
Мое личное мнение: препроцессор — это зло, даже в такой ограниченной форме, как в C#. Он способствует тому, чтобы смешивались разные уровни абстракции. Кому это очень надо, пусть прикручивает специализированные текстовые препроцессоры/шаблонизаторы поверх компилятора на свой страх и риск. Правила языка ради этого усложнять не стоит.
Здравствуйте, VladD2, Вы писали:
VD>Можно ли жить без препроцессор директив условной компиляции (вроде #if)?
Если макросами (а, например, как? — можешь показать?) можно будет реализовать функционал ConditionalAttribute (или предложить достойную или даже лучшую альтернативу), то жить ещё как можно будет.
Иногда, конечно, хочется воспользоваться (и иногда пользуется), но это всё от лукавого и было бы лучше капельку подумать и переписать без #if-ов, так что писать код будет лучше.
Самое полезное, что есть в таких дериктивах — #if 0, но это тоже так или иначе решаемо.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, VladD2, Вы писали:
VD>К сожалению я Яву практически (для реальной работы) не использовал. Интересно не вызывает ли это негативных эмоций у программистов?
Лично у меня отсутствие препроцессора вызывает только положительные эмоции. Так как стимулирует иметь нормальную архитектуру, а не городить костыли. Прекрасно препроцессор заменяет выделение абстрактного универсального слоя, а реализация уже под конкретные нужды. В том числе и на этапе сборки, когда в билд попадает только заточенный под конкретные нужды код.
На деле, условную компиляцию можно эмулировать, кстати. Обычными условиями, в качестве условия — какой то параметр (константа или значение конфига). Вот только плохая это практика.
Здравствуйте, elmal, Вы писали:
E>Лично у меня отсутствие препроцессора вызывает только положительные эмоции. Так как стимулирует иметь нормальную архитектуру, а не городить костыли.
Согласен. Потому тему и создал. Просто я уже сто раз сталкивался с решениями которые мне нравятся и кажутся очевидными, но не принимаются большинством сообщества. А языки ведь они не для себя лично проектируются (точнее не только для себя).
E>На деле, условную компиляцию можно эмулировать, кстати. Обычными условиями, в качестве условия — какой то параметр (константа или значение конфига). Вот только плохая это практика.
Ага. Но есть одно "но". Все это возможно только при условии, что условия не разрывают синтаксис (как я привел в примере с классом и структурой).
Вот, собственно, и интересно. Насколько народ считает необходимым такие вот разрывающие синтаксис условия? Потому как если они не нужны, то от чистого препроцессора можно легко отказаться.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, _FRED_, Вы писали:
_FR>Если макросами (а, например, как? — можешь показать?) можно будет реализовать функционал ConditionalAttribute (или предложить достойную или даже лучшую альтернативу), то жить ещё как можно будет.
ConditionalAttribute само собой разуется. Но можно и большее сделать. Скажем если сделать синтаксический макрос вида:
macro CompileIf(condition, expression, elseExpression = <[ () ]>) // по умолчанию возвращаем void-литерал, т.е. "ничего"
{
if (EvalEnvVar(condition))
expression
else
elseExpression
}
Тогда в коде мы можем писать нечто вроде:
CompileIf(DEBUG, DebugStaff());
или
CompileIf(DEBUG, DebugStaff(), ReleaseStaff());
Естественно, что этому делу можно будет даже синтаксис приделать (даже такой: #if ... #else ... #endif).
_FR>Иногда, конечно, хочется воспользоваться (и иногда пользуется), но это всё от лукавого и было бы лучше капельку подумать и переписать без #if-ов, так что писать код будет лучше.
_FR>Самое полезное, что есть в таких дериктивах — #if 0, но это тоже так или иначе решаемо.
Вот-вот. Потому я и думаю не было бы разумнее отказаться от тестуальных #if в пользу синтаксических?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
_FR>>Если макросами (а, например, как? — можешь показать?) можно будет реализовать функционал ConditionalAttribute (или предложить достойную или даже лучшую альтернативу), то жить ещё как можно будет.
VD>ConditionalAttribute само собой разуется. Но можно и большее сделать. Скажем если сделать синтаксический макрос вида:
… VD>Тогда в коде мы можем писать нечто вроде:
VD>CompileIf(DEBUG, DebugStaff());
А "DEBUG" Можно будет брать из настроек проекта (то есть параметров компилятора)? Собсно это и интересовало: возможность из макроса узнать, с какими параметрами был запущен компилятор, в частности, был ли указал символ DEBUG.
_FR>>Иногда, конечно, хочется воспользоваться (и иногда пользуется), но это всё от лукавого и было бы лучше капельку подумать и переписать без #if-ов, так что писать код будет лучше. _FR>>Самое полезное, что есть в таких дериктивах — #if 0, но это тоже так или иначе решаемо.
VD>Вот-вот. Потому я и думаю не было бы разумнее отказаться от тестуальных #if в пользу синтаксических?
Было бы. Если не страшит то, что у некоторых программистов может случиться "ломка" из-за отсутствия #if Но это я шучу: конечно, если в самом языке нет ничего такого, для чего был бы необходим #if то от него надо избавляться.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>А "DEBUG" Можно будет брать из настроек проекта (то есть параметров компилятора)? Собсно это и интересовало: возможность из макроса узнать, с какими параметрами был запущен компилятор, в частности, был ли указал символ DEBUG.
Естественно. Доступны все опции компиляции. Например, так можно узнать объявлен ли символ DEBUG:
when (typer.Manager.Options.IsConstantDefined("DEBUG"))
...
Так же можно добавить свои символы или удалить имеющиеся.
_FR>Было бы. Если не страшит то, что у некоторых программистов может случиться "ломка" из-за отсутствия #if Но это я шучу: конечно, если в самом языке нет ничего такого, для чего был бы необходим #if то от него надо избавляться.
Вот мне и интересно насколько народу дорги текстуальные макросы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Можно ли жить без препроцессор директив условной компиляции (вроде #if)?
Если мне не изменяет склероз, макросы в C/C++ применяются для двух вещей:
1. Платформозависимый код.
2. Рефлекшн (ASSERT/VERIFY: __FILE__, __LINE__, __ЖОПА__)
Соответственно, если у нас бейсик — платформонезависимый и со встроенным рефлекшн — то макросы нам как бы нафиг не нужны.
Здравствуйте, VladD2, Вы писали:
_FR>>Было бы. Если не страшит то, что у некоторых программистов может случиться "ломка" из-за отсутствия #if Но это я шучу: конечно, если в самом языке нет ничего такого, для чего был бы необходим #if то от него надо избавляться.
VD>Вот мне и интересно насколько народу дорги текстуальные макросы.
Тем, кому дороги, можно посоветовать использовать их на полную (сишную) катушку: но перед компиляцией ncc прогонять их через cl
Help will always be given at Hogwarts to those who ask for it.
Конкретно в этом случае можно обойтись и синтаксическими макрами с метаатрибутами. Синтаксис они ведь не рвут. Меня больше интресует более хардкорное применение более близкое к стилю С++.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2 wrote:
> N>В Java нет препроцессора, так что, видимо, можно
Да в Java вообще ничего нет. Можно конечно так жить, но зачем ?
лучше уж не использовать Java.
> К сожалению я Яву практически (для реальной работы) не использовал. > Интересно не вызывает ли это негативных эмоций у программистов?
Вызывает конечно. Из-за недостатка языка нужно компенсировать эти
недостатки на уровне архитектуры приложения, усложняя её.
ПО сабжу:
КОнечно же препроцессор никому не нужен, если есть макросы a-la лисповых.
В C/C++ просто нет другого, поэтому выбростить текущий не реально.
Здравствуйте, VladD2, Вы писали:
VD>Конкретно в этом случае можно обойтись и синтаксическими макрами с метаатрибутами. Синтаксис они ведь не рвут. Меня больше интресует более хардкорное применение более близкое к стилю С++.
В том же D отсутствие препроцессора ничем ни мешает, так как есть адекватные замены практически на все варианты использования.
Здравствуйте, VladD2, Вы писали:
VD>Откровенно говоря мне всегда не нравился препроцессор. Вот думаю реально ли отказаться от него полностью?
Да, главное чтобы интеграция со студией работала, там t4 есть.
Здравствуйте, VladD2, Вы писали:
VD>Согласен. Потому тему и создал. Просто я уже сто раз сталкивался с решениями которые мне нравятся и кажутся очевидными, но не принимаются большинством сообщества. А языки ведь они не для себя лично проектируются (точнее не только для себя).
Очень похоже, что ты только для себя + таких же гиков и проектируешь.
Здравствуйте, VladD2, Вы писали:
VD>Можно ли жить без препроцессор директив условной компиляции (вроде #if)?
Как известно, сами авторы языка С сделали себе диалект без #if
...
Another restriction is that the C compilers accept only a subset of the preprocessor directives required by ANSI. The main omission is #if, since we believe it is never necessary and often abused. Also, its effect is better achieved by other means. For instance, an #if used to toggle a feature at compile time can be written as a regular if statement, relying on compile-time constant folding and dead code elimination to discard object code.
... Plan 9 from Bell Labs
N>Мое личное мнение: препроцессор — это зло, даже в такой ограниченной форме, как в C#. Он способствует тому, чтобы смешивались разные уровни абстракции.
Разве? Препроцессор нужен не для смешения абстракций, а для их упрощения или уменьшения их кол-ва. Например, в отсутствии препроцессора, в том месте, где нужно всего лишь подставить пару разных строк для серверной и клиентской версии некоего софта, потребуется городить дополнительный интерфейс. А это решение очень спорно ввиду того, что в готовой программе интерфейс фактически используется не по назначению, ведь он не служит для развязки/абстрагирования, коль речь идет о взаимоисключающих подстановках уровня compile-time, но вовсе не run-time. Т.е. раз в готовой программе будет гарантированно единственная реализация некоего интерфейса, то его применение как способа решения проблемы является инженерным ляпом при наличии других ср-в, и оправданно лишь в случае отсутствия тех самых других ср-в, например как в Джава.
>Кому это очень надо, пусть прикручивает специализированные текстовые препроцессоры/шаблонизаторы поверх компилятора на свой страх и риск. Правила языка ради этого усложнять не стоит.
Дык, препроцессор и так должен поверх языка вызываться. То, что препроцессор может быть встроен в компилятор, вовсе не означает, что он должен быть встроен в язык (вернее, в его грамматику). Не надо смешивать уровни абстракций.
Здравствуйте, vdimas, Вы писали:
V>Разве? Препроцессор нужен не для смешения абстракций, а для их упрощения или уменьшения их кол-ва. Например, в отсутствии препроцессора, в том месте, где нужно всего лишь подставить пару разных строк для серверной и клиентской версии некоего софта, потребуется городить дополнительный интерфейс. А это решение очень спорно ввиду того, что в готовой программе интерфейс фактически используется не по назначению, ведь он не служит для развязки/абстрагирования, коль речь идет о взаимоисключающих подстановках уровня compile-time, но вовсе не run-time. Т.е. раз в готовой программе будет гарантированно единственная реализация некоего интерфейса, то его применение как способа решения проблемы является инженерным ляпом при наличии других ср-в, и оправданно лишь в случае отсутствия тех самых других ср-в, например как в Джава.
Для этого препроцессор точно не нужен. Достаточно чтобы в языке можно было явно выделять compile time, более менее нормально это сделано в D.
Например для того что ты выше описал хватает static if из D.
Здравствуйте, FR, Вы писали:
FR>Для этого препроцессор точно не нужен. Достаточно чтобы в языке можно было явно выделять compile time, более менее нормально это сделано в D. FR>Например для того что ты выше описал хватает static if из D.
В boost тоже подобного полно. Но я не понял, как натравить в D компилятор на один и тот же исходник без его изменения, и только за счет ключей при его вызове получить разницу в static if?
Здравствуйте, VladD2, Вы писали:
VD>Конкретно в этом случае можно обойтись и синтаксическими макрами с метаатрибутами. Синтаксис они ведь не рвут. Меня больше интресует более хардкорное применение более близкое к стилю С++.
Да ладно, макросы — не самоцель, а ср-во настроивать генерацию кода без изменения исходников. Нужно просто такое ср-во, которое позволит задавать некие условия как ключи компиляции, и этими ключами управлять кодогенерацией с прикладной точки зрения. А какие эти ср-ва будут, текстуальные или синтаксические — это вообще к делу слабо относится. Из важного в этом вопросе лишь вменяемый синтаксис использования всей этой кухни, потому как здесь: http://www.rsdn.ru/forum/philosophy/3847820.1.aspx
Здравствуйте, vdimas, Вы писали:
V>В boost тоже подобного полно. Но я не понял, как натравить в D компилятор на один и тот же исходник без его изменения, и только за счет ключей при его вызове получить разницу в static if?
В бусте нет ничего хотя бы близкого по возможностям static if.
Чтобы компилировать исходник без изменений в D есть version http://www.digitalmars.com/d/2.0/version.html
практически аналог #ifdef.
Здравствуйте, vdimas, Вы писали:
V>Да ладно, макросы — не самоцель, а ср-во настроивать генерацию кода без изменения исходников. Нужно просто такое ср-во, которое позволит задавать некие условия как ключи компиляции, и этими ключами управлять кодогенерацией с прикладной точки зрения. А какие эти ср-ва будут, текстуальные или синтаксические — это вообще к делу слабо относится. Из важного в этом вопросе лишь вменяемый синтаксис использования всей этой кухни, потому как здесь: http://www.rsdn.ru/forum/philosophy/3847820.1.aspx
Здравствуйте, VladD2, Вы писали:
VD>Откровенно говоря мне всегда не нравился препроцессор. Вот думаю реально ли отказаться от него полностью?
А не может это понадобиться тому, кто захочет писать код, который можно будет компилировать разными компиляторами, или разными версиями одного компилятора с отличающейся поддержкой фич? Тут ведь может возникнуть необходимость и в "разрывании синтаксиса" да и ориентироваться на возможности самой ограниченной версии.
#if N2
//используем фичу новой версии языка.#elif//делаем по-старому.#endif
Но, конечно, поддержка деректив препроцессора именно в компиляторе не нужна — можно же всегда отдельным препроцессором воспользоваться.
... << RSDN@Home 1.2.0 alpha 4 rev. 1446>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Здравствуйте, FR, Вы писали:
V>>Да ладно, макросы — не самоцель, а ср-во настроивать генерацию кода без изменения исходников. Нужно просто такое ср-во, которое позволит задавать некие условия как ключи компиляции, и этими ключами управлять кодогенерацией с прикладной точки зрения. А какие эти ср-ва будут, текстуальные или синтаксические — это вообще к делу слабо относится. Из важного в этом вопросе лишь вменяемый синтаксис использования всей этой кухни, потому как здесь: http://www.rsdn.ru/forum/philosophy/3847820.1.aspx