The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Metaprogramming in Heron - Revisited in a big way

I can scarcely believe it, but after having my ass kicked around in the JoS forums a while back I consequentially made some changes to Heron. I thought I had become too obstinate to properly respond to feedback. Generally the consensus was that I was making metaprogramming a needlessly verbose and unpleasant task. Since then I have made some substantial improvements. Thanks to everyone who contributed to the earlier discussions, and for those interested the new documentation is online at .
Christopher Diggins Send private email
Wednesday, September 22, 2004
Tee hee..  Glad to see that I'm doing a good job as arch-nemesis. ;)

I'm not entirely sure if I understand the new way things are...  The syntax still seems to be a smidge sticky.  I'm wondering if it would be possible to add a little more compiler intelligence to the mix and, when you are in a clearly metaprogrammed block, not require you to actually use the metaprogramming operators, but simply write straight code.

I'm almost thinking that you could simplify all of this by just having a "meta-block" that replaces some of the constructions, kinda like ASPs do.  Like, you'd surround a meta-block with a #< and ># brace instead of all of the syntax, keep the $ to access a meta-variable, maybe twist the meta-variable and meta-function syntax to exactly match regular variable and function syntax, and then your meta_if <> thingie can just die and be replaced by the much richer set of regular C/C++ conditionals.  The way that metaprogramming looks right now, is the boost library, with a few bits of compiler-level support.  This way, it would start to look like a natural part of the language.

Alternatively, you could keep the meta-function syntax seperate so it becomes a "macro" like construction that exists in the scope of the caller, and then allow some set of the regular procedures to be executed at compile time.  The only problem here is that it may lead to trouble if, say, the function you are trying to metaprogram calls a database.

OTOH, that can be useful if done carefully.  Consider a database abstraction layer that, upon compile time, checks to see if the fields you are using in the code are available in the database.  Or, going the other direction, a database abstraction layer that, upon compile time, checks the database and automatically generates a class to represent a row in a table that's entirely typesafe.
Flamebait Sr.
Wednesday, September 22, 2004
You are definitely doing a good job as an "arch-nemesis" ( which would be a welcome persona for by the way )

I am very leary about compilers doing too much guess-work for a programmer. It can lead to bad coding practices and difficult to maintain code.

The #< x + y ># idea I can understand would be nice to have from the standpoint of a single programmer, but would cause problems in the long run with maintainability, because it confuse compile time operations with run-time operations. Compile time addition is predefined by the system, whereas run-time addition is defined by the programmer.
Christopher Diggins Send private email
Thursday, September 23, 2004
"The #< x + y ># idea I can understand would be nice to have from the standpoint of a single programmer, but would cause problems in the long run with maintainability, because it confuse compile time operations with run-time operations."

I'm not sure that confusing compile-time operations with run-time operations is a big deal.  I've been following the Heron discussion and have been meaning to pipe in on the metaprogramming syntax (although Flamebait Sr. has been doing a great job).

I have to agree with Flamebait on the syntax -- it seems to add an unnecessary layer of things to remember for very little benefit.  As it stands now, I find it an inelegant solution.

Unlike in C++, you are trying very hard to separate run-time from compile-time.  I don't see any benefit to that separation!

In C++, if I write:

a = 5 + 6

It doesn't compile that into (pseudo x86 ASM):


It compiles that into:

MOV AX, 11

It performs that addition operation at compile-time because, well, it can.  And there is nothing incorrect about it.  I'd actually like a language compiler to go a step further and do the same thing with expressions like:

a = "Hello" + chr(32) + "World"

That "chr(32)" function is entirely deterministic.  It would be nice for the compiler to notice this fact and execute that at compile time saving me a costly step.  Such a feature could completely eliminate lookup tables and other constructs common in some C/C++ programs.  Who knows how much you could optimize away.

But that's just an argument for mixing run-time and compile-time.  As for metaprogramming syntax, I think the more straightforward the better.  Right now you have a language embedded in a language -- which, like the C/C++ precompiler, is very ugly.

You might want to look at the Dylan language for inspiration.  Most of the language constructs in Dylan are written in the Dylan macro language (so if, select, etc, are all macros).

Here is the macro for the while loop:

define macro while
  { while (?test:expression) ?:body end }
  => { local method loop ()
                if (?test)
                end if;
              end method;
        loop() }
Almost Anonymous Send private email
Monday, September 27, 2004
The other thing to remember about metaprogramming is that it, like templates, are generally reserved for the programmer who's making tools, not just software.

So it's OK if it's a little subtle in places.

The other thing to consider is that there's no guesswork on the compiler's part.  A function is either deterministic (the chr(32) example), or not.  If you try to use a non-deterministic function in a deterministic context, the compiler gives you a "Non-determinstic function -- not able to calculate the value at compile-time" error and it becomes the user's problem, not yours.

The thing about C/C++ is that they don't *care* about bad programming practices.  Pascal is a language that was built with padded walls to prevent you from doing anything you shouldn't be doing.  What happened?  Well, it didn't catch on as a padded-wall language, it ended up being extended until it had all of the C/C++ crap that was dangerous -- the Turbo Pascal extensions.  If you want to be the same sort of language as C/C++, you need to gleefully allow the programmer to do stupid stuff because if you forbid it, you are also preventing the expert programmer who "gets it" from doing brilliant stuff.
Flamebait Sr.
Wednesday, September 29, 2004

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz