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