[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Macros and little languages



Howard Stearns wrote:
> Some say code is read (maintained) more than it is written, and by more
> people, so that in the long run, a uniform programming-language-domain
> style is most important.
>
> Others say they are paid to write code, but that writing or fixing, it's
> easier when working in the problem domain.

This seems to imply a comparison between two roughly equal scenarios, and
that the choice between them might therefore merely a matter of taste.  I
believe that's demonstrably not the case.

The point of working in the problem domain is touched on in the other
message I've just posted, in the "succinctness = power" thread: semantic
compression.  A program written in the problem domain should be much shorter
than its equivalent written directly in the programming-language domain.
The benefits of this compression scale extremely well, since that savings is
multiplied with each new application of the problem-domain language.

It's only in cases where large compression cannot be achieved by programming
in the problem domain, that the choice may become more of an aesthetic one.

> Some worry that sufficiently powerful program-domain code, or
> conversely, that sufficiently powerful application-domain code, is too
> hard for mere mortals to work with for writing or for reading.

It may be hard(er) to develop a good problem-domain language, and there are
some other reasonable arguments against problem-domain code, but arguments
against the usability and comprehensibility of problem-domain code are not
borne out by experience.

In the long run, given sufficient resources, problem-domain languages always
seem to win over their programming-language-domain equivalents, for reasons
which could be described both as logical (it's most efficient) and economic
(it's most efficient!)  Once a good problem domain language does exist, it
tends to be more efficient to develop systems for the domain it addresses,
in that language.  That's why people do text searches using regular
expressions, and database queries using SQL, for example.

Confusing the matter is the fact that many of the most obvious examples of
problem domain languages, like the ones I've just given, tend to be in the
domain of program development tools: assemblers, compilers, configuration
languages, parser generators, etc.  Essentially, development tools provide a
large "horizontal market" which has helped domain-specific languages to
thrive there, and it's one we're all familiar with.  But other examples,
both general and specific, are legion, and I probably don't need to try to
catalog them here.  In case anyone hasn't noticed, XML is currently driving
an explosion of domain specific languages, which in a chaotic and
evolutionary way is moving in the right general direction.

> Some claim that development tools can reduce the exposure to code to
> such a small amount that the issue becomes moot.

Specialized development tools that automate coding are essentially a kind of
domain-specific language - it may not be a textual one, although very often,
the results are mapped isomorphically to a textual representation.  For
example, many screen/form design tools store their results as text in a
domain-specific language.  These sort of development tools can be considered
an apex (even if only a local maximum) of the domain-specific language
approach.

> Is it more important for a language to promote code that is readable by
> anyone versed in the particular programming language, regardless of the
> application domain, or is is it better to for a language to make it easy
> to churn out new code that works for particular applications?

That almost sounds as though it could be rephrased as "is it important for
languages to have a macro-like facility", since in the absence of something
macro-like, the former goal - readable by anyone - would always be
important.  But I don't really see why the two goals have to be mutually
exclusive.  For example, one can use Scheme or Lisp quite effectively
without ever using macros - it's an "add-on" feature that doesn't really
affect the core language.  The choice of whether to use macros, or how
heavily and where to use them, can be made by individual users and
organizations.

> How do the answers depend on whether we're talking about a closed group
> of programmers employed for a single task, vs. an open-source project,
> vs. distributed group-accreted semantics built on the Web in the next
> generation?

Again, why can't agreed-upon usage conventions, appropriate to the
environment, resolve this?  Do such choices really have to be enforced at
the language level?

I have an example here: in the first version of Java, a reflection
capability was not included.  I don't know if there were any specific
reasons behind this, other than simply choice of priorities in releasing the
first version.  However, there has historically been some conjecture, based
on experience with Smalltalk, that systems based around metaclasses are too
complex and confusing for ordinary users.  One might justify the omission of
truly reflective metaclasses from Java on these grounds (although I don't
know if anyone ever actually did that).

But real-world use of Java can benefit greatly from reflection, and a
reflection capability was duly added.  I don't think it's as clean or
intuitive as it might have been if it were integrated more closely into a
metaclass system, similar to Smalltalk's.  I'm willing to concede that this
may just be my preference, but I don't think there's much doubt that Java's
reflection isn't any easier for ordinary users to understand.

What I take from this is that even if certain powerful features are
considered dangerous for use in particular scenarios, doesn't mean they
should necessarily be excluded from a language entirely.

A related Java example is that it started out without anything resembling
first-class closures, but a facsimile was later added in the form of
anonymous inner classes.  This is consistent with the thesis that sooner or
later, every language ends up looking like Lisp/Scheme, but the corollary is
that these languages end up much more complex because of their attempts to
control, restrict, or ignore the features that are considered advanced.

I'm all for having the ability to control and restrict the use of advanced
features, but I think it can be done in less intrusive ways, with less
impact on a language's core design and capabilities.

> Is there any way to define the issue specifically enough
> to actually say something more useful than personal preference?

I think the issues here go far, far beyond personal preference.  Many of
them are only mistaken for personal preference because *none* of today's
languages yet manage to combine, in manageable ways, basic features that we
already know are useful and important.  This leads to arguments about the
relative worth of features that only seem mutually exclusive or competitive
to each other because they haven't yet been combined in a sufficiently
usable way in a single language.

As just one concrete example of that, I'd offer type systems.  Arguing about
whether a language should or shouldn't have static vs. dynamic typing seems
really silly, since it's fairly obvious that there are scenarios in which
static typing is extremely useful, but others where dynamic typing is just
as useful.  In fact, these scenarios tend to form a continuum, so it would
be most useful to be able to migrate programs from dynamically typed to
statically typed.  We know this is possible: the polymorphic type
inferencing languages allow this to some extent, soft typing systems are
attacking this in a somewhat different way, and heck, even something like
BeanShell, a Java scripting language/environment, manages to support this,
in a sense
(http://beanshell.org/manual/bshmanual.html#Loosely_Typed_Java_Syntax).

Until we have full-blown languages that can satisfy the most ardent
supporters of both static and dynamic typing, and allow as much or as little
enforcement as is desired in a given situation, and allow similar choices
between other feature sets -  all without requiring languages the size of
Ada or C++ - until then, our arguments are based on a kind of arbitrary
Hobson's choice amongst sets of language features.

Anton