looking for origin of quote on preprocessors and language design

Dear all, It's not exactly Haskell-specific, but ... I am trying to track down the origin of the proverb "the existence (or: need for) a preprocessor shows omissions in (the design of) a language." I like to think that in Haskell, we don't need preprocessors since we can manipulate programs programmatically, because they are data. In other words, a preprocessor realizes higher order functions, and you only need this if your base language is first-order. Yes, that's vastly simplified, and it does not cover all cases, what about generic programming (but this can be done via Data.Data) and alex/happy (but we have parsec) etc etc. Best regards, J.W.

Hello Johannes, Thursday, January 7, 2010, 3:32:03 PM, you wrote:
"the existence (or: need for) a preprocessor shows omissions in (the design of) a language."
yes, that's the common opinion. the same true for comments and identifiers :D shortly speaking, preprocessor is just another language on top of our one that has poor integration with main language. this partly solved by so-called syntactical preprocessors and even typeful ones (like Template Haskell) otoh there is no perfect language that is able to express any constraint. so preprocessor, applied to any given language, provides us additional level of expressiveness. so when you have some concrete problem that may be expressed in A only with preprocessor and in B as is - B is definitely better. if you typically write your programs in C++ w/o using preprocessor, and in C - with it, C++ is better. but when your programming level increases, you may go higher expressiveness of language you are using and start to need use of additional preprocessors. so if some language Pascal typically used without preprocessor and some language C - with it, it may just mean that C users are much more experienced and need more expressive power than Pascal ones -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Hello Bulat, Thursday, January 7, 2010, 4:03:07 PM, you wrote:
"the existence (or: need for) a preprocessor shows omissions in (the design of) a language."
forget to add: for language designers, analysis of typical preprocessor usage and adding analogous features to language instead is a great source of inspiration. in particular C++, D and other C descendants used it a lot -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Thu, 2010-01-07 at 13:32 +0100, Johannes Waldmann wrote:
Dear all,
It's not exactly Haskell-specific, but ... I am trying to track down the origin of the proverb
"the existence (or: need for) a preprocessor shows omissions in (the design of) a language."
I like to think that in Haskell, we don't need preprocessors since we can manipulate programs programmatically, because they are data.
In other words, a preprocessor realizes higher order functions, and you only need this if your base language is first-order.
Yes, that's vastly simplified, and it does not cover all cases, what about generic programming (but this can be done via Data.Data) and alex/happy (but we have parsec) etc etc.
Best regards, J.W.
Not quite. While I agree that "the *frequent* need for a preprocessor shows omissions in (the design of) a language." it is not necessary the case. Preprocessor may be useful if: - there is a new beatyful feature in newer version of compiler but you still want to have backward compatibility. - there are compiler or platform dependant elements. For example if you write a driver in Haskell you may want to share code as much as possible but you need to know 1) the size of registers and 2) the platform you're writing as Windows have quite different API then Linux or BSD. - You need to enable/disable features at build-time. It is not frequent at closed-source system but it is frequent on OpenSource systems. For example I might need to have minimal program for embedded system but with full feature set it likly conquer the desktops in such cases it is easier/more efficient to just write #if (defined WINDOWS && BITS >= 64) || defined ALSA ... #elseif GHC_VERSION >= 061004 #endif Regards

Maciej Piechotka schrieb:
Not quite. While I agree that "the *frequent* need for a preprocessor shows omissions in (the design of) a language." it is not necessary the case. Preprocessor may be useful if:
- there is a new beatyful feature in newer version of compiler but you still want to have backward compatibility. - there are compiler or platform dependant elements. For example if you write a driver in Haskell you may want to share code as much as possible but you need to know 1) the size of registers and 2) the platform you're writing as Windows have quite different API then Linux or BSD. - You need to enable/disable features at build-time. It is not frequent at closed-source system but it is frequent on OpenSource systems. For example I might need to have minimal program for embedded system but with full feature set it likly conquer the desktops
Many of these problems are solved by preprocessor intervention in C/C++, but there is often no need to do so. You could also write system dependent modules, where the right module for your system is included by the build system. I hope the build system does not count as a preprocessor. In Haskell it is however still no fun to support multiple versions of the base libraries, not to speak of different compilers - and their set of libraries. Unfortunately, the original question is still not answered.

On Wed, 2010-01-13 at 22:42 +0100, Henning Thielemann wrote:
Maciej Piechotka schrieb:
Not quite. While I agree that "the *frequent* need for a preprocessor shows omissions in (the design of) a language." it is not necessary the case. Preprocessor may be useful if:
- there is a new beatyful feature in newer version of compiler but you still want to have backward compatibility. - there are compiler or platform dependant elements. For example if you write a driver in Haskell you may want to share code as much as possible but you need to know 1) the size of registers and 2) the platform you're writing as Windows have quite different API then Linux or BSD. - You need to enable/disable features at build-time. It is not frequent at closed-source system but it is frequent on OpenSource systems. For example I might need to have minimal program for embedded system but with full feature set it likly conquer the desktops
Many of these problems are solved by preprocessor intervention in C/C++, but there is often no need to do so. You could also write system dependent modules, where the right module for your system is included by the build system. I hope the build system does not count as a preprocessor. In Haskell it is however still no fun to support multiple versions of the base libraries, not to speak of different compilers - and their set of libraries.
Unfortunately, the original question is still not answered.
Hmm. May I ask how to do for example something depending on POSIX or WinAPI? I am sorry but I cannot see how any of the above problems could be solved. Regards

