Re: The D Programming Language
AJ wrote:
Hi there,
James Kanze wrote:
<snip>
That depends. Library support isn't as good as core support
when it isn't as good. The fact that it is library and not core
isn't a disadvantage per se---I'd say that almost the opposite
is true. But you do have to compare the level of support; there
are some things that simply cannot be supported in a library
alone.
I think I agree, though I also think we need a clear definition of a
"library" and of "core-language" support. It is unclear at this point
whether a library can be "magic" in the sense that it does things a
regular user couldn't.
Of course it can be. There's no I/O whatsoever in the core C++,
so you couldn't write to a file unless there's some extra magic.
In some cases, the actual reason for putting something into the
library is that it cannot be implemented without magic.
It is also unclear what is meant by C++ any more. Is C++ simply the
language, or does it include the STL? I don't think I would include the
STL into the definition of the "core" C++ language.
Formally, C++ is defined by ISO 14882: if something is in ISO
14882, it's part of C++, if it's not, it's not. In practice, of
course, we tend to use a looser definition, and most people
would consider things like Boost as "C++" in some sense of the
word, not strictly speaking part of the language, but certainly
something available and to be used.
Here's one example: Multi-threading and thread safety.
And this is one of them: you definitly have to specify at the
language level when it is safe to access objects, and when not.
For 1: In D, this is achieved in a super-clean and succinct manner:
Adding a synchronized keyword.
That, on the other hand, is a serious defect, at least if it is
done as in Java. It forces locking to obey scope rules.
How is this a serious defect? It merely follows RAII, which is among
C++'s strengths (say, vs. C#/Java). This seems very orthogonal to me.
One of C++'s strengths is that you CAN define classes which
release resources in their destructor. Another is that they are
exactly that: classes, and that you can use them in many
different contexts, e.g.: shared_ptr< mutex::scoped_ptr >. Or
access the same facilities without using them at all---I see no
reason why you couldn't e.g. unlock a mutex in the "destruction
function" of a shared_ptr to something else.
Note too that even with an on stack object, you can "prepare" in
scope before e.g. acquiring the mutex.
Just because an idiom is superior 95% of the time doesn't mean
that we have a right to ban the other 5% of the uses.
In C++, one must add error-prone boilerplate for critical
sections (or mutexes, or locks) and in general the syntax is
verbose and a hassle.
I've never noticed this. My experience in Java is that the
synchronized keyword is a major problem; it's much easier to
write effective, correct code in C++ (using e.g. boost::mutex).
I'm not very familiar with Java's synchronized, unfortunately. I'll try
to read up on it.
The problem is that 1) it forces synchronization to obey scope,
absolutely and always, and 2) it is bound to an object---you end
up doing "new Object" just to get a mutex.
For 2: In D, synchronized is built-in. No need to download or
install anything else. No need to check additional
documentation on library usage.
I'm not sure I understand this point: if the functionality is
part of the standard library, there's also no need to download
or install anything else, and what's the difference between
having to check library documentation, and having to check
language documentation? The standard library IS part of the
language.
Well, this is a tricky semantically (what is what), as I mentioned
above. The point is that, as it stands, I believe there is _no_ C++
support for synchronized of any sort, without relying on an external
library.
At present, there is NO C++ support for synchronization of any
sort, period, since it is impossible to provide the support in a
library. So we end up counting on extensions to the Posix
support, or whatever, which is really only specified for C.
This is a recognized problem, the committee is working on it,
and my impression is that the committee feels that it is one of
the most important problems---whatever else may happen, the next
version of C++ will not ship without some sort of thread
support.
[...]
One other serious legacy flaw in D (inherited from C/C++) is that it
doesn't do away with undefined behavior. It's close, I think, but it's
unfortunate that the holes aren't closed entirely.
No language manages to completely do away with undefined
behavior. Although C++ could surely do better in this regard;
there's a lot of unnecessary undefined behavior.
I have doubts about that first assertion. Surely there are academic
languages out there that do.
Not and provide thread support. (There probably are academic
languages which avoid it completely. At a cost of not providing
enough other features to be useful for anything.)
Moreover, I wasn't aware that fully-managed
(e.g. no unsafe/PInvoke), CLS-compliant C# contained any UB. Does it?
I don't know about C#, but Java has some. Precisely in the case
where two threads access the same object without the necessary
locks. I'd be very surprised that C# managed to avoid that one
as well---doing so has an enormous cost in run-time. (Of
course, they don't call it undefined behavior. That would be
uncool. But the actual effect is exactly the same.)
I
also think pure ECMAScript is safe in that regard.
I'm not familiar with it, but you may be right. I suspect that
a purely scripted language could be made to avoid all undefined
behavior. If nothing else, just put a lock around every
instruction.
However, what is important is whether a programmer can do his/her task
efficiently with the language and the associated tools, not whether it
is done by the core language or by the standard library or by a
third-party library. Whether a language facilitates good libraries or it
hinders good development tools, much of the credit/blame is to the language.
'Efficiently' is the key. Adding certain things to the core language can
improve efficiency by an order of magnitude. "Can be done at all" isn't
the same as "can be done simply and easily." :)
Formally, if it is part of the standard library, the compiler
can know about it, and do whatever is necessary. This is often
the case for standard library functions (like memcpy) in C. To
date, it's not become the case for anything in C++, at least to
my knowledge, although the standard certainly allows it. I
think, however, that part of the goal is to design things so
that the compiler can do the job well, not just for standard
components, but for any user defined class.
I think this is what Walter disagrees with. If you're gonna make a
special case for some part of the "standard" library, then why not make
that feature part of the "core" language in the first place?
I think that the C++ committee would also prefer that everything
in the library could be implemented as if by a user. (Except
for things that intentionally cannot be, like I/O.) But
formally, there's nothing to disagree with: the standard very
strictly specifies what's in the library, and forbids you to go
around hacking it. So the compiler can know.
In practice, most C compilers do---it's hard to imagine a C
compiler to day that doesn't generate memcpy inline, using
built-in knowledge, for example.
You get the
advantage of nicer syntax and semantics with the advantage of clean,
intrinsic compiler support without having to "cheat" with a "magic"
library (which is what he called the worst of both worlds).
Having the library depend on compiler magic for performance is
not an ideal situation. On the other hand, there are definite
cases where you don't want to encumber the basic language with
additional syntax, but you can't implement the functionality in
the basic language: C and C++ I/O are a classical example (and
most other languages, at least before C, did put I/O in the
basic language). For things like arrays and string, of course,
the ideal would be that the language itself allows a definition
such that you don't need to have it in the language, that the it
could very well be part of the library, with no noticeable
difference. Obviously, C++ (and no other language I know) has
reached this ideal, but the committee is working on it; I
believe, for example, that the notion of what a compile time
constant is is being extended, and there is an attempt to permit
{...} type initialilzation for user defined types.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]