Monday, 29 September 2008

Beautiful code

What is beatiful code? The shortest answer (which I've read somewhere but can't remember where) is:

we all know what "ugly code" is: code that someone else wrote...
But beautiful code? Isn't it in the eye of the beholder? Well, for me, beautiful equals readable. You have to see on the first sight what the overall idea of the piece of code is. On the other side, the idea itself might be crap (!!!) but then we should ask the next question: what is a beautiful design/architecture?

I, for my side, am thus a proponent of writing aesthetically appealing code. And I'm not alone! Read this:

Whether it is a natural occurrence, a quirk of human languages, or conditioning, most people find while (x==3) significantly simpler to read than while (3==x). Although neither is going to cause confusion, the latter tends to slow people down or interrupt their train of thought. In this book, we have favored readability over safety—but our situation is somewhat different than that of normal development. You will have to decide for yourself which convention suits you and your team better. *
Here we've got it: the eternal problem with the coding guidelines forcing me to write a plug-ugly (3==x)! The question is: should we write ugly code as to be on the safe side? I admit, that I never wrote such an ignominious line of code in my life. You expect trouble? Nope! I've never had any problems at this point! Well, one single time I mistyped it, but found it out in an instant! In C++ you have to develop certain sensitivity for that construct, that's all.

As for practical examples (instead of dull theoreticizing) - some time ago I asked myself: what is the most cool/beatiful piece of code you eve wrote, what would you show to others in order to impress them or to show them how crystal-clear ;-) your style is? As it was even before my lambda library, and only had plain production code on my disposal, I settled on the following piece:
/*------------------------------------------------------------------------*/ /**
* @brief configDelta
* @descr
* This function compares two configurations and returns the differences.
*
* @param[in] other - the other configuration
* @param[in] scope - what delta requested: all the new entries, all the deleted
* entries, or all changes altogether?
* @param[out] delta - the calculated diffrence
*
* @note Assumption: both configurations must be sorted!!!
*///--------------------------------------------------------------------------->

