Can software development be elevated from the Microsoft style?

A paper and a talk presented at MacHack'96, The 11th Annual Conference for Leading Edge Developers.

Summary

composing safe, fast, and beautiful code in C++ and C. With an unusual slant on safety and performance, the paper discusses serial (vs. random) access to a collection, pointers vs. references, function classes, incorporation, transient object and classes.
The paper introduces a number of efficient and powerful (yet obscure) patterns that make code safe and neat: precision-targeted pointers, nested functions, lazy objects, stealing of a body, natural iterators. A few good and bad code snippets show off the benefits of well-crafted code.

A solution to a Fragile-Base Class Problem

When a base class of a class hierarchy is extended with new data
members, overridden virtual methods, or even with new virtual
functions, it is nevertheless possible to avoid rebuilding of the
entire hierarchy. One can bypass recompilation for a rather long limb
of a class derivation tree.

This technique requires some discipline in building a
hierarchy, but in return guarantees that only the top-most class needs
to be recompiled to take into account modifications made to a base
class. The rest of the hierarchy (which may have been compiled to a
set of separate libraries) may be used as it is.

See it for yourself, by building, "upgrading", and not recompiling sample "libraries" and targets in FBCSolution.tar.gz. Check out the README file for more details.
June 27, 1997

GenuineLambda-abstractions in C++

The following code snippet speaks for itself. It is not a toy: the snippet is taken from an actual working code, a part of LinAlg, a Linear Algebra and Optimization classlib. This code is to verify that my implementation of the Brent root finder really works:

This code is C++ standard-compliant. It compiles with gcc 2.8.1 and Visual C++ 5.0, and runs successfully.

The last three lines of the code constitute a single expression, which creates a few "anonymous" objects, uses them and destroys afterwards. The first argument of the MakeTestFunction() is the title of a test case; the second argument is a test's body itself, specified as an anonymous function: a genuine lambda abstraction. The whole MakeTestFunction clause has the obvious meaning of defining a test case datatype, which is subsequently instantiated and run.

The Lambda() macro really makes a "body" (functor) without a name; the name may be attached -- "bound to" -- later.

Pointers as closures

There is a deep connection between C pointers on one hand, and Scheme
closures that respond to the messages ref and
set on the other hand. We can therefore precisely emulate
the semantics of & in Scheme. We can also say that C
has a limited form of closures.

The article referenced below demonstrates the connection by re-writing
-- almost verbatim -- two C code fragments into Scheme. The C samples
rely on pointers to let invoked functions share and mutate the
variables local to the caller.
For example, the following C fragment

void modify(int ** p, int * py)
{
**p = *py * *py;
*p = py;
}

becomes in Scheme

(define (modify p py)
((*= (* p)) (* (* py) (* py)))
((*= p) py)
)

The technique can easily be generalized to permit pointer arithmetics as well.

and it will compile and work (with this iostream.h included), without any changes in your code whatsoever.
Made at a Be Dev kitchen on Dec 13, 1996 (in 5 minutes)

In much more detail, and in a much broader context, this code is described in the article
Speaking in Iostreams-ese, published in C/C++ Users Journal, v.15, No. 5, May 1997, pp. 47-55.

Keyword arguments of C++ functions

The article which is referred to below talks about implementing keyword function arguments in several languages, including C++. A "dictionary" of C++ function's arguments can be constructed and searched
either at run time, or at compile time. The first solution is rather straightforward, and is mentioned rather briefly. The article then gives a complete example, which shows how construction of this "argument environment" and variable lookups can be
done entirely at compile time (see the middle of the article).

Advanced i/o and Arithmetic Compression classlib
Besides i/o and compression code, this package provides vocabularies, (poly/homo)morphic dictionaries with a dynamic "inheritance" path. These vocabularies give one implementation of a run-time variable lookup. The package is capable of greater things: a hierarchical lookup of arguments using defaults of different scope and generality.

Why C++ is not very fit for GUI programming

With no intent of starting a holy war, this paper lists several annoying C++ snags seem inherent in GUI C++ programming. I encountered these problems while wrapping XVT's platform-independent graphical toolkit in a C++ class library. It appears that the pitfalls and workaround kludges are fairly common, to many event- and callback-based systems.

References

