From: Christian Date: 2001-01-20T16:35:23+09:00 Subject: [ruby-talk:9586] Re: 101 Misconceptions About Dynamic Languages "Larry J. Elmore" wrote: > > Christian> But I do know that > > Mr Stepanov chose to move from Ada95 to C++ to implement his STL. Why? > > Larry> Actually, he didn't. From an interview in DDJ in March, 1995 > (http://www.sgi.com/Technology/STL/drdobbs-interview.html): > > This particular [C++ template] technique became crucial > for my work because I discovered that it allowed me to do many things > that were not possible in Ada. I view this particular design by Bjarne > as a marvelous piece of work and I'm very happy that he didn't follow my > advice." > > Of course, the Ada being referred to here is Ada83. The differences > between Ada83 and Ada95 aren't as great as between C and C++, but Ada95 > is a considerably nicer language. I was thinking of that article when I claimed that Mr Stepanov moved from Ada95 to C++. I should have re-read it and referenced it. However, the spirit of the claim holds: C++'s templates are more suitable to use to implement a STL than Ada95's generics. He even claims that C++ allows him to "do many things that were not possible in Ada". Of coure, he was refering to Ada83, not Ada95, but it is not clear if the situation has changed. > Even with a standard and the STL, > writing portable C++ seems to be somewhat problematic, as this page > relates: http://www.mozilla.org/hacking/portable-cpp.html If you want C++ code to work on a wide variety of compilers, with radically different language support, of course you will become very limited in what features and techniques are available. That is obvious, and says nothing about C++ itself. Is it true that if I write a bad C++ compiler that does not support virtual functions properly, then you must not use virtual functions? Yes, if you want your code to work with my compiler. The truth of the claim that you cannot use templates if you want to write portable C++ code is directly related to the set of compilers that you will be using. Yes, some compilers have bad template support. Conversely, some have excellent template support. Frustrating? Well, only if you need to be that backwards compatible. Are there even Ada95 implementations on every platform that has a bad C++ compiler? Are all Ada95 implementations equal? Sure, if you're in the DoD. But what happens when you let go the reins? > True, but do have a look at > http://www.adaic.com/docs/flyers/95cplus.shtml The author is very eloquent, and careful, at least at first, to limit his language bias (which is wholly acceptable in this context). However, the article is dated. It claims that C++ has no standard, which was true at the time of writing (1992). Because of this, many of his arguments are now false, or at least much weaker. It bemoans the lack of features in C++ that were later introduced in the standard: "C++ classes are the only encapsulation mechanism in the language". Hello, namespaces. That said, some valid points are made convincingly. The fact that proficiency in C++ implies proficiency in the environment in which it is being used is true. Although it could be claimed that this is both obvious and good, the point is taken that it can result in assumptions that fail in a different environment. But there are ways and means, and POSIX is a good start (most *nix's and Win2k are POSIX compliant, although again YMMV). It could be claimed that POSIX is then "a part of C++". True enough, from that perspective. It is well and good that Bjarne refused the temptation to add threads or tasks to C++. These are necessarily application space issues. This point could be argued, but it is true that models change from platform to platform and even from year to year. How can one buil-in, 'standardized' model for threading work in all cases for all purposes for all time? The notion of a microthread is different to that of a thread. By refusing to lock C++ to any model, Bjarne gave us the flexibility to change and adapt. Yes, this means a less strict environment. It also means that we can solve problems quickly and efficiently, and be adaptable to changes. > If it's execution which truly matters, then wouldn't a modern OO > assembler be the way to go? :) Although you mention it sarcastically, the notion of a modern OO assembler is a profound and relevant one. The more things change, the more they stay the same. .NET has an 'object-oriented assembly language': it's called MSIL. Out of interest, here's a sample. Note that this is the input given to the JIT compiler. It includes meta-data that describes interface as well as implementation (I snipped a lot for brevity). .module RothCalcr.dll .class private auto ansi _vbProject extends [mscorlib]System.Object { .custom instance void [mscorlib]Microsoft.VisualBasic.Globals.StandardModuleAttribute::.ctor() = ( 01 00 00 00 ) .export _vbProject { } .field static assembly class [mscorlib]System.Collections.Dictionary _vbEventCollection .method public static void _main() il managed forwardref { .maxstack 8 IL_0000: ret } // end of method _vbProject::_main } // end of class _vbProject .namespace Samples.Assemblies.Download.Calcr { .class public auto ansi CRothCalculator extends [mscorlib]System.Object { .export public Samples.Assemblies.Download.Calcr.CRothCalculator { } .field private static literal int32 StatusMarriedJoint = int32(0x00000000) .field private static literal int32 StatusMarriedSeparate = int32(0x00000001) .field private static literal int32 StatusSingle = int32(0x00000002) .method public instance int32 GetAmount(int32 agi, int32 status) il managed forwardref { // Code size 96 (0x60) .maxstack 2 .locals init (int32 V_0, int32 V_1) IL_0000: nop IL_0001: ldarg.2 IL_0002: stloc.1 IL_0003: ldloc.1 IL_0004: switch ( IL_0017, IL_002d, IL_0043) IL_0015: br.s IL_0059 IL_0017: ldarg.1 IL_0018: ldc.i4 0x27100 IL_001d: ble.s IL_0023 } // end of method CRothCalculator::GetAmount .method public specialname rtspecialname instance void .ctor() il managed forwardref { // Code size 7 (0x7) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: ret } // end of method CRothCalculator::.ctor } // end of class CRothCalculator } // end of namespace Samples.Assemblies.Download.Calcr > Larry> Seriously, though, maintenance is an > important part of much software engineering. Yes, but less so over time. The situation where a company has millions of lines of code to maintain over many years is happily going away. Of course, there will be the need for legacy. But as hardware and deployment environment evolves ever faster, maintenance can often be a poorer choice than a re-write. Yes this is a weak point, but is it not true that given that the number of programmers increases non-linearly, the amount of software increases non-linearly, thereby reducing the importance of 'legacy code'? I do not mean to argue that maintenance is not important because C++ doesnt support it well (it does). I argue that, more generally, the sheer amount of new code that will be written in the future will make that legacy code far less important than it was when there were fewer programmers and a relatively stable deployment environment. Case in point: my profession. I am a game developer. Each new title, I re-write the systems from scratch. Very little is used from one game to the next. It just isn't meaningful anymore. Yes this is an extreme case, but it demonstrates the importance of expressibility and practicality over maintainability. I fear that I am in dangerous water here and that I am not expressing myself well, so I'll move on :). > > I am familiar > > with Lisp. Who can get a degree (or two) and not be? No, I don't use > > it professionally. I don't use ML professionally either, but that > > doesn't mean I have no understanding of FP. FP rocks, we all know > > that. It is also very intellectual, and above most people. But that > > doesn't mean that we should throw away the notion of functions as > > first-class-objects. > > Huh? Ruby does not have functions as first-class objects. You cannot pass a function as an argument, nor return one as a result. > > Now, what about continuations as first-class-objects? > > As in Scheme? Yes, or C++ with microthreads. > > Or a 'stackless' Ruby (http://www.tismer.com/research/stackless/)? > > That might be interesting. I am very interested in coroutines. This is why I played around with stackless Python. Then I found that using Win32 fibres (see CreateFibre()) and a few pages of code I can do so directly in C++. I wonder what could be done with Ada95? How would the use of fibers in Ada95 contend with the built-in task model? Oops. Christian.