C++11 Makes Competitors Go Rusty | Nerds Central
C++11 Makes Competitors Go Rusty
Rust is breaking free, but does it have any real world value?
C++11 is out (has been for a while) and brings many things from Tr1 into the standard.
Things like managed memory (shared_ptr) and lambdas and template meta programming (TMP)
bring new paradigms to the beating heart of C++. So much so, I would argue, that C++11
makes some of the 'new kids on the block' (think Go and Rust) look pretty pointless.
少し前に C++11 は正式なものとなり、Tr1 の多くの事柄が標準となりました。メモリー管理
(shared_ptr) やラムダのようなもの、それにテンプレートメタプログラミング(template meta
programming, TMP) は C++ の beating heart に新しいパラダイムを持ち込みました。それはと
ても大きなものなので、C++11 は 'new kids on the block' の一部 (think Go and Rust) を
ほとんど意味のないものにしてしまったのだとわたしは主張します。
'Go Rusty' as in go old, look old, corrode and otherwise become less good. This is
really just a play on words because both Google and Mozilla have been playing the 'new
object oriented native language' game recently. I can really see the motivation,
especially from organisations which want to create highly stable, performant,
cross-platform systems like browsers. The issue I see with both Go and Rust is that
they are solving yesterday's problems. C++/Tr1 has also solved many of the same
problems without needing a new compiler, for teams to learn a new language and
introducing all those compatibility issues with existing code.
'Go Rusty' as in go old, look old, corrode and otherwise become less good.
これは実際には単なる言葉遊びに過ぎません。なぜなら Google と Mozilla の両方ともが最近
になって 'new object oriented native language' ゲームをプレイしているからです。わたし
は動機、とりわけ highly stable で高性能でブラウザーのようにクロスプラットフォームなも
のを望む組織からの同期をわたしは理解できます。わたしが Go と Rust の両方で見つけた問題
は、これら二つの言語が過去の問題を解決しようとしていることです。C++/Tr1 はすでに同じ問
題の多くを、新しいコンパイラーや新しい言語のチームへの教育、既存のコードに対する互換性
問題すべての introducing を必要とすることなしに解決してしまっています
So Boost and Tr1 are cool, but not part of the standard... Well, no longer, a large
proportion (if not all) of what Go and Rust are trying to do with a complete new language
C++ has done by adding to an existing one via the 2011 standard.
ですから Boost や Tr1 は cool だけど標準のものではないという意見はもはや当てはまりませんし、
Go と Rust が完全に新しい言語でもって試みたことの大部分は
C++ が2011年の標準を通じて追加された既存のものによって成し遂げました。
From Wikipedia:
"
Rust is an experimental, concurrent, multi-paradigm,compiled programming language
developed by Mozilla Labs.[1] It is designed to be practical, supporting pure-functional,
concurrent-actor,imperative-procedural, and object-oriented styles. The main developer is
Graydon Hoare, who began work on the system in 2006; Mozilla became involved in 2009.[2]
In 2010, work shifted from the initial compiler, written in OCaml, to the self-hosted
compiler written in Rust itself.[3] It successfully compiled itself the following
year.[4] The self-hosted compiler uses LLVM as its backend. Version 0.1 of the Rust
compiler was completed in January 2012.[5] Mozilla described it as an alpha release,
suitable for early adopters and language enthusiasts.
"
Go is a compiled, garbage-collected, concurrentprogramming language developed by
Google Inc.[6] The syntax of Go is broadly similar to that of C: blocks of code are
surrounded with curly braces; common control flow structures include for, switch, and
if. Unlike C, line-ending semicolons are optional; variable declarations are written
differently and are usually optional; type conversions must be made explicit; and new
go and select control keywords have been introduced to support concurrent programming.
New built-in types include maps, Unicode strings, array slices, and channels for
inter-thread communication.
"
I can totally get why people want to write new programming languages. Sometimes it becomes
very annoying dealing with some seemingly stupid, repetitious and just plain awkward
aspects of many main stream languages. However, I learned from Robert Sales and Micro Focus
that a much more productive solution to annoying syntax is to make the compiler able to work
out what you mean with better syntax and leave in the old syntax as well. Why is this better?
Here are some (but not all) the issues created by introducing a new language into an
existing echo-system (which all projects are these days):
わたしはようやく、なぜ皆が新しいプログラミング言語を使いたがるのかを理解できました。
Sometimes it becomes very annoying dealing with some seemingly stupid,
repetitious and just plain awkward aspects of many main stream languages.
しかしながらわたしは、 Robert Sales と Micro Focus から、
annoying syntax に対するより一層 productive な solution は
コンパイラーがあなたがより良いと考えている構文を cut したり
古い構文をそのままにしておくようにできるようにすることであると学びました
なぜこれが better なのでしょうか?
Here are some (but not all) the issues created by
introducing a new language into an existing echo-system
(which all projects are these days):
Massive but ineffective - lots of engineering does not make something worth while or
work well. Normally the reverse is the case!
Compatibility: The new language will have to talk with older languages. Types will
have to be translated; memory models will need to be aligned and compilers will need
to 'play nice' together. This is not just as the compiled object level but at the ABI
level during linking etc.
互換性:
新しい言語は古い言語と対話をしなければなりません、型は変換されなければならないし、メモ
リーモデルをそろえる必要があってコンパイラーは 'play nice' together しなければならな
いでしょう。これはコンパイルされたオブジェクトのレベルの話ではなく、リンクの際の ABI
レベルでの話です。
Performance: This new language is super fast. Great, but it will have to work with
existing systems. The interface between the two will slow stuff down a lot. Either
that interface will have to be messy (see Compatibility above and/or JNI) or via a
marshalling system (Protocol Buffers, Avro etc). The problem with marshalling between
dissimilar systems is that it is really slow. It might seem like a good idea (just
like the steam gun right) but it is a stupidly expensive and complex way to solve a
problem of one's own invention. Such protocols are great for clustering, cloud
processing and client-server work; they are just wrong headed for gluing systems
together to work around using different languages in one system. Keep it simple.
性能:
この新しい言語は super fast で Great ですが、既存のシステムと動作しなければなりません。
それら二つの間のインターフェースは大幅にスローダウンさせる要素となるでしょう
Either that interface will have to be messy (see Compatibility above and/or JNI)
or via a marshalling system (Protocol Buffers, Avro etc).
dissimilar systems 間でのマーシャリングの問題はそれが本当に遅いということです。
It might seem like a good idea (just like the steam gun right)
but it is a stupidly expensive and complex way to solve a problem of one's own invention.
Such protocols are great for clustering, cloud processing and client-server work;
they are just wrong headed for gluing systems together
to work around using different languages in one system. Keep it simple.
Build: Build system complexity has been one of the biggest headaches in all the major
projects I have seen over the last few years. Build systems are getting more and more
complex as the demands of heterogeneous programming and dependency management push
technology beyond the sane. Frameworks like maven, msbuild and even good old make work
fine if a project uses one language; they generally degenerate into a big ball of mud
otherwise.
ビルド:
ビルドシステムの複雑さは過去数年わたしが見てきたすべての主要なプロジェクトにおいて
biggest headaches のひとつとなりました。heterogeneous programming に対する要求や
dependency management push technology beyond the sane
に伴ってビルドシステムはますます複雑になってきています。
maven や msbuild のようなフレームワークであるとか、あるいはgood old な make でさえも
ひとつのプロジェクトでひとつの言語しか使っていないのであれば問題なく働きます。
they generally degenerate into a big ball of mud otherwise.
Debugging: Debugging across languages is really tricky. I should know, I have spent a lot
of time doing it over the last few years. For example, even debugging from COBOL into Java
and back on the same JVM is tricky because a Java debugger does not understand COBOL and
the same is the case in reverse. Jumping between native languages can be even harder when
their internal data structures, interpretations of indirections (pointers etc) and
(shudder) interpretations of thread state are completely different.
デバッグ:
複数の言語をまたがってのデバッグは本当に tricky です。I should know,
過去数年間にわたり、わたしはそういったことのために多くの時間を費やしました
たとえば
even debugging from COBOL into Java and back on the same JVM is tricky
なぜならJava のデバッガーはCOBOLを理解しないし
その逆にCOBOLのデバッガーはJavaを理解しないからです
Jumping between native languages can be even harder
when their internal data structures,
interpretations of indirections (pointers etc)
and (shudder) interpretations of thread state are completely different.
Team Training: Assembling a team of people who know one language well is hard enough;
doing so across multiple languages is extremely challenging. Some people will be
prepared to learn new stuff but not all will. Time pressure, as we all know and love
it now, generally does not leave time to learn a language up front in a project.
チームのトレーニング:
ひとつの言語をよく知る人たちでチームを組むことはとても困難なことです。
複数に言語にまたがってそういったチームを編成するのは extermely challenging です。
Some people will be prepared to learn new stuff but not all will.
Time pressure, as we all know and love it now,
generally does not leave time to learn a language up front in a project.
Team Embedded Knowledge: It is very hard to keep the knowledge of a multi-language
project spread throughout a team. It is even harder to keep that knowledge 'live' as
team members leave and join. Because language interoperation patterns are less well
known and less standardised that intraoperation patterns, unique embedded knowledge
tends to build up in teams.
Version Management (language/runtime): Different languages frequently have slightly
different life-cycles and dependency management issues. These accumulate to cause
challenges in revision control.
(言語とランタイムの) バージョン管理:
別々の言語はしばしば大きく異なるライフサイクルと dependency management を持っています。
These accumulate to cause challenges in revision control.
Tooling Costs: Good tooling can be expensive. Tools like profilers, code complexity
analysis systems and test coverage checkers can all be pretty costly to buy. Whilst
some have good open source alternatives, these have the embedded cost of maintenance
and installation. Again, multiple languages usually means that a team needs more tools
and hence more cost.
Licensing Of Runtimes And Libraries: We often get complacent thinking all libraries
and runtimes will be free. This in not the case. Even if they are 'free' as in they
cost no money, their licensing requirements might complicate commercial arrangements.
If they are commercial and have enforced licensing this introduces a whole new level
of complexity. One really nasty situation is when two completely different forms of
code hardening in the licensing systems do not play nicely together. I have seen it
happen and it is not pretty.
ランタイムやライブラリーの Licensing:
Lifespan And Sundown: All things come to an end. Support for a language or, more often,
a version of a language will come to an end. Managing these life cycle events can be
challenging in a single language environment. When more than one language enters the
picture, the cycles will almost certainly not coincide. The less common a language is,
the more likely that is will be sundowned whilst the products using it are still
current. It is fairly easy to get into a situation when one can never actually release
on a completely stable, current set of components.
Lifespan And Sundown:
すべてのものごとには終りがあります。ある言語に対するサポートもそうですし、もっと頻繁に
あるのが言語のあるバージョンのサポートが終了することです。これらの life cycle events
を管理することはsingle language environment において challengig となる可能性があります。
二つ以上の言語が視野に入ってきた場合、そのサイクルは almost certainly not coincide
となるでしょう。
The less common a language is, the more likely
that is will be sundowned whilst the products using it are still current.
It is fairly easy to get into a situation
when one can never actually release on a completely stable,
コンポーネントの current set
Startup And Shut-down Sub-Systems: A programming language is just the code right? Wrong -
generally there is a lot more to it than that. It can be tricky even to mate up C with C++
projects because C++ has to initialize statically referenced objects before main is called.
Many other languages have even more complex issues to do with threading, signals and
loaders which all get in each other's way when building a mixed language system.
サブシステムのスタートアップとシャットダウン:
A programming language is just the code right?
Wrong - generally there is a lot more to it than that.
C++ では main が呼び出されるよりも先に静的に参照されているオブジェクトの初期化を行わなけ
ればならないのでC++を含むCプロジェクトでさえ混乱を招くほどtrickyとなる可能性があります。
他の多くの言語では、スレッドやシグナル、
mixed language system を構築するときに
all get in each other's way するローダーを扱うときに
もっと複雑な問題を抱えさせします。
Paradigm Contamination: Seeing Java written in the in style of COBOL is quite an eye
opener. I am not a COBOL bigot either way; it is a solid language that is really good
for some things. Java is also a solid language, but it really should not be programmed
in the style of COBOL. However, where the two languages touch the chances are the
COBOL will look like Java and the Java look like COBOL. I have seen exactly the same
thing with C# and C. If a programmer is working in C and writing a bit of Java, the
chances are the Java will be C like. Equally, the natural paradigm of a cross language
API tends to be a hybrid of both languages. Whilst these things are to be expected,
they are horrid. The code looks bad, smells bad and is hard to test or maintain.
パラダイムの汚染:
COBOL のスタイルで書かれた Java を見ることはかなり衝撃的なことです。わたしはいずれにし
ても COBOL bigot ではありませんが、COBOL は soolid な言語で、一部の事柄に対してはとて
も優れた代物です。Java もまた solid な言語ですが、COBOL スタイルでプログラムされるべき
ものではありません。わたしは C# と C とでのこれとまったく同じことを見たことがあります。
あるプログラマーがCを使っていて、ちょっとだけJavaで書くことをしたら
その Javaコード は C で書いたもののようになることでしょう。
同じく、cross language API の自然なパラダイムは両方の言語の hybrid となる傾向があります。
Whilst these things are to be expected, they are horrid.
そのコードは見た目も悪く、悪臭を放ち、テストや保守が困難です。
Brain Strain (the bilingual problem): Children which are brought up from babyhood as
bilingual usually learn to speak more slowly than their monoglot contemporaries. Can
the analogy be brought over to programming? In the absence of hard evidence from
psychologists, it seems at least likely and reasonable to assume that coding progress
will be slowed down by the extra cognitive burden of working in more than one language.
... and so on ...
So what am I saying?
I hope I have established that in modern environments, introducing new languages carries
with it a lot of down sides. To put it another way - there has to be an overwhelming need
before there is an overall benefit in introducing a new language rather than using a well
established general purpose language. Go and Rust are compiled straight to native and so
the existing candidate as an alternative is C++. C++ has huge pre-existing libraries and
is (with the possible exception of C) the most likely language in which other native code
will be written. Even if there is a large legacy C library set, C++ to C is a well know
interoperation with some issues from the list above but not too bad.
So, is there an overwhelming need to replace C++ with Rust or Go?
I would definitely say NO! Simple paradigm following within the pantheon of C++ allows
this language to behave just as well as Rust or Go - or at least that is what I fully
expect.
Let us think about the big ideas behind Go: It is simple, clean and has garbage collection.
Well, one can write simple clean C++ and use share_ptr. Just because C++ can be super
complex does not mean it has to be.
Let us think about the big ideas behind Rust: Type inference, static assertions (checks),
simple constant rules to facilitate reasoning about multi-threaded execution. These are
nice things indeed. However, using lambda's correctly along with other templating
techniques makes C++ straightforward for multi-threaded reasoning. Template Meta
Programming should be able to perform most of the type reasoning which the compile time
checks are performing in Rust. C++11 has type inference. It does not use clever code branch
analysis like Rust, but it is there (auto and decltype).
The ideas in Rust are definitely more tricky to implement in C++ than those in Go; however,
the effort required to do so is , IMHO, trivial compared to creating, using and maintaining
a new language. Further, the effort to replicate Rust's good features in a C++ paradigm is
much less than the effort of dealing with a new language (as described above).
Rust におけるこのアイデアは C++ で実装するには Go よりも格段にトリッキーなものです。し
かし、わたしの見るところでは実装するのに要求される労力は新しい言語を作って、それを使っ
て、メンテナンスをすることに比べればたいしたことがないものです。加えて、C++ のパラダイ
ムで Rust の good features を replicate するための労力は新しい言語を扱うための労力と大
差ありません。
Here is a very trivial bit of C++ with which I was playing this morning:
// VSPL.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
bool parse_numbers(Iterator first, Iterator last)
{
using qi::double_;
using qi::phrase_parse;
using ascii::space;
bool r = phrase_parse(
first,
last,
double_ >> *(',' >> double_),
space
);
return first == last;
}
}
int main()
{
typedef std::istream_iterator<int> in;
std::string code = "1,2,3,4,5,6";
std::cout << (client::parse_numbers(code.begin(), code.end())?"All is well":"It barfed") << std::endl;
auto exiter = [] (const int v) { if(v==123)exit(0); } ;
for_each(in(std::cin),in(),exiter);
}
Here we can see a lambda being used as an immutable first order entity. The for_each
could be parallel or serial, it really does not matter. We can also see type inference
where the type of the lambda is inferred from its internal code (in this case void).
Here we can see a lambda being used as an immutable first order entity.
The for_each could be parallel or serial,
it really does not matter.
We can also see type inference
where the type of the lambda is inferred from its internal code (in this case void).
I did not include this here because it is a clever bit of code; Indeed, my motivation is
quite the opposite! I am working on a parser for my research language VSPL using the Spirit
library in Boost. The above was just a play thing to make sure the project was set up
correctly. However, easy features like type inference, lambdas, name spaces and internal
DSLs are so accessible in C++ now that they are just natural in the most trivial coding
example. I just don't see a strong enough argument for new languages to replace C++.
I did not include this here because it is a clever bit of code;
わたしはここではこれを含みません。
なぜならこれは clever bit of code だからです。
Indeed, my motivation is quite the opposite!
I am working on a parser for my research language VSPL using the Spirit library in Boost.
The above was just a play thing to make sure the project was set up correctly.
However, easy features like type inference, lambdas, name spaces and internal
DSLs are so accessible in C++ now that they are just natural in the most trivial coding example.
I just don't see a strong enough argument for new languages to replace C++.