The original comment
"Eric Merritt" <cyberlync-/[email protected]> Wed, 06 Aug 2003 18:45:17 -0000
| Newsgroups | gmane.comp.programming.pragmatic |
|---|---|
| Message-ID | <[email protected]> |
To: address@hidden
Subject: Questions for a language designer
From: Scott McKay
Date: Tue, 27 May 2003 15:49:47 -0400
A friend at work has been toying with the idea of what
his "ideal programming language" would look like. I don't
think he's serious about actually implementing it, but he's
a really smart guy who wants to learn something about doing
language design. He wanted pointers to literature that
might give him some insight. I said I thought that, while
there are lots of books and papers that describe particular
languages, and books and papers that describe the details
of building compilers, run-times, type systems, semantics,
etc, there isn't really a whole lot about that describes
how to design a "good" language, where "good" is defined
as "meets some set of [measurable] criteria defining some
set of needs".
I've been involved in designing and implementing a couple
of languages, and I've built a lot of tools and environments,
and generally kept up with what people have been doing for
a long time. What this means, of course, is that I've been
directly involved in or witness to the making a bunch of
mistakes that might have been avoided if I/we had been able
to formulate the right questions at the outset.
So I decided to send him a list of questions that I would
ask myself, and describe why these questions are worth
asking. After it reached a certain length, I realized
that it would probably be worth doing a proper job of it,
since I've never seen all of these questions asked in the
same place.
I wonder if some of you might be willing to collaborate a
bit on turning this starting point into a *really* good
list of questions. What I need for each entry are one
or more related questions, a rationale for why these are
good or important questions, and (secondarily) a couple
of possible answers. The answers are to stimulate further
thinking, not to provide "the one right answer".
Public discussion is welcome, as are private replies. I
will collate all the contributions into this document
(properly credited, of course) and periodically send out
the result. If it turns out well, we can "publish" the
result someplace useful.
Thanks! The list (so far) follows:
- What need are you trying to fill? Don't fall into
the trap of "a scripting language", because they
always turn into general-purpose languages. In
particular, is high-performance an issue? This
says something about whether you want to implement
a VM-based or a natively compiled language.
- What about debuggability? If you plan to compile
it, you need to think about how to store debugging
information.
- How do you want to bootstrap it? This, too, says
something about what kind of back-end you might build.
Perhaps you build a tiny VM in C, then compile to
C. This way, you avoid fun but time-consuming work
on code generation for modern super-scalar hardware,
register allocation, etc.
- Do you want to be able to catch type errors early or
late? That says something about your type system.
If you allow type declarations, do you want to think
about parameterized types? If you go whole-hog
with F-bounded polymorphism, you can get performance
*and* type-safety *and* ease of use, but it's hard
to get this exactly right.
- What about namespaces? Do you want to have a simple-
minded scheme like Java, where classes, namespaces,
and files are roughly equivalent? Lisp-style packages?
Dylan-style modules and libraries? Within a single
first-class namespace, how many second-class namespaces
are there? Java has 7 or 8: class names, function
names, local variable names, slot names, etc. Common
Lisp has at least 3 (function, variable, and class
names). Dylan and Scheme have one, which greatly
simplifies things at a small loss of generality which
can usually be worked around with name conventions.
- What about encapsulation? Do you want to do information-
hiding on a class basis like C++ and Java, or on a
"module" basis like Dylan?
- Do you want first-class functions? What about
lexical closures? First-class continuations? The
answer to those questions will tell you things about
heap- and stack-allocation, and will also tell you
how important it might be to do a continuation-based
compiler. It also tells you how hard your compiler
has to work to avoid consing environments unnecessarily.
Lots of sophisticated language designers go with
simple closures and avoid full continuations, because
full-scale environment capture is hard to do well.
- Do you want a first-class object system? Should it
extend all the way to the primitive types, or do you
want to special-case those like Java? Do you want a
Smalltalk/Java-style single-receiver object orientation,
or a CLOS-style multi-method generic function dispatch?
If the former, do you need some sort of static overloading
like C++? If the latter and performance is important,
do you need some sort of Dylan-style "sealing" so that
you can do some compile-time optimizations? Do you
want single inheritance, single inheritance with
interfaces, multiple inheritance, or a hybrid single
inheritance with mixins? If you've got a more static
type system, you'll need to deal with casts. Do you
additionally want auto-conversion?
- If you've got an object-system, how much of a meta-object
system do you want to expose? Do you want it to be
purely reflective, or more than that? In Dylan, we
separated 'make' from 'initialize', which was a good
idea, but do you also want to separate out 'allocate',
so that you have control over where an object is
created, e.g., in a "persistent memory" pool that
might be back-ended by a database?
- Are there different semantics for "pointer-ish" and
"non-pointer-ish" objects, like in C? Or is everything
a first-class object reference, like in Lisp?
- Do you need hairy CLOS-style method combination, or is
a simpler style like we did in Dylan enough? Do you care
about what Gregor Kiczales calls "aspects", which might
change your decision?
- Do you want to support threading? Do you want to roll
your own threads or use OS threads? Do you want to
support massive concurrency like Erlang? The answers
to those questions will tell you about aspects of the
run-time, memory allocation/GC, and performance. Oh
yeah -- it also tells you if you can actually take
advantage of the multiple processors sitting in most
of the machines we all have. Do you want Java-style
synchronization where it is built in to objects, or
should that be handled orthogonally?
- How well do you want to be able to integrate with
native libraries? This decision affects your memory
model, how you plan to represent run-time type info,
how function call/return works, how signalling works,
etc. By "memory model", I also mean to include what
sorts of objects are boxed or tagged. (Opinion: the
Harlqn/FunO Dylan compiler got it wrong -- I think we
should have boxed everything, and then concentrated our
efforts on box/unbox optimizations. This would have
*hugely* simplified FFI issues.) Good integration
with native code probably means that you will end up
using a conservative collector, and that will effect
the semantics of "finalization" (if you have it).
- Do you want to be able to return multiple values?
How about &rest arguments? These affect function
call/return, tail-call elimination, and stack vs. heap
allocation optimizations.
- What's your order of evaluation in expressions? This
affects what sort of optimizations can be safely done.
- What compilation model do you want? Lots of include
files like C[++]? Lots of "packages" like Java?
Whole-worlds like Lisp? Separate libraries like Dylan?
This affects a lot of things, not least of which is
the ability to deliver small applications. It also
informs the design of your core run-time.
- Is the core run-time tiny like Scheme? Small like
Dylan? Huge like Common Lisp? If you like the Common
Lisp model, it's worth looking at EuLisp to see how
to re-package it in a more layered way.
- Even in a small run-time, you need to get the basic
types right. Are your numeric types "closed" (that is,
do they include reals -- rationals and irrationals --
and complex numbers)? Are your string and character
types rich enough to model Unicode?
- Think hard about collections. How do the following
relate to each other: sets, tables, vectors, arrays,
lists, sequences, ranges? In Dylan, we decided too
late having the tail of a list be a "cons" was maybe
not such a great idea; what about that? How do your
collections interact with your threading model?
- Think hard about iteration, especially over collections.
If all collections obey a uniform iteration protocol,
it means that you can do things like 'for e in c ...'.
Note that if iterators are done in a first-class way,
this has performance implications that your compiler
needs to worry about.
- Do you want macros? Lisp-style macros? Dylan-style
pattern-matching non-procedural hygienic macros?
Scheme-style 'syntax-case' pattern-matching procedural
hygienic macros? This says a lot about the syntax of
your language, and it also says a lot about the model
you choose for compile-time evaluation environments.
- What syntax do you want? Parentheses unaccountably
give lots of people hives, but S-expressions make a
lot of things much simpler. Infix syntax is quite
nice when it's done well, but you've got to get the
"kernel" of that exactly right if you want your infix
macro system ever to be usable. If you decide on
S-expressions, should they be represented as lists
and conses, or do you wany a first-class object for
that?
--- In [email protected], "Eric Merritt" <cyberlync@y...> wrote:
> On 2003.05.27 16:56 Jerry Jackson wrote:
> >
> > - What's the metaphor? Although the days of the "pure"
> > languages are mostly gone, I believe it's still worthwhile to have a
> > good sense of the core language mental model, e.g.:
> >
> > FOL (Prolog), Objects (Smalltalk, etc.), Functions (lots), PDP-11 (C) :-),
> > Production System (OPS5, etc.).
> >
> > Different core models influence the "natural" styles of program development
> > in different languages even if the set of available facilities is similar.
> > They
> > also help define which late-arriving features will "fit" and which will be
> > warts.
>
> and
>
> On 2003.05.28 08:26 andrew cooke wrote:
> >
> > I wonder if the most interesting languages (those that do something
> > new) take a list like this and try to find some abstraction that
> > allows apparently conflicting choices to be viewed as two applications
> > of a single idea.
>
> get to the heart of the matter in my opinion.
>
> The finest programming is poetry, not prose. A language has to have
> an internal harmony and a natural rhythm to be poetic. Such coherence
> is never accidental; it must be supplied by the language designer.
>
> For the programmer, you want a language with as little friction as
> possible, where code flows freely and naturally. Simplicity, symmetry
> and internal consistency all help. A little harder to pin down but
> just as important is a language design that lends itself to conventions
> and idioms (the secret to C's success).
>
> For the reader (tester, maintainer, integrator, student), you want
> clarity and conciseness -- two properties often at odds with each other.
> A language which is intuitive, and thereby self-documenting,
> accomplishes both goals.
> It seems to me that the only practical way to achieve these things is
> to begin with a unified underlying vision -- a mental model or metaphor
> rich enough to suggest answers to almost all of the design questions.
> Best is to have both a model and a metaphor -- a conscious mental model
> to determine the broad structures and rules, and an intuitive metaphor
> or style to determine how those structures and rules get translated
> into concrete symbols and syntax.
>
> Of course most language designers do have mental models -- that's often
> why they design languages in the first place, so that they can talk
> about their mental models knowing that there's at least one language
> it makes sense in :)
>
> Michael St. Hippolyte
> http://www.bentodev.org
------------------------ Yahoo! Groups Sponsor ---------------------~-->
Buy Ink Cartridges or Refill Kits for Your HP, Epson, Canon or Lexmark
Printer at Myinks.com. Free s/h on orders $50 or more to the US & Canada. http://www.c1tracking.com/l.asp?cid=5511
http://us.click.yahoo.com/l.m7sD/LIdGAA/qnsNAA/W4wwlB/TM
---------------------------------------------------------------------~->
To unsubscribe from this group, send an email to:
pragmatic_lang-unsubscribe-hHKSG33TihhbjbujkaE4pw@public.gmane.org
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/