Rules of good declarative language design

I was wondering, are there any. I would normally think of this as the kind of thing that is an art, and not to be guided by rules, but I am having to criticize a declarative DSL that seems poorly designed to me and I would like to have some things to point to.

The major initial sin I can see here is that the format is very verbose, requiring the declaration of many things the compiler could find for itself
(the compiler compiles to C# for Asp.NET and clientside html/javascript)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I am unaware of such a list,

I am unaware of such a list, but it may be fun to try to compe up with some rules of thumb...

A few ideas

* Order of declaration of named things should be unimportant. Declaration order may matter for things not given names or things which are sequential in the application (if that makes sense).

* In particular, naming to get around limitations in nesting is obnoxious. C/C++ are egregious offendors of this principle; one longstanding "rule" of these two (recent standardization might relax this) is that curly-braces {} cannot occur inside of parentheses. In other words, you can't do foo (1,new class {...}, 5);--the class that you might want to declare inline in the procedure call has be be declared before and named.

* Likewise, self-reference without needing an explicit name or forward is nice. Again, I'll pick on C++, where anonymous classes may not have constructors because there is nothing to call them.

* Naming of things is useful if you want to refer to them more than once, for complicated expressions, or for documentation purposes. For things used only once, naming should be optional (at least for the user; internally-generated unique names for things are OK).

* Sometimes it is useful to be able to declare complicated things in steps, separated by other declarations; and or do partial declarations (to be finished by the time the declaration "phase" is over). This is nice; but be sure to detect and warn if a declaration is not complete.

For things used only once,

For things used only once, naming should be optional

That's funny, just this morning, I was thinking about that usually you need to provide a name to a recursive function, so that it's able to call itself.
But that it could be avoided by a 'this' keyword to call the current function itself (and if you need to access the outer function from an inner function you can do outer_func=this and then in the inner function call outer_func) but I wondered if the added complexity of the 'this' keyword is really worth it to just avoid naming a function..

fix


Fixpoint combinators...

...or the explicit invokation thereof, are probably inappropriate in a DSL intended for domain experts who aren't computer scientists. Self-reference operators (MyClass, this) permit self-recursion, but they don't permit as easily mutual recursion between two entities.

Naming/letrec are probably the best way to do it, which is unfortunate.

What goes on under the hood, is another matter.

Recursion

I wasn't actually recommending it. I agree that naming is the best way to do it, generally. I don't see why this is unfortunate, usually such things -should- be named. However, what you want to do is make using recursion/iteration rare via high-level constructs that do the iteration for you, e.g. map/foreach/fold.

A few more

I've been recently working on a compiler for declarative language with write-once variables.

  • If a variable is written to more than once *with the same value*, don't error.
  • If a variable is never assigned and never used, don't throw an error.
  • As was said before, order of declaration vs. assignment should not matter.

well

the language is an XML dialect, and a few declarative languages in the past have been SGML dialects (DSSSL for example).
I wonder if there would be generic rules of thumb, and then some sort of clarification for markup based declarative languages.

Maybe one of the generic rules of thumb would be: don't use XML.

and then if you use XML the first clarification would be: see why we told you not to do that?

We had many discussions of

We had many discussions of XML vocabularies over the years (that's one of the things the XML department is for). Maybe you can make use of what's found in these discussions.

Useful notes from the Unix tradition

When your language is nowhere near Turing-complete, syntactic sugar is your friend: see http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s09.html .

Designing mini-languages: see http://www.catb.org/~esr/writings/taoup/html/ch08s03.html .