The opposite of expressible would be orthogonal:
If a language L cannot express an additional feature F,
then F is orthogonal to the features of L.
For example, the programming language could provide for
the direct expression of higher-level design abstractions.
(But these abstractions could also be supported by frameworks, etc).
This is discussed in The Programming Design/Implementation Boundary.
Discussion of Orthogonality and Expressiveness
- Pro Expressiveness with exceptions:
«[I]f you have a choice of several languages,
it is, all other things being equal,
a mistake to program in anything but the most powerful one.
-
There are many exceptions to this rule. If you're writing a program
that has to work very closely with a program written in a certain
language, it might be a good idea to write the new program in the
same language. If you're writing a program that only has to do
something very simple, like number crunching or bit manipulation,
you may as well use a less abstract language, especially since it
may be slightly faster. And if you're writing a short, throwaway
program, you may be better off just using whatever language has
the best library functions for the task. But in general, for
application software, you want to be using the most powerful
(reasonably efficient) language you can get, and using anything
else is a mistake, of exactly the same kind, though possibly in a
lesser degree, as programming in machine language.
» [BTA]
- Pro Expressiveness:
Having the `right' features for the application domain
of a programming language is a development-aim because:
``... programming patterns ...
are an obstacle to an understanding of programs...''
and ``Programs in more expressive programming languages ...
contain fewer programming patterns
than equivalent programs in less expressive languages.''
[EPL, 38]
[My comment 1:] But to choose among two sets of mutually expressive features
we need other criteria like less error-prone.
[My comment 2:] Some less expressive features can be preferable
if they have other advantages like better structure.
E.g. goto + labels cannot be `expressed' (as [EPL] defines it)
by structured control constructs (if I am not mistaken).
- Con Expressiveness:
OTOH, an increase in expressive power
``comes at the expense of less ``intuitive'' semantic equivalence relations''
[EPL, 2f]
``may destroy semantic properties of the core language
that programmers may have become accustomed to''
[EPL, 41].
- Pro Othogonality:
``Orthogonal features encourage a uniformity in language structure
that makes a programming language look like a ``toolkit''
of strandardized parts that connect together in predictable ways.
For this reason, orthogonality is promoted as a crucial property
of a well-designed programming language.''
[STPL, 156]
[My comment:] If the set of features is orthogonal,
it eliminates `superflousous' features
(i.e. features that don't increase the expressive power).
- Compromise Othogonality:
``But a slavish devotion to orthogonality, per se,
can lead to a baroque language with many unnecessary features.
For example, does the imperative language ...
truly benefit from ``numerical block'' and ``location blocks''
[block = construct with local declarations]?''
[STPL, 156]
[My comment:] However, exceptions to the general rule "orthogonal features are combinable"
violate Regularity,
and thus compromise Simplicity.
It may be simpler for the language user (not the language implementor)
to allow some useless combination for the sake of regularity.
How to Evaluate
Interestingly, since starting the PLD site, I cannot remember having
found criteria directly for PLs, but only criteria
for modeling and specification methods:
[STDA] Barbara H Liskov, Stephen N Zilles: Specification Techniques for Data Abstractions; Trans. SE 1(1); 1975.
Criteria for evaluating specification methods:
- Formality: "
a notation that is mathematically sound
".
- Constructability: "
It should be possible to construct specifications without undue difficulty
"
- Comprehensibility: "
A person trained in the notation ... should be able ... with a minimum of difficulty, [to] reconstruct the concept which the specification is intended to describe
"
- Minimality: "
The properties which are of interest must be described ... in a way which adds as little extraneous information as possible
"
- Wide Range of Applicability: "
[T]he larger the class of concepts which may be easily described by a technique, the mrore useful the technique
"
- Extensibility: "
[A] minimal change in a concept results in a similar small change in its specification
"
[ORM1] Terry Halpin: UML Data Models from an ORM Perspective: Part One;
Conceptual Modelling 1; April 1998.
gives criteria for evaluating conceptual modeling methods:
Expressibility,
Clarity,
Semantic stability,
Semantic relevance,
Validation mechanisms,
Abstraction mechanisms,
Formal foundation.
Examples of Evaluations & Judging Language Comparisons
Non-judging comparisons between languages are discussed in PL comparison.
- [Mark A Ardis: A Framework for Evaluating
Specification Methods for Reactive Systems -- Experience Report; 159-168 in SE'95]
gives an example of evaluating specification methods including their
formal specification languages (Modechart, VFSM, Esterel, Lotos, Z, SDL):
``Our evaluation indicates the following trends:
Applicability is not an issue, and implementability and testability/simulation
are by and large not much of a problem. ...
Verifyability ... is a strength of all the languages. ...
Contrary to traditional criticism and popular perception
we found that the learning curve was not a problem. ...
Perhaps surprisingly, our evaluation suggests that maintainability
is not a strength of any of these languages.''
- Programming Language Critiques
- Flame on Pascal
- Ada9x better than C++ (1992)
- Entity-Relationship is the hard way to database modeling,
Object Role Modelling is the easy way, says [Scot A Becker:
An Argument for the Use of ER Modeling; Conceptual Modeling 10; Aug 1999]
- Lisp is [BTA]
- good for rapid development
- a most powerful language (c.f. expressiveness):
«In Lisp ... macros ... are programs that write programs.
Programs that write programs? When would you ever want to do that?
Not very often, if you think in Cobol. All the time, if you think
in Lisp. ...
The source code of [our main application] was probably about 20-25%
macros. Macros are harder to write than ordinary Lisp functions,
and it's considered to be bad style to use them when they're not
necessary. So every macro in that code is there because it has to
be. What that means is that at least 20-25% of the code in this
program is doing things that you can't easily do in any other
language.»
«Our hypothesis
was that if we wrote our software in Lisp, we'd be able to get
features done faster than our competitors, and also to do things
in our software that they couldn't do. And because Lisp was so
high-level, we wouldn't need a big development team, so our costs
would be lower. If this were so, we could offer a better product
for less money, and still make a profit. We would end up getting
all the users, and our competitors would get none, and eventually
go out of business. That was what we hoped would happen, anyway.
-
What were the results of this experiment? Somewhat surprisingly,
it worked. We eventually had many competitors, on the order of
twenty to thirty of them, but none of their software could compete
with ours.
»
- Comparing Development Costs of C and Ada (1992)
«Our data indicates that Ada has saved us millions of development dollars.»
- Eiffel:
The following rationals of language preference decisions
at Eiffel.com
give a hint which properties of languages
are considered important in software development projects
targeted by the OOPL Eiffel:
The Subjectiveness of Language Comparisons
The Blub Paradox [BTA]:
«[T]o explain this point I'm
going to use a hypothetical language called Blub. Blub falls right
in the middle of the abtractness continuum. It is not the most
powerful language, but it is more powerful than Cobol or machine
language.
And in fact, our hypothetical Blub programmer wouldn't use either
of them. Of course he wouldn't program in machine language. That's
what compilers are for. And as for Cobol, he doesn't know how
anyone can get anything done with it. It doesn't even have x (Blub
feature of your choice).
As long as our hypothetical Blub programmer is looking down the
power continuum, he knows he's looking down. Languages less powerful
than Blub are obviously less powerful, because they're missing some
feature he's used to. But when our hypothetical Blub programmer
looks in the other direction, up the power continuum, he doesn't
realize he's looking up. What he sees are merely weird languages.
He probably considers them about equivalent in power to Blub, but
with all this other hairy stuff thrown in as well. Blub is good
enough for him, because he thinks in Blub.
When we switch to the point of view of a programmer using any of
the languages higher up the power continuum, however, we find that
he in turn looks down upon Blub. How can you get anything done in
Blub? It doesn't even have y.
By induction, the only programmers in a position to see all the
differences in power between the various languages are those who
understand the most powerful one. (This is probably what Eric
Raymond meant about Lisp making you a better programmer.) You can't
trust the opinions of the others, because of the Blub paradox:
they're satisfied with whatever language they happen to use, because
it dictates the way they think about programs.»
(The author remarks that expressivity is not a linear order,
allowing for several ``most'' expressive languages)
- The Abstraction Principle:
Abstraction is the technique of giving names to program terms.
This supports the factorization requirement.
The principle demands involution,
i.e., the generality of combining
naming and syntactic classes:
``The phrases of any semantically meaningful syntactic class
may be named.'' [STPL, 31]
- E.g. locations by alias, expressions by functions,
commands by procedures, declarations by modules,
type structures by classes (abstract data types).
- «... we can treat the abstraction principle
as a ``record introduction principle.''
The record introduction principle might say:
Phrases of any semantically meaningful syntactic class
may be components of records.» [STPL, 61]
- The Parameterization Principle:
The technique of parameterization increases the reuse potential
of factorization.
The principle demands involution,
i.e., the generality of combining
virtual/formal names and syntactic classes:
«The phrases of any semantically meaningful syntactic class
may be parameters.» [STPL, 75]
- «... the paramterization principle is in fact
a ``lambda abstraction principle,''
because parameterized phrase forms
-- lambda abstractions -- are allowed in the language.»
[STPL, 95]
- The Correspondence Principle
increases consistency
by treating similar the concepts of abstraction names and paramter names:
«For every abstraction form,
- define I
2 = U,
there may be a corresponding parameterized form
- define I
1(I2) = ... in I1(U),
(and vice versa) such that the semantics of binding
I2 to U is the same in both.» [STPL, 90]
- The Qualification Principle
concretizes the Principle of Locality:
«Any semantically meaningful syntactic class
may admit local definition.» [STPL, 105]
- A construct that admits local definitions is called a block.
Note: Don't adhere slavishly to ``any''.
- «... the qualification principle is a restatement
of the abstraction principle restricted to local scope.»
[STPL, 95]
Worked out methods for developing a programming language seem not to exist.
Some general guidelines for how to proceed:
- Reuse: Take existing languages as a model,
and reuse established constructs from them.
«Use established constructs as much as possible.» [PLD, 517]
(continued from).
Existing PLs provide a wealth of constructs (discussed in PL features).
«The notations of mathematics are a second,
though certainly not indendendent source of concepts» [PLD, 523].
(+) This development method helps achieving a high degree of familiarity.
(-) But «it should be clear that past formalisms
are not the source of new ideas.
It is the undisciplined ramblings of human communication
that are most likely to lead to real linguistic progress.» [PLD, 524]
E.g. domain specific programming languages
may include primitives taken from the application domain of their programs.
- Experimental Prototyping:
Concretize your ideas far enough to able to use it to write some programs,
or (at least) one larger application.
-
«Having decided not to do very much, and to copy most of it,
the problem reduces to achieving the necessary features
... in a consistent manner.
The simplest way to proceed is to write some programs.
That is, let your new language invent itself naturally.» [PLD, 517]
-
«You Need an Application to Drive the Design of a Language ...
This may not be an absolute rule, but it seems like the best languages all evolved
together with some application they were being used to write. C was written by
people who needed it for systems programming. Lisp was developed partly to do
symbolic differentiation, and McCarthy was so eager to get started that he was
writing differentiation programs even in the first paper on Lisp, in 1960.
-
It's especially good if your application solves some new problem. That will tend to
drive your language to have new features that programmers need. I personally am
interested in writing a language that will be good for writing server-based
applications.
» [5QLD]
- Formalizing:
«Then attempt to use the standard language definition tools (grammars)
to specify the language concisely. ...
- One might suspect that the language would not improve
by having to conform to a restrictive defining tool.
But experience shows that it does.
In some sense there is no art unless there is a restriction of the medium.
In some perverse way, the human mind, in coping with restriction,
produces its best results.
And grammars, the very formalization of nested definition,
are a rich medium.
» [PLD, 518]
- Iterative:
«The restrictive form of definition will surely suggest changes
in the language, then, in turn, in the sample programs.
Iterate the process until both the program and the language description
are elegant and understandable.»
[PLD, 518]
- Evolving A Programming Language:
A given language is changed, yielding a language
which can be seen as a new version of the old language or as a new language.
E.g. Bjarne Stroustrup: The Design And Evolution of C++; Addison-Wesley, 1994.
- A common example are the standardized forms of programming languages
which are (usually) developed (evolved) from an already existing languages.
For example the evolution of Fortran 90 from Fortran 77
with the main antagonisms
traditionalists vs. revisionists,
featurists vs. generalists, and
US-nationalists vs. internationalists.
- In "Language standards committees and revisions"
Brain Meek talks about
- Standardization as language evolution or as revolution?
- Is language development for users or for implementors?
- Should language evolution be backward-compatibile
even for people who are not properly organised?
His WG10 guideline classifies changes into
- Change to semantics of well-defined feature.
- Deletion of semantically well-defined feature.
- Deletion of semantically ill-defined feature.
- Clarification of semantically ill-defined feature.
- Change or deletion of obsolescent feature.
And it demands a rationale for each proposed change,
an assessment of how widely the affected feature is used
and of the difficulty of converting affected programs.
[APL] A D Falkoff, K E Iverson: The design of APL; IBM Jounal of Research and Development; July 1973. Reprinted in: Programming Languages: A Grand Tour; 1987
-- ``guiding principles in [APL's] language design'' [Stansifer]:
practicality; simplicity
[EPL] Felleisen: On the Expressive Power of Programming Languages; SCP 91.
dvi
ps
[Anatomy][TAPL]
-- portability; frequency, locality, coherence, distinct, flexibility, power
[5QLD] Paul Graham: Five Questions about Language Design; private notes 2001.
-- throwaway programs, for people, for yourself,
control, brevity, hacking
[BTA] Paul Graham: Beating the Average.
[Horn] James J Horning: What the compiler should tell the user; In: Compiler Construction (LNCS 21); 1974.
[PLD] W M McKeeman: Programming Language Design; In: Compiler Construction (LNCS 21); 1974
-- [good] PL properties: adequacy, translatability;
simplicity, orthogonality, human thought
Stansifer>[Stansifer]
-- criteria for evaluating PL design:
translatability; factorization, orthogonality, simplicity, regularity, consistency
Ulf Schünemann 071297, 200901