Hi, macros are a very useful thing, but of course if you don't use your brain, they can do a lot of harm. Here's how I see it:
The easiest way is to tell vala to emit the symbols that will then be defined when compiling the generated C code. That way vala will guard you from name conflicts and the code will be more readable. In C, the preprocessor is generally used for two things: - symbolic constants -- but real constants serve the purpose better and
As Anatol stated in another mail, this is a bad idea to use real constants, as sometimes you want not to include some code at all during compilation, basing on a constant value. But the debugcode example is, I'd call it, a weak example. The strong example would be: the library that can use different backends for some functionality. Then: #if BACKEND=UsingSomeLibrary some_library_call(foo, bar); #elsif BACKEND=UsingSomeOtherLibrary some_other_library_call(foo, baz, bar); #endif Here it's not a matter of optimization or convenience not to include both calls, and select them at runtime - you have to compile only one of them, and the other one will simply not compile (as the backend SomeLibrary does not have some_other_library_call() function). This currently can be done in Vala with some effort, we have #if, #else... but: - sometimes you want to use one switch -D that will enable and disable a lot of internal switches. For this, in C you use #ifdef ... #define .... In Vala you must rely on a build system to pass all switches. I hardly can express in my native language how I HATE such solution, so I can't write it in English too... This should be possible to enable some defines basing on values of other defines at the level of a code, not of a build system. Then one simple file with all definitions would be clear and elegant solution. - doing "const int foo = SOME_DEFINE;" would be a good thing, is it possible?
- generic constructs -- but vala does have generics, so you don't need those.
Generics do not cover all that macros can do. I can give two examples: - I need to wrap setjmp. Yes, I need to use setjmp - in debug mode my application has a testsuite, and in this testsuite I use signal()/setjmp() combination to trap SIGSEGV, just to make the testsuite not stop working after first crash. As you may know, setjmp() cannot be wrapped in a function (after the function returns the jump point would be a trash). It must be wrapped in a macro. If I wrap it in an inline function, what guarantee do I have that if the compiler reaches inlining limit it will still be inlined? It must be wrapped in a macro. - macros are not type safe. It's bad in most cases, and it's really good when you know how to use it. Suppose that I want to wrap any function. Let's say that I want to be able to call any function and make this call protected by setjmp/signal from crashing with SIGSEGV. When using macros in C, I can: #define TRAPM(a, b) ... and use it in a way: TRAPM(function1, (foo)); // calls function1(foo); TRAPM(function2, (bar, baz)); // calls function2(bar, baz); Quite more powerful than anything you can do in a high-level language. Of course _defining_ macros at the preprocessor level in a modern language would be unnecessary conservatism, I think that maybe seeing syntax like this will be a good thing: class Foo : GLib.Object { public macro foo(a, b){ ... } public static macro bar(.... } And have generated vapi files contain public macros so that they can be used in a foreign code. What do you think about these ideas? best regards, AW.
Even in C++ you usually avoid the preprocessor for most things, because preprocessor symbols cannot be scoped. Which is doubly so applicable to vala. -- Jan 'Bulb' Hudec <bulb ucw cz> _______________________________________________ vala-list mailing list vala-list gnome org http://mail.gnome.org/mailman/listinfo/vala-list
-- Mój klucz publiczny o identyfikatorze 1024D/E12C5A4C znajduje się na serwerze hkp://keys.gnupg.net My public key with signature 1024D/E12C5A4C is on the server hkp://keys.gnupg.net
Attachment:
signature.asc
Description: PGP signature