Paper and the presentation
at MacHack'95, The Tenth Annual Technical Conference for Leading Edge Developers, Southfield, MI, June 22-24, 1995.

C++ compiler as an expressive
type inference engine

This article will show that any standard C++ compiler can deal with
algebraic data types, perform term comprehension, and do type
arithmetic. C++ compiler acts as a term-rewriting engine -- an
interpreter of an untyped lambda-calculus over type identifiers. It is
the compiler that finds an attempt to divide by zero and aborts the
compilation -- before an executable is built, let alone run. We rely
extensively on a partial template instantiations. It is a standard C++
feature that offers term comprehension and resolution of polymorphic
types. The code in this article compiled with egcs-2.91.66 and g++
2.95.2 compilers, on FreeBSD and Linux.

This term re-writing engine is somewhat similar to expression
templates. There are however important differences. Expression
templates deal with terms that represent C++ expressions, e.g.,
a=b+2*c where a, b and
c are matrices. An expression template will rewrite this
into a (sequence) of other expressions to explicitly iterate over all
elements of matrices a, b, and
c. Expression templates therefore manipulate variables
whose type -- Matrix in the case above -- is already
known.The term-rewriting engine in this article deals with
types and type identifiers. The engine re-writes type
constructors rather than program variables. The result of the engine
is an inferred type of an expression.

Of course term-rewriting is not unique to C++. Some may argue that
other languages like Prolog, ML, or Erlang are more suitable to this
task. One has to keep in mind however that it is a C++ compiler
that does term-rewriting, of type expressions. Prolog and Scheme are
(dynamically-typed) languages with latent types; they do not apply in
the present context of static type inference. ML and Haskell do
sophisticated type inference; yet their type systems are
decidable. The ultimately static typing illustrated in this article
requires a more expressive type system. Beside C++, Cayenne and other
languages with dependent types can accomplish this task. Yet among
major contemporary programming languages only C++ appears to be able
to implement this ultimately static type system, and perform a very
general term rewriting of types at compile-time.

scheming with the C preprocessor: a computable#include

How to get the C preprocessor to #include different .h files depending on a user-#defined symbol, whose all possible values are
generally unknown at the time the code is written.
In other words, how to get the preprocessor to substitute Foo for Barinside#include "Foo.h"
Note, the preprocessor does not normally substitute #defined symbols
inside C strings (let alone parts of C strings, let alone #include
strings)

Chess tournament scheduling: tough but possible

tournament-sched.c
is the complete code mentioned in the article. This code -- running on
a lowly PDP-11 clone -- had actually scheduled several tournaments,
in real time.

Phil Troy has kindly pointed out that the scheduling problem is
actually that of minimum-weight perfect matching in a general graph,
for which efficient exact solutions are known. These solutions are the
variations and improvements of Edmond's maximum-weight matching
(aka blossom) algorithm. A good description can be found in
Computing
Minimum-Weight Perfect Matchings by William Cook, Andre' Rohe in
INFORMS Journal on Computing, as well as in many books on
combinatorial optimization.

Advanced Finite Automaton as a simple HTML formatter

This is a simple self-contained C code for a primitive
lynx-like formatting of HTML documents. The notable feature of the code is an
extensive use of a Finite State Machine with
byte-compiled actions and an option to
call a new state instead of just move to it, with an
opportunity to return to the caller-state. The code is
commented, even excessively so at the beginning.

Programming in a Finite Automaton style

An illustration that such an abstract thing as a Finite State Machine can actually be used for mundane programming tasks.

This C code is a simple filter that prints out words from the input stream one by one, ignoring C-style comments. This sounds immensely trivial, until you actually try to write the code. Keep in mind that it should be able to handle empty lines, leading and trailing spaces, and such catches as

e*/**// /* aaa
/* ****a/ //// *
/ */ */

If you wrote the code in a traditional style, you may want to compare it with the FSM one below.

Magical conversion from a (char *) to a Pascal string in C++.
Plus a few other tricks how to encapsulate some QuickDraw data structures into classes and get native QuickDraw functions to take the embellished objects as their own (that's the magic)

In a nutshell, this post is about one method of writing very general
foreach()-type iterators that call an iteratee function within its
own (and local) environment, without casting to (void *) and fro,
without causing name conflicts, and without exposing private parts.