Maciej Piechotka schrieb:
Hmm. May I ask how to do for example something depending on POSIX or WinAPI? I am sorry but I cannot see how any of the above problems could be solved.
Sure, I choose different Hs-Source-Dirs for the different platforms. Multiple Hs-Source-Dirs are merged. Example: http://hackage.haskell.org/packages/archive/sox/0.1/sox.cabal

2010/01/07 Maciej Piechotka
On Thu, 2010-01-07 at 13:32 +0100, Johannes Waldmann wrote:
Dear all,
It's not exactly Haskell-specific, but ... I am trying to track down the origin of the proverb
"the existence (or: need for) a preprocessor shows omissions in (the design of) a language."
I like to think that in Haskell, we don't need preprocessors since we can manipulate programs programmatically, because they are data.
In other words, a preprocessor realizes higher order functions, and you only need this if your base language is first-order.
Yes, that's vastly simplified, and it does not cover all cases, what about generic programming (but this can be done via Data.Data) and alex/happy (but we have parsec) etc etc.
Not quite. While I agree that "the *frequent* need for a preprocessor shows omissions in (the design of) a language." it is not necessary the case. Preprocessor may be useful if:
- there is a new beatyful feature in newer version of compiler but you still want to have backward compatibility. - there are compiler or platform dependant elements. For example if you write a driver in Haskell you may want to share code as much as possible but you need to know 1) the size of registers and 2) the platform you're writing as Windows have quite different API then Linux or BSD. - You need to enable/disable features at build-time. It is not frequent at closed-source system but it is frequent on OpenSource systems. For example I might need to have minimal program for embedded system but with full feature set it likly conquer the desktops
in such cases it is easier/more efficient to just write #if (defined WINDOWS && BITS >= 64) || defined ALSA ... #elseif GHC_VERSION >= 061004
#endif
I think that pre-processing is an inevitable result of poor support for DSLs. When looking into embedded programming for the AVR family recently, I was surprised at the degree to which programmers rely on C macros; they're the only way they can get the expressiveness they want at a price they can accept. Haskell has strong support for embedded DSLs and the abstraction penalty is low so it's not hard to get away with just writing Haskell for things. Just the same, there are some aspects of Haskell syntax that make it horribly awkward for some applications. I would like to write all my shell scripts in Haskell -- especially those scripts that drive SSH connections or multiple external processes -- but the line noise penalty is pretty high right now. Using quasi-quotation -- a kind of pre-processor -- with a more shell-like set of shortcuts might be just the right thing. It's nice to reflect on the fact that Haskell offers a lot of flexibility for program transformation but is relatively safe from the incomprehensibility that results from the use of monkey patching in Ruby or macros in general. -- Jason Dusek

It strikes me that this question may be related (perhaps distantly) to
Godel's incompleteness theorem. Anyone else see similarities here?
On Thu, Jan 7, 2010 at 7:32 AM, Johannes Waldmann
Dear all,
It's not exactly Haskell-specific, but ... I am trying to track down the origin of the proverb
"the existence (or: need for) a preprocessor shows omissions in (the design of) a language."
I like to think that in Haskell, we don't need preprocessors since we can manipulate programs programmatically, because they are data.
In other words, a preprocessor realizes higher order functions, and you only need this if your base language is first-order.
Yes, that's vastly simplified, and it does not cover all cases, what about generic programming (but this can be done via Data.Data) and alex/happy (but we have parsec) etc etc.
Best regards, J.W.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Haskell doesn't *need* preprocessors, but they sure make a lot of
things easier. There are three I use regularly (c2hs, cpphs, noweb),
and each serves a purpose which isn't directly supported by plain
Haskell:
c2hs -- Supports generating foreign function imports and wrappers
based on C header files. This is simpler and less prone to
cross-platform type errors than writing the declarations in Haskell,
which generally requires a cpp-style #if..#else..#endif preprocessor
anyway.
cpphs -- The C preprocessor, adapted to Haskell syntax. I'd like to
replace my uses of it with Template Haskell, but TH's limitation that
its splices can't be defined in the same file make it (for my
purposes) essentially useless. cpphs is text-based, which means you
can glue together pretty much anything and let the compiler verify
that it type-checks.
noweb -- True literate programming (as opposed to .lhs verbose
commenting), which allows sections of the source code to be
re-arranged arbitrarily. I suppose it's possible in theory for a
language to support this without a preprocessing step, but (to my
knowledge) not even LISP derivatives do/can.
On Thu, Jan 7, 2010 at 04:32, Johannes Waldmann
Dear all,
It's not exactly Haskell-specific, but ... I am trying to track down the origin of the proverb
"the existence (or: need for) a preprocessor shows omissions in (the design of) a language."
I like to think that in Haskell, we don't need preprocessors since we can manipulate programs programmatically, because they are data.
In other words, a preprocessor realizes higher order functions, and you only need this if your base language is first-order.
Yes, that's vastly simplified, and it does not cover all cases, what about generic programming (but this can be done via Data.Data) and alex/happy (but we have parsec) etc etc.
Best regards, J.W.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (7)
-
Bulat Ziganshin
-
Henning Thielemann
-
Jason Dusek
-
Johannes Waldmann
-
John Millikin
-
Maciej Piechotka
-
MightyByte