void SimpleCfgFile::configDelta(const SimpleCfgFile& other, CfgDelta scope,
vector<string*>& delta) const
{
TRACE_FUNC("SimpleCfgFile::configDelta");
delta.clear();

switch(scope)
{
case addedDelta:
TRACE_DEBUG("addedDelta");
// all in this but not in other:
set_difference(begin(), end(),
other.begin(), other.end(),
inserter(delta, delta.begin()),
less_then_deref<string*>());
break;

case removedDelta:
TRACE_DEBUG("removedDelta");
// all in other but not in this:
set_difference(other.begin(), other.end(),
begin(), end(),
inserter(delta, delta.begin()),
less_then_deref<string*>());
break;

case completeDelta:
TRACE_DEBUG("completeDelta");
// all in this but not in other + in other and not this:
set_symmetric_difference(begin(), end(),
other.begin(), other.end(),
inserter(delta, delta.begin()),
less_then_deref<string*>());
break;

default:
TRACE_ERR("Unknown scope requested for configuration delta!!!");
}

TRACE_VALUE(delta.size());
}
You see, it's not a rocket science. What I liked in this piece of code was it's conciseness, readibility and (though it's of no real importance for workings of the code) its symmetry. And moreover, I was amazed how a judicious usage of the standard library simplified the task which at first seemed to be rather a daunting one!

An lastly, it's an illustration for the fact that you don't have to use a lambda library to obtain a clear code: I just wrote the following trivial functor:
  template <class T> struct less_then_deref : binary_function<T,T,bool>
{
// OPEN TODO ---> constraint: isPtrType(T)...
bool operator() (const T& x, const T& y) const { return *x < *y; }
}
instead of the lambda expression (*$1 < *$2) and it is still readable. Or even more readable by using a telling name?

---
* taken from the following book: Groovy in Action, Dierk König et al., Manning 2007, page 157-158

Wednesday, 17 September 2008

Google's technology stack

Well, I said I wouldn't write any knee-jerk reaction posts on this blog, only well thoght-through, throughly researched, and insightful entries. Certainly, I have some entries I should be rather working on, like mutithreading testing or lock-free synchronization... But I must admit, that was a bit over-optimistic, as you'll see in a second...

Recently, I stumbled across this one:
Google has recently launched the Google App Engine. From an Java enterprise developers point of view it is shamelessly easy to use, deploy, etc. Well, unfortunately it only takes Python apps for now, but it is stated that there will be more languages supported in the future. But it’s Google again putting its finger into the Java EE wound (first GWT with webapps, then Android shaking the Java ME world, and now App Engine showing how runtimes should look like).*
I blogged before about the "Google phone", which came out not as a phone, but as an SDK (BTW: do you want to make your 1st milion? Take part in the Android Developer Challenge, no kidding!). The local german "Java Magazin" published on this ocasion (i.e Android's release) an editorial, accusing Google of attacking Sun, Java, splitting the Javaland and whatever. What the fuss?

I cite Wkipedia**:
Dalvik is often referred to as a Java Virtual Machine, but this is not strictly accurate, as the bytecode on which it operates is not Java bytecode. Instead, a tool named dx, included in the Android SDK, transforms the Java Class files of Java classes compiled by a regular Java compiler into another class file format (the .dex format).
So you are writng Java code, but it's not running on the JVM! Is that forbidden?
"...some have related Dalvik to Microsoft's JVM and the lawsuit that Sun filed against Microsoft, wondering if a similar thing might happen with Google, while others have pointed out that Google is not claiming that Dalvik is a Java implementation, whereas Microsoft was."***
I don't know. But I think it shouldn't be!

Now for the Google App Engine. As I had a look at it some time ago, it didn't ring a bell with me. I rather though about it as of another grid computing offering, like Amazon's Elastic Cloud: just write your app locally and ther throw it on the grid and it will scale automatically with your needs. But when a Java person sees this, it sees Java technology attacked. The same for GWT: it is JSF as it should always has been. But come on, you are still writing your programms in Java, the difference is that the ideas don't come from Sun! I'd rather say Google is giving a second life to Java by providing new ways for using it. I wouldn't have though that 5 years ago, when they were essentially a C++/Pythonn shop!

Additionally, I can't help feeling that the Java poeople are thinking in an "imperialistic" way: boasting about their superiority, but on the other side always suspicious that someone may have try to challenge their (self proclaimed) supremacy. Like the late USSR...

But on the other side, when you look at Google, you could be tempted to think, that they are writing everything new: newly they published an own C++ test framework**** and an own (C++) transfer data encoding****, just as example. So maybe it's not an assault on Java iteself, but just a manifestation of the "Not Invented Here" syndrome? Now, the employees must do something in their 20% project-free time, so they programm every conceivable thing anew (and better?).

---
* http://adminsight.de/2008/05/05/springsource-announces-an-application-plattform/
** http://en.wikipedia.org/wiki/Dalvik_virtual_machine
*** http://www.infoq.com/news/2007/11/dalvik
**** Google test framework: http://code.google.com/p/googletest/wiki/GoogleTestPrimer, Google transfer encoding: http://code.google.com/apis/protocolbuffers/docs/overview.html, and now they even wrote their own browser: Google Chrome (ok, you knew that already...)

Wednesday, 27 August 2008

The end of dumbing-down of programming?

Times are changing. Definitely. Think about this little story: do you remember what Java's USP was at the beginning? Yes, the garbage collection, and yes, the JVM portability. But the main thing was it's philosophy of not allowing bad programmers to make bad mistakes. We don't have pointers, we don't have operator overloading, we don't have multiple inheritance, our core classes are final... As one person expressed it at that time: "...they gave me a paper hammer instead of a real one so I can't hit my fingers!" And that's the reason why i din't like it, didn't really want to use it, and consequently missed out on a cash-cow :-(.*

But yesterday, I read this on the InfoQ**:
... And it is true, my experience weaves that out too: you can create environment really restricted just to keep bad developers out of trouble, but these restricted environments harm the productivity of your best programmers. Basically what you do is: you are not speeding up your bad developers and you are slowing down your best developers and that's why our productivity stinks in software right now, but the attitude is changing around.
I've read similar complaints before, but as it seems, after the Ruby-shock (RoR faster than Struts and 10x mote productive) such opinion is somehow fashionable and even almost mainstream today.

What do you say? Isn't that the old C++ philosophy we are returning to? I cite Bjarne***:
Kierkegaard was a strong proponent for the individual against "the crowd" and has some serious discussion of the importance of aesthetics and ethical behavior. I couldn't point to a specific language feature [....] but he is one of the roots of my reluctance to eliminate "expert level" features, to abolish "misuses", and to limit features to support only uses that I know to be useful.
---
* The language was just plain uninteresting to me, and I didn't see its real merits at the time. Maybe I didn't want to see them?
** http://www.infoq.com/interviews/Languages-Platforms-Neal-Ford
*** http://technologyreview.com/Infotech/17831/page3/


PS: BTW, concerning the "Java is the next Cobol" thing, there was a discussion on some German Java forum here, where I argued with 2 arguments, but as I see now, I (and everyone else) missed the most important one. Namely: Java is the new Cobol, as it's mainly used in corprate and business settings (like Cobol was). The solution is simple, isn't it?

Wednesday, 9 July 2008

C++ pocket lambda library, the last

So, this will be definitely the last part! I promise! I planned this to be a three part series, and see how it has grown. But let's go down to the business: in the previous installments we achieved the following:
    // part 1: basics
find_if(vec.begin(), vec.end(), _$1 <= 10);
transform(vec.begin(), vec.end(), vec1.begin(), _$1*2);
sort(vp.begin(), vp.end(), *_$1 <= *_$2);
    // part 2: function applications
for_each(vec.begin(), vec.end(), bind(sinus, _$1*(pi/180.0)) );
    // part 2a: member access
find_if(vecx.begin(), vecx.end(), _$1->*(&XXX::getValue) <= 2);
    // part 3: output
for_each(vec.begin(), vec.end(), cout << delay("---") << _$1 << delay("\n"));
You can see, we had defined a kind of a custom (if not too counter-intuitive) mini-language for the lambda expessions. As each language has to be learnt, we'd like it to be kept simple! So I have only one more thing to add, namely:

1. Control structures


This is really fun, because it's not difficult at all and it let us define very cute lamdbas indeed. The entire code, as it stands in the library, is like that:
    // if_then
// ---

template <class S, class T> void eval_then_expr(S& e, T& t) { e(); }
    // helper: Assgn needs the iterator for: if_then(_$1==0, _$1=44)
// --- OPEN, TODO: make general for e.g.: if_then(_$1>=3, cout << _$1)
// --

template <class T> void eval_then_expr(Assgn<T>& e, T& t) { e(t); }
    template<class S, class T> struct IfThen  : public lambda_expr {
S if_expr;
T then_expr;
IfThen(S s, T t) : if_expr(s), then_expr(t) {}
template <class U>
// OPEN, TODO: check if then_expr needs the val argument!
bool operator()(U& val) { if(if_expr(val))
eval_then_expr(then_expr, val); }
};
    template <class S, class T>
IfThen<S, T> if_then(S s, T t) { return IfThen<S, T>(s, t); }
    // t.b.c....
you see, there are some TODOs, which we'll discuss in the due time, but the technique is simple: first we store the if_expr and the then_expr (as functors), and when the IfThen functor is evaluated, we just evaluate the sub-functors, and make the then_expr dependant on the value of the if_expr. I didn't think myself this would be so simple! As this isn't a ready library, but rather an exploration of some possibilities in code, ther are a lot of open ends here. First, we probably don't need the val parameter in the function call operator. Second, if the then_expr needs the iterator (i.e. _$1), I currently just hacked in only the overload for the assignment. This must be extended with some general forwarder mechamism. But even with this rudimentary support, we can do this now:
    // count occurences
for_each(vec.begin(), vec.end(), if_then(_$1 == 1, globvar(yyy_ctr)++));
    // replace values
for_each(vec.begin(), vec.end(), if_then(_$1 == 1, _$1 = 9));
I think it's pretty useful. Other possible control structures? Well, I think they are possible, but not so useful: a loop, a switch? I don't think that it would be good design. What we really would need sometimes, is rather a possiblility to nest STL algorithms than to use a loop functor. But it's not difficult, maybe something along the lines of:
    template <class U>
bool operator()(U& val) { auto it = val.begin(); // C++Ox
for(it != val->end(); it++)
eval_loop_body(loop_body, it); }
would do, and then we could process a container of containers:
    for_each(cc.begin(), cc.end(), loop_all(cout << _$1));
and perhaps even to extend it like that:
    for_each(cc.begin(), cc.end(), loop_some(_$2 < 1, cout << _$1));
for_each(cc.begin(), cc.end(), loop_counted(10, cout << _$1));
But do we need it? I think it's more a gimmick that an useful feature, because it's not orthogonal: you have a host of special loop_xxx lambdas instead of a single mechanism. What do you think?

2. Summing this all up


In conclusion? There are 2 conlusions:

1. lambda library is cool, all this stuff is cool, I'm cool.

2. Frankly, isn't that all just appalling? All that effort and what we got is an unnatural syntax! And it's not transparent: for each new combination of operators I've got to write new code in the library (or almost)! Makes you think of Phillip Greenspun's Tenth Rule of Programming: "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp." Please Mr. Stroustrup, why don't we have lambda-expressions as core language feature in C++???

Actually, as the things are, it seems like we are going to have lambda functions in the new C++0x standard*! For me, they look like Groovy lambdas (or are they really Ruby's ???), compare**:
Groovy: myMap.each { key, value -> println "$key => $value" }

C++0x: for_each(a.begin(), a.end(), <> (int x) -> int { return sum += x; } );
// or, equivalently, but not much Groovy-like:
for_each(a.begin(), a.end(), <>(int x) { return sum += x; } );
Should we rejoice then? The proposal paper itself lists the problems with lambda expressions:

1. lambda-libraries may render simpler code in basic cases, compare:
    // lambda lib.
os << _$1
// lambda expr.
<> (int i) extern(os) { os << i; }
You see, we need the old, ugly, annoying type specifications again! An we've just started to ejoy the typeless (ehm, generic...) programming in C++! Isn't that what the whole template thing is for! This leads immediately to the second problem:
2. there are no polymorfic lambda functions!!!

The proposal doesn't allow us to write templated, polymorfic lambda function (i.e. ones with implicit type recognition), as it would clash with the concepts feature. More specific, it wouldn't exaclty clash and explode, but rather the concepts couldn't guarantee the correct type checking in this case. So bye bye type freedom? Do we alway have to use the annoying explicite typing? Imagine a lambda function working with an iterator on a list of strings, an then write this type expicitely as input parameter. Ghastly! When you are using a lambda library solution, you'll simply write _$1, and that's it! In such a case, the whole point of the lambda expression, its conciseness, goes down the drain. I can write a standalone functor as well.
Summing up: if have only a simple thing to do, a lambda library solution is simpler. But if there is some more work to do, and we don't have elaborate type specifications for input parameters, the lambda expression solution has clearly an edge, as we don't have to learn a new, special-purpose mini-language, but can just use the standard C++ syntax.

As it seems none of the solutions is optimal: do we need both of them?. And I can say I'm rather not pleased, although the situation here is definitely better than in Python.

3. Personal note


In the past I thought (or rather believed) that you could just do everything in C++ with libraries, operator overloading and template tricks. But I guess I was just dazzled by the template syntax ;-). After this series I think there are limits to the flexibility of C++ which can be only worked around with ugly syntax (or macros).

---
* as in the last "State of C++ Evolution" document they are on the list of the features which are definitely planned to be included, see: "State of C++ Evolution (between Portland and Oxford 2007 Meetings)" of Dec.01.2007 - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2142.html
** C++0x lambda expressions proposal - http://www.research.att.com/~bs/N1968-lambda-expressions.pdf

Wednesday, 25 June 2008

The future of C++

In my recent blog entry* I complained about not exactly knowing where C++ is heading, what features will C++0x contain when it finally appears, and if we'll need to switch to hex as in C++0a ;-). Then I read some interviews with Bjarne Stroustrup** and the things became clearer.


1. The process


The first ambiguity I addressed, was the problem of the very loooong time which C++ needs when acquiring new features, and hinted at the lack of corporate backing. Bjarne on that**:
BS: The progress on standard libraries has not been what I hoped for. ... We will not get ... I had hoped for much more, but the committee has so few resources and absolutely no funding for library development.
and:
BS: There is no shortage of good ideas in the committee or of good libraries in the wider C++ community. There are, however, severe limits to what a group of volunteers working without funding can do. What I expect to miss most will be thread pools and the file system library. However, please note that the work will proceed beyond '09 and that many libraries are already available; for example see what boost.org has to offer.
So that's pretty clear, the industry isn't backing C++ anymore, and the ISO beaurocracy isn't helping here. Java's JSP is definitely more lightweight. Python hasn't a commitee. IBM, Sun (and Google?) are massively backing Java. Previously Google was a stronghold of C++ (MapReduce, BigTable, BigFile), but lately Java seems to take over, in the real "weed language" manner.


2. The features


The second of my questions was the extent of new features which will make it into new standard, beacuse this was a constant source of confusion: thousands of proposals, each in a different state of progress, constantly wandering between approved, considered, considered strongly, considered not so strongly, not considered, demised, etc ;-). Now the new feature scope seems to stabilize at last. Bjarne again**:
BS: I do — based on existing work and votes — expect to get:

Libraries
- Threads
- Regular expressions
- Hash tables
- Smart pointers
- Many improvements for containers
- Quite a bit support for new libraries

Language
- A memory model supporting modern machine architectures
- Thread local storage
- Atomic types
- Rvalue references
- Static assertions
- Template aliases
- Variadic templates
- Strongly typed enums
- constexpr: Generalized constant expressions
- Control of alignment
- Delegating constructors
- Inheriting constructors
- auto: Deducing variable types from initializers
- Control of defaults
- nullptr: A name for the null pointer
- initializer lists and uniform initialization syntax and semantics
- concepts (a type system for template arguments)
- a range-based for loop
- raw string literals
- UTF8 literals
- Lambda functions
The most important feature (IMHO) is**:
BS: The new memory model and a task library was voted into C++0x in Kona. That provides a firm basis for share-memory multiprocessing as is essential for multicores.
and, of course, the auto keyword and lambdas!

Maybe more important is what won't be there**:
BS: The progress on standard libraries has not been what I hoped for. .... We will not get the networking library, the date and time library, or the file system library. These will wait until a second library TR. I had hoped for much more, ...
BS: ... What I expect to miss most will be thread pools and the file system library. However, please note that the work will proceed beyond '09 ...

But an important change of working style will take place:**
... Fortunately, the committee has decided to try for more and smaller increments. For example, C++0x (whether that'll be C++09 or C++10) will have only the preparations for programmer-controlled garbage collection and lightweight concurrency, whereas we hope for the full-blown facilities in C++12 (or C++13).
and we may expect a host of new extensions in the future!

On the other hand, at least when the multithreading is concerned, there are independent libraries available, and they offer some rather high level concepts! Take for example the latest Trolltech's Qt 4.5 framework***, which implements futures, automatic scaling for multicore, has a MapReduce implementation plus concurrent mapping and filtering algorithms. It's just like Java 7's fork-join framework* and the ParallelArray class. Bravo! Other library with high level threading support are of course the Intel's Thread Building Blocks, it's not bad either! At this point we don't need a standard document, as it seems.


3. The prospects


At last, let's pose a more general question: what kind of language wants C++ to be? In the past Bjarne Stroustrup maintained that C++ should be a "general purpose programming language". Contrast this with the statements from the last interviews**:
JB: You are looking at making C++ better for systems programming in C++0x as I understand it, is that correct? ...

BS: Correct. The most direct answer involves features that directly support systems programming, such as thread local storage and atomic types.

JB: C++ is often used in embedded systems, including those where safety and security are top priorities. What are your favorite examples and why do you think C++ is an ideal language for embedded systems especially where safety is a concern, aside from easy low-level machine access?

BS: Yes, and I find many of those applications quite exciting.

For my taste, Bjarne thinks clearly that C++ is an system and embedded programming language: e.g. he expressed his fondness for robotics systems before. That's bad news, because I don't really like embedded programming and automotive :-(((. On the other hand, system programming is quite exciting for me, provided I haven't to fiddle about low level data structures too much.

Allow me a question in this context: for me OO programming is about hiding low level details, seeing the bigger picture. If the strengths of the language lie in the hardware access then maybe it's not so useful for OO programming? We can use C for low level programming (like Wireshark's code does, and it's not a toy system) and do OO in Java or Python? So where's the place for C++ then?

But maybe the future will be totally diffrent? Maybe we won't be programming C++ anymore but rather the Qt platform, which only happens to be written in C++? This would be akin to the Java platform: because C++ doesn't provide a standard ABI, many comapnies are using Qt as to assure the portability of their code between operating systems (among others my current client). Interestingly, not only in GUI applications, abut also in general purpose programming! But what about the (maybe only preconceived) imcompatibility with the standard library, which I bemoaned in one of my previous entries? If I can give faith to Danny Kalev's words****:
And in other news, Nokia completed its acquisition of Trolltech last week.
...
Qt is currently used in Skype, Google Earth, and Adobe Photoshop Elements.
....
After Nokia's acquisition, it seems that Qt will be modified to support Symbian and other mobile environments, or at least POSIX libraries and better support for mainstream C++.
then it seems that not only yours truly is having that impression, and that there will be a remedy soon!

--
* Language trends and waiting blues: http://ib-krajewski.blogspot.com/2008/04/language-trends-and-waiting-blues.html
** An Interview with Bjarne Stroustrup: http://www.ddj.com/cpp/207000124 (but
also http://www.informit.com/articles/article.aspx?p=1192024 , although I don't quote it here)
*** http://labs.trolltech.com/page/Projects/Threads/QtConcurrent
**** C++ Reference Guide: http://www.informit.com/guides/guide.aspx?g=cplusplus (Notes on 25th of June)

Sunday, 8 June 2008

C++ pocket lambda library, part III


As I first wrote my C++ lambda code about a year and a half ago, I didn't know that I'm hitting such a hot topic. I wanted just to reduce the amount of code I had to write, and didn't have any high-church functional programming thingy in mind. But now lamdbads and closures are all the rage: look at all those Groovy articles on developerWorks for example. Even Java 7 will have closures (or won't it?). Definitely, Ruby has made programming languages an interesting topic again!

BTW, do you know how currying and lambdas looks like in Haskell, a popular functional (dynamically and strongly typed) language? If you don't know what it is, we've discussed currying in a previous posting of this mini-series*. In Haskell it is very natural syntactically, you can just write (well, almost, I skipped the T=>T=>T type definition):

    product = a b = a*b
    double = product 2    <-- curried!
    double 2
This is basic, but look at that:

    doubleEach = map (2 *)
i.e. we define a partially evaluated function (as map needs 2 arguments, a function and a list) waiting for application. It's like you'd be using the bind() template of our last posting* in C++. And look at the cute lambda function shortcut: (2 *) is a function (unsurprisingly, as in Haskell everything is a function, contrary to Ruby or Groovy where everything is an object, even the functions ;-)). I like it.


1. Getting exxpresive


Admittedly the code in the 2nd part of this mini series was rather bland*: some hyper technical stuff but not really very entertaining like the 1st part (which was really fun for me to code). I wrote it only for completness' sake, as it is part of my code. I hope this installment will be more fun again.

So let us tackle the last topic we need to implement as to have an usable lambda mini-library: the expression templates. The what? Wy do we need it exacltly? I'm certainly not going to write code like: __expr template <class Expressible> express_anger(Expressible& e); - not in my life!!! Ok, ok, let's introduce the concept gently.

Do you know for example the Boost (e)Xpressive library? It expresses (expressively) regular expressions (Boost Spirit library does in much greater style for grammars) by C++ code constructs. I.e. instead of:

    sregex rex = sregex::compile( "(\\w+) (\\w+)!" );
you can write

    sregex rex = (s1= +_w) >> ' ' >> (s2= +_w) >> '!';
using the domain specific language (buzzword alarm!!!) instead. The string: "\\w+" is replaced by an (Xpressive) expression +_w. You recognize perhaps the usage of placeholders, like our _$1 or _$2, operator overloading and assignment of partial matches to external variables (external to the closure, you'd say in Perl or Groovy). But in this case we don't have a single operation which should create a functor, neither a combination of two different operations. Here we have one operation applied again and again (>> concatenator), and we have to encapsulate it in a single lambda functor!

The same problem emerges in the context of out mini-library.

    for_each(vec.begin(), vec.end(), cout << "-->" << _$1 << "\n");
we have to collect all the items which have to be sent to cout, which can be infinite in number!

Here expression templates come to the rescue. First described by Todd Veldhuizen**, they let us to define recursive templates with operator overloading. And recursion can go infinitely deep down, so we can accomodate our long shift operator sequences with our usual aplomb! What we need is following tree structure:

                  expr
                    ¦
                   op >>
                 /    \
               op >>   \
             /   \      \
           op >>  \      \
         /        \      \
      s1=+_w  ' ' s2=+w_  '!'
True to the "Modern C++ design" book's ubiquitous typelists usage, we can express this runtime structure in compile time with a following monstrous type:

    Op<Op<Op<Char, Expr>, Expr>, Char> rex;
Here, all the structural information has been recorded: just read the type from left to right and compare it with the picture of the parse tree. Now we have to supply the arguments to the constructor of an object of this type and then call a method of the rex object. But we don't do it in classical sense, the construction and the type definition will be done recursively while compiler is parsing the expression. Hence the name of the expression templates #B-D.


2. First real exxpressive code


To convince the compiler to to some sensible work for us we first define the following recursive template:

    // Shift represents a node in the parse tree
    // ---
    template<typename Left, typename Op, typename Right>
        struct Shift  : public lambda_expr
    {
        Left leftNode;
        Right rightNode;
        std::ostream& out;

        Shift(Left t1, Right t2, std::ostream& os)
            : leftNode(t1), rightNode(t2), out(os) { }

        template <class T>
            void operator() (T& t) { Op::print(leftNode, rightNode, t); }
    };
You can see, the structure of the tree node is different form the monstrous type given as example above, well, it's even more complicated. Using this approach we would express the above example tree as:

    Node<Node<Node<Char, Op, Expr>, Op, Expr>, Op, Char> rex;
Ok, why not. If it's supposed to help, I couldn't care less... ;-)

But what has this all with our lambda library? The answer is, we can apply the same concept to the problem of priniting data to cout: supposed we have a following lambda function: cout lt;< "element:" << _$1, we'll can build a type tree like:

                  expr
                    ¦
                  << op
                 /    \
             << op     \
             /   \      \
            /     \      \
         cout "element:" _$1
One interesting thing to note is the ()-operator, which prints the actual node of the parse tree using a mysterious T& t argument: it is the actual parametr of the lambda function, i.e. the uderlying iterator itself!

So if we have the top level tree node (i.e. the expr in the diagram above), we'll just call its ()-operator an the whole tree is printed out, hopefully! Two problem pose themselves here:

1. how to descend to the subnodes of the tree while printing, and
2. how do we get the whole tree structure constructed in the first place?


3. Recursive printing


To answer the first question we need the representation of the recursive printing operation in code:

    struct shiftOp // Represents << operation
    {
        template <class Left, class Right, class T>
            static void print(Left& left, Right& right, T& t)
            {
              print(left.leftNode, left.rightNode, t); // walk down
              left.out << right(t);  // if right needs t? : << _$1*2 ???
            }
 
template <class Right, class T> static void print(std::ostream& left, Right& right, T& t) { left << right(t); // at the beginning }
 
template <class Left, class T> static void print(Left& left, placeholder<1>& right, T& t) { print(left.leftNode, left.rightNode, t); left.out << t; // special case placeholder } };
First we walk down the tree in the depth first, left to right mode (the first print() function). When we arrive at the lowest left node of the tree we do the first print, then go back and print the corresponding right node. Note that we don't walk a physical tree here, we walk a type expression which is organized like a tree! The print() functions will "match" a part of the type-tree, print the matched part, and match the subtype in a recursive manner. So we are treating types in compile time as we'd treat data in the runtime! That's why this is called template META-programming.

Then we need only 2 specialisations: one for the first invocation of the shift operator, where the left operand is the output stream itself, and the second one to deal with our lambda mini-library's placeholder types. The placeholder will be printed directly to the stream. Our tree expression for the simple example above will be then as follows:

    Shift<Shift<cout, shiftOp, "element"-Expr>, shiftOp, _$1> lambda;
Now just imagine how the print() function will work on it.


4. Growing the tree


To answer the second question we need 2 simple ;-) operator overloading definitions:

    // The overloaded operator which does parsing for expressions of the
    //  form "a<<b<<c<<d" => Shift<Shift<Shift<A, op, B>, op, C>, op, D>()
 
// for ostream: cannot be taken by value!
template<class Left, class Right> Shift<Left&, shiftOp, Right> operator<< (Left& left, Right right) { return Shift<Left&, shiftOp, Right>(left, right, left); // left IS an ostream! }
 
// for lambda_expr: must be taken by value! template<class Left1, class Left2, class Right> Shift<Shift<Left1, shiftOp, Left2>, shiftOp, Right> operator<< (Shift<Left1, shiftOp, Left2> left, Right right) { return Shift<Shift<Left1, shiftOp, Left2>, shiftOp, Right>(left, right, left.out); }
The first one starts the recursive template definition at the "cout <<"-expression, an the second one goes one nesting level deeper and one <<-operator application to the right. It's an elaborate syntax, but conceptually it's not a rocket science! Note how the stream (cout) parameter is handed down the expression tree.

Yeeee-ha! We are done now! Let us try it out:

    for_each(vec.begin(), vec.end(), cout << _$1);  // OK
    for_each(vec.begin(), vec.end(), cout << _$1 << "\n" ); // compile error???
    for_each(vec.begin(), vec.end(), cout << i++ << ":" << _$1 << " " ); // again!!!
Did you see that? We still cannot use our lambda library. What is it this time? Well, we need a last building block, and for discussioon of that we need a separate paragraph.


5. External data in lambda functions


The problem is, that inside of an lambda expression we are working with functors, and not with native C++ data types. This means, we need a function call operator for each element of the lambda expression. What can be easier than that! We can make a trivial functor, which, when evaluated returns our literal value i.e. "\n" or ":"!

    // constant_ref
    //  ---
    template<class T> struct Const : public lambda_expr
    {
        T& val;
        Const(T& t) : val(t) { }
        const T& operator()() const { return val; }
        const T& value() const { return val; }

        template <class S> // for different context: needed for Shift!!!
            const T& operator()(S& s) const { return val; } // ignore input
    };
 
template<class T> Const<T> delay(T& t) { return Const<T>(t); }
This can be described as a delayed evaluation: the compiler first wraps the constant in a functor, and the constant's value is used in runtime instead of compile time. Now a lambda like: auto lambda = (cout << _$1 << "\n"); will work. BTW I wonder if that would compile...

Maybe you don't remebmer, but it the IIa part of this series*** I showed the following code snippet:

    // assign to a external counter
    int aaa;
    for_each(vecx.begin(), vecx.end(), aaa += _$1->*(&XXX::value));
only to say, that it wouldn't work yet. What's the problem? Basically the same one: we are using native C++ type instead of a functor. The solution is of course the delayed evaluation from above, but now must cater for the basic operations:

    // variable_ref
    //  ---
    template<class T> struct Var : public lambda_expr
    {
        T& val;
        Var(T& t) : val(t) { }
        T& operator()() const { return val; }
        T& operator()(T& t) const { return val; } // ignore input
        T& value() const { return val; }

        AssgnTo<T> operator=(T t) { return AssgnTo<T>(val, t); }

        template <class S>  // assign from lambda_expr
            AssgnTo<T> operator=(S s) { return AssgnTo<T>(val, s); }
    };
 
template<class T> Var<T> globvar(T& t) { return Var<T>(t); }
Here we enabled the assignment to the C++ data type. The addional operators could be implemented like this:

    // OPEN todo: be more modular!!!
    //  --- return lambda_operation<lambda_exp, oper_type>
    template<class T>
        AddAssg<T> operator+=(Var<T> v, const T& t) { return AddAssg<T>(v.value(), t); }
    template<class T>
        AddAssg<T> operator+=(Var<T> v, placeholder<1>) { return AddAssg<T>(v.value()); }
 
template<class T> Incr<T> operator++(Var<T> v, int) { return Incr<T>(v.value()); }
Now we can finally write:

    int xxx = 0;
    for_each(vecx.begin(), vecx.end(), globvar(xxx)++);
    for_each(vecx.begin(), vecx.end(), globvar(xxx) += 5);
    for_each(vecx.begin(), vecx.end(), globvar(xxx) += _$1->*(&XXX::value));
and, for example:

    for_each(vec.begin(), vec.end(), cout << _$1 << delay("\n") );
    for_each(vec.begin(), vec.end(), cout << globvar(i++) << delay(":") << _$1 );
But not, among others: globvar(aaa) = _$1->*(&XXX::value), as it's not a complete, orthogonal, and idustrial strength library. It was only a little pastime of mine...


6. The End?


Ehm, I thought this will be the last part of the description of my simple implementation, but no, I'll need another blog entry as not to bore you to death with this one. Meantime, the writing of this description has taken more time than the actual implementation itself!!! But I have some more points to make, and at the end of a long post, there are rater unlikely to be given much attention. So long then!

---
* Part II: http://ib-krajewski.blogspot.com/2008/01/c-pocket-lambda-library-part-2.html
** Techniques for Scientific C++: http://ubiety.uwaterloo.ca/~tveldhui/papers/techniques/techniques01.html
*** Part IIa: http://ib-krajewski.blogspot.com/2008/04/pocket-c-lambda-library-part-iia.html


Friday, 30 May 2008

God wrote in LISP: programming and genesis.

Did you ever ask yourself what programming language God used to implement the Universe? I mean, he had a pretty tight deadline - only 6 days - so he must have been using something rather high level. And a rather complex one to boot. And as a programmer, you don't have any doubts thet God must have been using a programming language for the task: without abstraction the task is just too complex ;-).

I came across this song while hearing the OOPSLA podcasts and everything became clear: he used LISP! Hear it here: ( >> )*. I must say, I really like it a lot. It's wonderful: it's like a hymn on a great, dead language. The lyrics come from Bob Kanefsky. All I could trace about him is that he wrote some parody songs, but he must be a programmer himself judging from the quality of lyrics.

And the lyrics are right: Object Oriented languages describe how we humans are thinking about the world, but LISP (or functional languages in general) describe the thoughts of God... so pure... ;-). Let me cite: "Don’t search the disk drive for man.c...". It's almost ontology, I like it :-).

PS: As always there is a monority opinion as well, see http://www.xkcd.com/224.

---
* or here, if embedding works:

.