I am not sure if this was brought up before, but this language is quite
interesting when compared to C++ (and others such as C, C#, Java):
http://www.digitalmars.com/d/index.html
The comparison:
http://www.digitalmars.com/d/comparison.html
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
>Hello folks,
>
>I am not sure if this was brought up before, but this language is quite
>interesting when compared to C++ (and others such as C, C#, Java):
>http://www.digitalmars.com/d/index.html
>
>The comparison:
>http://www.digitalmars.com/d/comparison.html
Mumble mumble mods... how are we supposed to reply here? :-) There's
no question, just a general opinion. Perhaps that we only like C++ and
assembly? :-O
{ One fruitful avenue of discussion might be how to emulate the pure D
features in current C++, or how some of these features could or will be
supported in the C++0x language or its standard library. -mod/aps }
--
Gennaro Prota
[To mail me, remove any 'u' from the provided address]
> Hello folks,
>
> I am not sure if this was brought up before, but this language is quite
> interesting when compared to C++ (and others such as C, C#, Java):
> http://www.digitalmars.com/d/index.html
>
> The comparison:
> http://www.digitalmars.com/d/comparison.html
1. Yes, it has been brought up before.
2. It was off-topic then, and it is still off-topic now.
This group discusses the C++ language. Not the relative merits (in
someone's mind) of C++ versus X, regardless of whether X is COBOL,
FORTRAN, Forth, Ada, or anything else, except C.
Try comp.programming if you want to discuss the relative merits of
different languages.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
We have tried that before, but as the designer of the D language believes
that we should compare core language only, and that features already
implemented in the C++ library doesn't count, this avenue hasn't been very
fruitful.
Some of us, who are not compiler writers, actually see a great advantage in
being able to add library features.
Bo Persson
> >I am not sure if this was brought up before, but this language is quite
> >interesting when compared to C++ (and others such as C, C#, Java):
> >http://www.digitalmars.com/d/index.html
> >The comparison:
> >http://www.digitalmars.com/d/comparison.html
> Mumble mumble mods... how are we supposed to reply here? :-)
Maybe you're not. Not every posting needs a response.
I'll admit that as a moderator, I would have rejected it, on the
grounds that it is really an announcement, and D isn't something
new, meriting a new announcement---anyone who regularly reads
this group is aware of its existance, knows something about it's
relationship to C++, and above all, knows how to find
information about it if he wants.
If I didn't know Walter to be a man of impeachable integrity,
I'd suspect him of putting the OP up to it, in order to get more
exposure.
> There's
> no question, just a general opinion. Perhaps that we only like C++ and
> assembly? :-O
> { One fruitful avenue of discussion might be how to emulate the pure D
> features in current C++, or how some of these features could or will be
> supported in the C++0x language or its standard library. -mod/aps }
Do we really want another endless discussion on garbage
collection? I suggest that we put it off until someone has
something new to say, that isn't just a repetition of what we
said the last time around. (That doesn't mean that I'm against
garbage collection---just against endless discussions that don't
change anyone's mind.)
--
James Kanze (Gabi Software) email: james...@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
I don't believe there's much point to discuss library features in
language X vs language Y because any library can be implemented in any
language. Heck, I once posted that a garbage collector could not be
implemented in Java, and someone replied that it was possible and
someone had done exactly that. I've even heard of a FORTRAN compiler
written in TECO!
Isn't it a lot more interesting to discuss core language features that
make it easier/harder to write certain types of code (and thereby
libraries)? Given all the core changes proposed for C++, certainly a lot
of people feel the core language support is inadequate.
But what I think is fruitful to discuss or not only pertains to what I
decide to post - I don't control these discussions. I'm not a moderator
here.
> Some of us, who are not compiler writers, actually see a great advantage in
> being able to add library features.
I don't know of any computer language that prevents one from writing
libraries for it, even TECO (gads, I'm old). But certainly, it's the
core features of a language that have a powerful influence on the style
and ease of building libraries for it.
Building template libraries for C++ is a major source of activity and
interest, so it's fun to compare it with D programming language
templates: http://www.digitalmars.com/d/templates-revisited.html
> I don't believe there's much point to discuss library features in
> language X vs language Y because any library can be implemented in any
> language.
>
> [...]
>
> I don't know of any computer language that prevents one from writing
> libraries for it, even TECO (gads, I'm old). But certainly, it's the
> core features of a language that have a powerful influence on the style
> and ease of building libraries for it.
Yes, you said it; but isn't it contradictory to what you said above?
For example, in Pascal you cannot write a single library procedure that
sorts both array [1..10] of integer and array [1..20] of integer. Thus
it is important for the core language to have enough flexibility and
power to accommodate good library designs.
But considering only the core language features would be a serious
mistake; it would be an unfair disadvantage to a language which has
preferred library solutions to core language solutions. For example,
under that criterion, you would say "C99 can handle variable-length
arrays but C++ can't; C99 can handle complex numbers but C++ can't."
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.
--
Seungbeom Kim
> But considering only the core language features would be a serious
> mistake; it would be an unfair disadvantage to a language which has
> preferred library solutions to core language solutions. For example,
> under that criterion, you would say "C99 can handle variable-length
> arrays but C++ can't; C99 can handle complex numbers but C++ can't."
And that Fortran can handle IO, but C++ (and Java!) can't.
There is no cut and dried answer. At some early point, the
developers of C decided, for example, that IO would be relegated
to the library. And then designed the language in such a way
that this would be possible (e.g. in C, varargs, conversions
between pointers and pointer arithmetic, etc.). Similarly, C++
has generally made the choice to enrich the language in such a
way as to permit a library solution, rather than solve the
problem directly. There are, of course, limits to what one can
do in this direction, and at least some of the proposals for the
next version of the standard---things like threading, garbage
collection or concepts---require or benefit from some help from
the compiler.
In general, as a user, what interests me is how efficiently the
language supports my application. Whether that support comes in
the form of language features, standard library, or even, at
least to some degree, third party libraries, is really
irrelevant. (Considering support from third party libraries is
somewhat arguable; the fact that Java has Swing, where as C++
depends on third party libraries for GUI support, is a definite
disadvantage for C++ if your application needs GUI support.)
--
James Kanze (Gabi Software) email: james...@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
--
The C++ language defines features that can optionally be implemented as a
library, or built into the compiler. The standard allows, but does not
require, specific compiler support for these features. In my opinion, they
are still part of the language.
The D language requires compiler support for strings, the C++ language
allows it. That doesn't mean that there are no strings in C++.
>
> Isn't it a lot more interesting to discuss core language features
> that make it easier/harder to write certain types of code (and
> thereby libraries)? Given all the core changes proposed for C++,
> certainly a lot of people feel the core language support is
> inadequate.
Some people feel the need for more features. I am not sure that they are all
widely missed by others. Variadic template arguments are not high on my wish
list, for example.
>
> But what I think is fruitful to discuss or not only pertains to
> what I decide to post - I don't control these discussions. I'm not
> a moderator here.
It was I who didn't find it fruitful to compare the languages, when you
concentrate on a core only comparison. Without the string, vector, and
complex classes, C++ admittedly is just half a language.
I respect your opinion, but just don't find it interesting to discuss
languages from that point of view.
Bo Persson
Seungbeom Kim wrote:
<snip>
> But considering only the core language features would be a serious
> mistake; it would be an unfair disadvantage to a language which has
> preferred library solutions to core language solutions. For example,
> under that criterion, you would say "C99 can handle variable-length
> arrays but C++ can't; C99 can handle complex numbers but C++ can't."
It would also be unfair to consider library support as good as core
language support for (at least) two reasons:
1) Syntax.
2) Convenience.
Here's one example: Multi-threading and thread safety.
For 1: In D, this is achieved in a super-clean and succinct manner:
Adding a synchronized keyword.
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.
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.
In C++, one must install and add a dependency to boost (non-trivial) or
pthreads (still non-trivial), or sacrifice platform-independence and go
Win32.
On the other hand, D isn't available by default almost anywhere, whereas
C++ is, so that's one disadvantage. However, wasn't this the case with
C++ vs. C too, at some point?
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.
> 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." :)
Cheers,
-Al.
--
True, but you can write two library procedures to do it, the point being
you *can* do it in a library.
> Thus
> it is important for the core language to have enough flexibility and
> power to accommodate good library designs.
Sure, we agree on that.
> But considering only the core language features would be a serious
> mistake; it would be an unfair disadvantage to a language which has
> preferred library solutions to core language solutions. For example,
> under that criterion, you would say "C99 can handle variable-length
> arrays but C++ can't; C99 can handle complex numbers but C++ can't."
I've done complex numbers in C long before C99. You can do it with a
library in any language, including Pascal. Therefore, it's a fairly
meaningless point of technical language comparison.
> 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.
Certainly, the richness of currently available libraries for a language
affects what one can do with the language today. The ease of building
reusable libraries for a language affects what one can do with it tomorrow.
> Whether a language facilitates good libraries or it
> hinders good development tools, much of the credit/blame is to the language.
I agree, and that's why I prefer to talk about core language features
when comparing languages.
--
I agree with the need for getting rid of undefined behavior as much as
possible, but in a systems oriented language it's hard to see how it can
be gotten rid of completely. For example, casting an int to a pointer
and dereferencing it will give undefined behavior, but that's a
capability that's needed.
Such a design choice means that it combines the worst characteristics of
a core feature (not modifiable/replaceable by the user) with the worst
characteristics of a library feature (poor integration with the language).
> The D language requires compiler support for strings, the C++ language
> allows it. That doesn't mean that there are no strings in C++.
As far as I know, there is no existing C++ compiler that implements
std::string in the compiler. Furthermore, since it is required to be
indistinguishable from a library implementation, it isn't in any useful
sense part of the core language.
C++ does have core strings (char[]) and core arrays (T[]), it's just
that they were abandoned and (unofficially) deprecated rather than fixed.
>> Isn't it a lot more interesting to discuss core language features
>> that make it easier/harder to write certain types of code (and
>> thereby libraries)? Given all the core changes proposed for C++,
>> certainly a lot of people feel the core language support is
>> inadequate.
>
> Some people feel the need for more features. I am not sure that they are all
> widely missed by others. Variadic template arguments are not high on my wish
> list, for example.
Many advanced C++ library developers have demonstrated that one can get
by without variadic templates. But with them, the sizes of some
libraries can drop by 90%.
Template improvements don't float everyone's boat. What is high on your
core language wish list?
>> But what I think is fruitful to discuss or not only pertains to
>> what I decide to post - I don't control these discussions. I'm not
>> a moderator here.
>
> It was I who didn't find it fruitful to compare the languages, when you
> concentrate on a core only comparison. Without the string, vector, and
> complex classes, C++ admittedly is just half a language.
Strings and arrays (and to a lesser extent complex) are such fundamental
types that relegating them to the library means missing out on the
syntactic and semantic niceties one can get by putting them in the core.
After all, would you want 'int' to be library only, and turn your back
on all the goodies a language can offer through direct support of it?
> I respect your opinion, but just don't find it interesting to discuss
> languages from that point of view.
That's your privilege and prerogative.
> It would also be unfair to consider library support as good as core
> language support for (at least) two reasons:
> 1) Syntax.
> 2) Convenience.
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.
> 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.
> 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).
> 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.
> In C++, one must install and add a dependency to boost
> (non-trivial) or pthreads (still non-trivial), or sacrifice
> platform-independence and go Win32.
Pthreads is delivered pre-installed on all of my platformes:-).
But that's not the point. At present, there is no support for
threading in (official) C++. Library or language. That is a
weakness. A weakness currently being addressed by the
committee. The final solution will doubtlessly contain both
library elements and language elements---the library cannot
possibly define what sequence points mean in a multi-threaded
environment, and it would be completely silly to not use
functions and classes to create new threads, mutexes, etc.
(Note that Java uses the synchronized keyword principally
because it doesn't have destructors, and has no other way of
ensuring that a lock is released in case of an exception. One
weakness leads to another.)
> On the other hand, D isn't available by default almost anywhere, whereas
> C++ is, so that's one disadvantage.
A pretty serious one. For me, the absence of a compiler for
Sparc under Solaris means that it's not even worth my time to
find out more.
> However, wasn't this the case with
> C++ vs. C too, at some point?
I'm not sure. The earliest C++ compiler used C as an
intermediate language, so could easily be ported to any machine
on which C ran.
> 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.
> > 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.
--
James Kanze (GABI Software) email:james...@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
> I agree with the need for getting rid of undefined behavior as much as
> possible, but in a systems oriented language it's hard to see how it can
> be gotten rid of completely.
My opinion is the total opposite: Leave behaviour as undefined all over the
place giving plenty of freedom to the implementation.
--
Frederick Gotham
But there is no requirement that parts of the Standard Library MUST be
implemented in compilable C++. An implementation is generally free to do
better than that. The difference is that core features must be supported
directly by every platform (well even here there is room for an
implementation to provide a feature with cumbersome code if nothing else
is possible)
One reason that there are so many constraints on what you are allowed to
do in the std namespace is exactly that implementations are free to
provide standard library features in any way consistent with the
specifications.
One example is valarray where the intent was that implementations for
hardware with array-processors could provide sophisticated and efficient
implementations while less powerful hardware could still provide an
implementation. And, yes, I know that valarray has not lived up to
expectations but I also know that the problem was withdrawal by the
companies producing big number-crunching hardware from language
development (both C and C++) during the later part of the 90s)
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects
[...]
> > But considering only the core language features would be a serious
> > mistake; it would be an unfair disadvantage to a language which has
> > preferred library solutions to core language solutions. For example,
> > under that criterion, you would say "C99 can handle variable-length
> > arrays but C++ can't; C99 can handle complex numbers but C++ can't."
> I've done complex numbers in C long before C99. You can do it with a
> library in any language, including Pascal. Therefore, it's a fairly
> meaningless point of technical language comparison.
You're missing his point. Sure you can do complex numbers in a
library, in pre-C99 C. But the results will not be anywhere
near as convivial as the language support for them in Fortran.
One of the design goals of C++, as I understand it, is precisely
that you should be able to implement a library solution which is
as convivial and as performant as the language support in
Fortran. Rather than add a complex type to the language,
Stroustrup added operator overloading. The result is that
complex can be effectively relegated to the library, at no real
cost. (In theory, anyway. Depending on the compiler, the fact
that function calls etc. are involved may reduce optimization.)
> > 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.
> Certainly, the richness of currently available libraries for a language
> affects what one can do with the language today. The ease of building
> reusable libraries for a language affects what one can do with it tomorrow.
> > Whether a language facilitates good libraries or it
> > hinders good development tools, much of the credit/blame is to the language.
> I agree, and that's why I prefer to talk about core language features
> when comparing languages.
But... From that point of view, the fact that some things can be
effectively relegated to the library, rather than be implemented
in the core langage, would be a symptom of an advantage in the
language. (Supposing, of course, that the functionality in the
two cases was equivalent.)
--
James Kanze (GABI Software) email:james...@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
Frederick Gotham wrote:
> Walter Bright:
>
>> I agree with the need for getting rid of undefined behavior as much as
>> possible, but in a systems oriented language it's hard to see how it can
>> be gotten rid of completely.
>
>
> My opinion is the total opposite: Leave behaviour as undefined all over the
> place giving plenty of freedom to the implementation.
My knowledge of C++ compiler internals is not very extensive. However, I
still find this "wild-west" mentality kind of detrimental for the end-user.
Can someone with a C++ implementation background actually confirm that
the great hassle that is UB significantly benefits the implementation?
That is to say, that the benefit outweighs its cost? I think that a lot
of UB doesn't actually help anyone and is just there out of
carelessness, or laziness. Perhaps just for C compat? If so, this simply
passes the buck to C.
It'd also be interesting to hear from people familiar with the upcoming
C++ standard about whether UB is being mitigated in any way.
Thanks!
-Al.
--
Its somewhat out of context but I want to mention that variadic
template arguments are at the very top of my wishlist! Followed
by a huge gap and then something similar to reflection in some
other languages.
Variadic templates allow proper implementation of many of the
core features in generic code, like tuples or functions with
arbitrary arguments. Given that generic adapters are used in
many places, makes variadic templates (or something which
does something similar to them) crucial. It avoids a lot of typing
and/or some form of preprocessor coping with this repetition.
Good luck, Denise!
If your point is that std::complex is just as good as native complex,
consider the following:
1) Digital Mars C and D implement complex natively, and complex function
return values are in the floating point register pair ST1,ST0. I don't
know of any C++ compiler that does that. It's certainly more efficient.
Native support also means the compiler can easily enregister the complex
numbers within the function.
2) std::complex has no way to produce a complex literal. So, you have to
write:
complex<double>(6,7)
instead of:
6+7i // D programming
3) Error messages involving native types tend to be much more lucid than
error messages on misuse of library code.
4) There is much better potential for core native type exploitation of
mathematical identities and constant folding than there is for library
types where meaning must be deduced.
5) Lack of a separate imaginary type leads to problems such as
identified by Professor W. Kahan: "A streamline goes astray when the
complex functions SQRT and LOG are implemented,
as is necessary in Fortran and in libraries currently distributed with
C/C++ compilers,
in a way that disregards the sign of 0.0 in IEEE 754 arithmetic and
consequently
violates identities like SQRT( CONJ( Z ) ) = CONJ( SQRT( Z ) ) and
LOG( CONJ( Z ) ) = CONJ( LOG( Z ) ) whenever the COMPLEX variable Z
takes negative
real values. Such anomalies are unavoidable if Complex Arithmetic
operates on
pairs (x, y) instead of notional sums x + i*y of real and imaginary
variables.
The language of pairs is incorrect for Complex Arithmetic; it needs the
Imaginary type."
So, why isn't there much of any outcry about these problems with
std::complex? My theory is that few use C++ for serious numerical
computing, derived from the observation that popular and widely used C++
compilers have dropped support for extended doubles (80 bit floating
point) without pushback from the users.
I used to do numerical analysis (calculating stress, inertia, dynamic
response, etc.), and having 80 bits available is a big deal.
> But... From that point of view, the fact that some things can be
> effectively relegated to the library, rather than be implemented
> in the core langage, would be a symptom of an advantage in the
> language. (Supposing, of course, that the functionality in the
> two cases was equivalent.)
The problem is, the functionality is not equivalent. If it was, why are
there proposals to, for example, add new basic types to core C++ to
support UTF strings?
[...]
| 2) std::complex has no way to produce a complex literal.
My understanding is that there is a general solution on the table.
[...]
| So, why isn't there much of any outcry about these problems with
| std::complex? My theory is that few use C++ for serious numerical
| computing, derived from the observation that popular and widely used C++
| compilers have dropped support for extended doubles (80 bit floating
| point) without pushback from the users.
Let me see if I get it right. You have observed (from data you
collected) that widely used C++ compilers have dropped support for
extended doubles (80 bit floating point) without pushback from the
users. Therefore it logically follows that few use C++ for serious
numerical computing.
--
Gabriel Dos Reis
g...@integrable-solutions.net
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.
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.
>> 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.
>> 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.
>> 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.
>> In C++, one must install and add a dependency to boost
>> (non-trivial) or pthreads (still non-trivial), or sacrifice
>> platform-independence and go Win32.
>
> Pthreads is delivered pre-installed on all of my platformes:-).
> But that's not the point. At present, there is no support for
> threading in (official) C++. Library or language. That is a
> weakness. A weakness currently being addressed by the
> committee. The final solution will doubtlessly contain both
> library elements and language elements---the library cannot
> possibly define what sequence points mean in a multi-threaded
> environment, and it would be completely silly to not use
> functions and classes to create new threads, mutexes, etc.
> (Note that Java uses the synchronized keyword principally
> because it doesn't have destructors, and has no other way of
> ensuring that a lock is released in case of an exception. One
> weakness leads to another.)
Right.
>> On the other hand, D isn't available by default almost anywhere, whereas
>> C++ is, so that's one disadvantage.
>
> A pretty serious one. For me, the absence of a compiler for
> Sparc under Solaris means that it's not even worth my time to
> find out more.
Give it some time, I guess :). Although I've always thought Walter
should allow more outside help with D development. Also, I believe there
is a D front-end with a GCC backend. So that's one means of
cross-platform support (not sure if it works on Solaris though).
>> However, wasn't this the case with
>> C++ vs. C too, at some point?
>
> I'm not sure. The earliest C++ compiler used C as an
> intermediate language, so could easily be ported to any machine
> on which C ran.
Good point.
>> 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. Moreover, I wasn't aware that fully-managed
(e.g. no unsafe/PInvoke), CLS-compliant C# contained any UB. Does it? I
also think pure ECMAScript is safe in that regard.
>>> 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? 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).
Cheers,
-Al.
Ouch. Unless this is a joke, I can only be happy that your opinion isn't
shared by many :o). Why would you think undefined (I think you really
meant "unspecified") behavior is a good thing?
Andrei
--
I think it would be goofy to limit comparison to core features.
Otherwise a language with configurable syntax that allows things like
custom statements, user-defined literals etc. will come last as they
have a very small core.
Comparing how a library implementation fares versus a core language
approach towards the same feature is more to the point. But let's not
forget one important detail. The disadvantage of core implementation is
the absolute dictatorship of the entity that defines the language. I
view that as a major drawback. The obvious disadvantages of library-side
implementations (less natural syntax, less opportunities for
optimization etc.) should be considered in balance with the democracy
advantage they enjoy. Therefore, I'm personally way more enthused by
languages that offer their user access to (meta)liguistic tools, rather
than languages that are closely bounded by the view, limits, creativity,
bias, preferences of their creator.
Andrei
> >> I agree with the need for getting rid of undefined behavior as much as
> >> possible, but in a systems oriented language it's hard to see how it can
> >> be gotten rid of completely.
> > My opinion is the total opposite: Leave behaviour as undefined all over the
> > place giving plenty of freedom to the implementation.
> My knowledge of C++ compiler internals is not very extensive. However, I
> still find this "wild-west" mentality kind of detrimental for the end-user.
Very. There are a lot of cases where the undefined behavior
really isn't necessary. Java doesn't allow any freedom
whatsoever with regards to order of initialization, for example,
and yet Java regularly beats C++ in terms of speed when dealing
strictly with basic types.
> Can someone with a C++ implementation background actually confirm that
> the great hassle that is UB significantly benefits the implementation?
Well, if multithreading is taken into account... The current
C++ standard doesn't address the issue, but I would expect that
modifying a variable from two different threads will be
undefined behavior. Giving it a defined meaning would almost
mean putting a lock around each access, which is really not
acceptable, and for the compiler to detect which variables
cannot be accessed from more than one thread at a time is far
beyond any known compiler technology today.
Not the implementation, of course, but as Walter has pointed
out, there are also cases where the purpose of undefined
behavior is to let the implementation define something sensible
for the environment where it runs. You couldn't do memory
mapped IO, for example, without exploiting undefined behavior
that the implementation has "defined".
> That is to say, that the benefit outweighs its cost? I think that a lot
> of UB doesn't actually help anyone and is just there out of
> carelessness, or laziness.
Mainly historical reasons, I think. When C was first being
developped, using Sethi-Ulmann numbers were state of the art
optimizing, and they imply being able to reorder exceptions.
Today, of course, opimization techniques have evolved immensely,
and in practice, I don't think that this freedom really buys the
implementation much.
> Perhaps just for C compat? If so, this simply
> passes the buck to C.
> It'd also be interesting to hear from people familiar with the upcoming
> C++ standard about whether UB is being mitigated in any way.
We're adding to it:-). We can't avoid adding to it, since we
are adding support for threading---and thus, a whole new realm
of possible undefined behaviors.
It would be nice if we did define things like the order of
evaluation, but there doesn't seem to be a consensus to do so.
--
James Kanze (GABI Software) email:james...@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
> If your point is that std::complex is just as good as native complex,
That's not my point, at all. My point is that developing the
language in ways which would allow std::complex to be just as
good as a native type might be more productive than just
implementing it as a native type, and letting it go at that. In
over thirty years of programming, I've never needed a complex
type; I have needed fixed point decimal, IP addresses, and a lot
of other "small" objects. Obviously, adding all of them (and
everything everyone else needs) to the language isn't an option.
So why not move in a way that helps everyone, and not just a
small group?
> consider the following:
> 1) Digital Mars C and D implement complex natively, and complex function
> return values are in the floating point register pair ST1,ST0. I don't
> know of any C++ compiler that does that.
And why not? Wouldn't it be better to develop a compiler which
put any class type consisting of only two doubles in registers,
rather than special case complex? (I know that g++ does put
some simple structures in registers, at least in certain cases.
I don't know if complex falls into those cases, however.)
> It's certainly more efficient.
It's a cheap hack, yes, which allows compiler writers to get
efficiency simply for a benchmark case, while not providing it
in general. Why should complex be more performant than Point2D,
or ColorPixel, or any other small class of that sort? (That's
the Java situation, which is why Java beats C++ when dealing
with double[], but becomes significantly slower as soon as you
change it to Point2D[].)
> Native support also means the compiler can easily enregister the complex
> numbers within the function.
I'm not sure I understand. What do you mean be enregister the
complex numbers within the function.
At any rate, I know that it is easier for a compiler to optimize
a built in type. Which doesn't mean that it can't do as well
with a user defined type, just that it requires a lot more
sophisitication on the part of the compiler. But that's an
argument which affects every type---in my current work, fixed
decimal would be more useful than complex, and in my preceding
job, an IP type. Where do you stop?
> 2) std::complex has no way to produce a complex literal. So, you have to
> write:
> complex<double>(6,7)
> instead of:
> 6+7i // D programming
Syntax is an issue, but isn't the solution developping ways to
provide comfortable syntax for user defined types?
> 3) Error messages involving native types tend to be much more lucid than
> error messages on misuse of library code.
Especially if the type is a template:-).
Again, it's a problem that compiler writers should solve, if
only because library types aren't going to go away. (It is, I
think, a more difficult problem than just getting the two
doubles of a struct into registers.)
> 4) There is much better potential for core native type exploitation of
> mathematical identities and constant folding than there is for library
> types where meaning must be deduced.
I'm not sure about this. The "mathematical identities" of a
constant are based on the identities of the underlying reals,
along with the operations performed on them (definition of
addition, multiplication, etc.). I would expect that the
compiler could find them in both cases.
> 5) Lack of a separate imaginary type [...]
I won't argue about the qualities of a particular
implemenation choice. My knowledge of numeric processing isn't
sufficient to really be able to judge such things. But I don't
see where this is a problem related to the issue of whether the
type is built-in or not: you could easily define an imaginary
type in the library, and you could just as easily define a
built-in complex without imaginary.
> So, why isn't there much of any outcry about these problems with
> std::complex?
Maybe because it's not a real problem. Or maybe just because
not enough people understand the issues. (I seem to recall
reading somewhere that IBM's base 16 floating point cause real
problems as well, but there wasn't much outcry about it,
either.)
> My theory is that few use C++ for serious numerical
> computing, derived from the observation that popular and widely used C++
> compilers have dropped support for extended doubles (80 bit floating
> point) without pushback from the users.
I think it's more than a theory. Numerical computing was, is
and ever shall be done in Fortran. I'd guess that C++ is a
distant number 2 (but well ahead of any of its followers);
people didn't take the effort to develop (and continue
developement on) Blitz++ for nothing.
As for extended doubles, I suspect that the main part of the
reason is a lack of hardware support on the plateforms being
used. I know that Sparc doesn't have it, for example. In fact,
the only machine I know today where it is present is on PC's,
and compilers there DO support it.
> I used to do numerical analysis (calculating stress, inertia, dynamic
> response, etc.), and having 80 bits available is a big deal.
I can also be a trap. I'm sure that numeric analysists know how
to deal with it, but I've seen people caught out more than a few
times by the fact that intermediate calculations are done in
long double, and the exact value of the results depending on
when and where the compiler spilled to memory.
> > But... From that point of view, the fact that some things can be
> > effectively relegated to the library, rather than be implemented
> > in the core langage, would be a symptom of an advantage in the
> > language. (Supposing, of course, that the functionality in the
> > two cases was equivalent.)
> The problem is, the functionality is not equivalent.
Agreed, to a degree. But given the choice, which is to be
preferred: add a new type to the language each time someone
needs it, or extend the language so that equivalent
functionality can be added by a library type. The first is
quick and easy; IMHO the latter, while far more difficult to do
well, is a better long term solution.
> If it was, why are
> there proposals to, for example, add new basic types to core C++ to
> support UTF strings?
I don't know. I've supported UTF-8 strings in my code for
years, without new types:-).
>From what little I understand, the only things the new types
will guarantee is a specific size---char might be 8, 9 or 32
bits, but a char8_t will be exactly 8 bits. And maybe the
character encoding, but I'm not sure. (It would also be nice if
they'd guarantee that character types are unsigned.) All of the
rest would be handled by library functions.
--
James Kanze (GABI Software) email:james...@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
> Such a design choice means that it combines the worst characteristics of
> a core feature (not modifiable/replaceable by the user) with the worst
> characteristics of a library feature (poor integration with the language).
It means that you can get the performance from the library type
without actually doing the work necessary to optimize library
types:-).
> > The D language requires compiler support for strings, the C++ language
> > allows it. That doesn't mean that there are no strings in C++.
> As far as I know, there is no existing C++ compiler that implements
> std::string in the compiler. Furthermore, since it is required to be
> indistinguishable from a library implementation, it isn't in any useful
> sense part of the core language.
> C++ does have core strings (char[]) and core arrays (T[]), it's just
> that they were abandoned and (unofficially) deprecated rather than fixed.
They are a little bit too broken to be easily fixed.
[...]
> Template improvements don't float everyone's boat. What is high on your
> core language wish list?
Thread support, garbage collection and modules. All of which
affect the basic definition of the language, and can't be done
in a library at all. (By thread support, I mean things like
redefining sequence points so they have a meaning in a
multithreaded envirionment, and such. I see no problem with the
interface to the various requests being in the library; in fact,
I rather prefer it that way. But parts of the library will
probably need to collaborate with the compiler---which is
nothing new, either, since that's already the case with such
"library" types as type_info.)
> >> But what I think is fruitful to discuss or not only pertains to
> >> what I decide to post - I don't control these discussions. I'm not
> >> a moderator here.
> > It was I who didn't find it fruitful to compare the languages, when you
> > concentrate on a core only comparison. Without the string, vector, and
> > complex classes, C++ admittedly is just half a language.
> Strings and arrays (and to a lesser extent complex) are such fundamental
> types that relegating them to the library means missing out on the
> syntactic and semantic niceties one can get by putting them in the core.
> After all, would you want 'int' to be library only, and turn your back
> on all the goodies a language can offer through direct support of it?
I think you can find arguments for types like string and arrays.
But that's not the point. If you argue that string's in D are
supperior to string's in C++, that's one thing. And it may even
be that the reason is that string's in C++ aren't a native type.
But the argument that C++ doesn't have a string type is false.
It does. (It actually has two, which is probably a bigger
problem than any problem due to the fact that std::string is
part of the library, and not part of the core language.)
And if the language offered ways to define int as an efficient
library type, I'd be all for it. It doesn't. In the case of
int, I don't think it can---int generally corresponds to a basic
type in hardware. Strings and arrays are a bit less clear. And
about the only real argument I can think of for making complex a
basic type is performance (or the absense of any good
abstraction mechanisms---in Fortran IV, there really wasn't an
alternative).
--
James Kanze (GABI Software) email:james...@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
I think it would come first, as it has core features far more advanced.
> Comparing how a library implementation fares versus a core language
> approach towards the same feature is more to the point. But let's not
> forget one important detail. The disadvantage of core implementation is
> the absolute dictatorship of the entity that defines the language. I
> view that as a major drawback.
Since the C++ Standard allows the Standard Library to be hardwired in to
the compiler, hasn't that happened anyway (even if no actual C++
compiler has done so)?
> The obvious disadvantages of library-side
> implementations (less natural syntax, less opportunities for
> optimization etc.) should be considered in balance with the democracy
> advantage they enjoy. Therefore, I'm personally way more enthused by
> languages that offer their user access to (meta)liguistic tools, rather
> than languages that are closely bounded by the view, limits, creativity,
> bias, preferences of their creator.
You seem to be arguing you're enthused by core features that enable
better libraries to be written, rather than the library itself. I would
agree with that.
I don't think anyone here is advocating a core language that somehow
prevents powerful libraries from being written. D's core support for
arrays doesn't in the slightest prevent someone from writing a vector
class any more than C++'s core arrays prevent it. There just isn't much
point to writing a vector class in D, since the core arrays are good enough.
It's like why isn't there a C++ std::int library type? Because the core
int is good enough, not because you cannot write a library integer.
It can be magic, in that the library writer can make a deal with the
compiler writer, to have some formally undefined heaviour actually being
defined for a specific use. Some offsetof macros use that trick.
>
> 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.
The C++ language is what is included in the standard, all chapters.
>>
snip
>> 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?
> 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).
Requiring compiler support doesn't make a feature clean, it makes it dirty.
I believe that's where James and I disagree with Walter.
If you have a core language support that allows std::string to be
efficiently implemented as a library, that means that other similar classes
can be efficiently implemented as well. By someone other than the compiler
writer.
The fact that it can be done as a library only, with no specific magic,
actually shows that the language is stronger, not weaker.
The fact that Walter designs and implements his own language, puts him in a
different position than most of us. Perhaps that influences his point of
view? Or maybe his views is the reason for doing it?
I am very happy when I can implement, or extend, some feature without
specific compiler support.
Bo Persson
It seems I've entered a period of posting "sorry, the above is not
meaningful to me" to clc++m.
Anyway, the above isn't meaningful to me.
Let complex(x,y) = x+i*y.
Is the professor's point then that
sqrt( conj( complex(-9, +0) ) ) === sqrt( complex(-9, -0) )
"should" ideally evaluate to
complex(+0, -3)
instead of complex(+0, +3)?
But even if so, how does an Imaginary type help with that, when x+i*y
can always be represented as Complex(x,y) and vice versa?
Furthermore, what is the relevance to library versus built-in?
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
I know people who do numerical analysis who do not understand the
problems with creeping roundoff error. I wouldn't call them serious,
because they don't recognize when their answers are way off. They refuse
to believe that a .0000001% error can rise up to utterly swamp their
results.
On the other hand, I used to do numerical analysis work (using FORTRAN).
If I got the wrong answer, it would put lives at risk (I worked on
flight critical airplane control systems) or at the very least cost an
awful lot of money. This analysis included things like numerical
integration, finite element, and matrix inversion, which are all very,
very sensitive to creeping roundoff errors.
The easiest way to deal with roundoff errors is to increase the
precision. Any compiler that doesn't at least provide the full precision
of the underlying hardware cannot be taken seriously as a tool for doing
serious numerical analysis. It tells me the compiler vendor has some
agenda other than paying attention to the numerics crowd, and I wouldn't
use such a tool for serious numerical work.
The fact that those compiler shortcomings are rarely mentioned, and are
not fixed, tells me that whoever is using them is not serious about
numerical work. Wizzy template metaprogramming libraries don't mean jack
if your Mars probe fires its retro rockets 10 feet below the surface.
Most of what I see about floating point work these days with C++ seems
to be about game programming. The focus with that kind of work is speed,
speed, speed, not accuracy. Nothing falls out of the sky if your line is
a few pixels off.
Unlike C++, a conforming D compiler is *required* to provide a type
representing the max precision the underlying hardware is capable of.
And btw, g++ does offer 80 bit long doubles on the x86. Kudos to the gcc
implementors.
--
> Can someone with a C++ implementation background actually confirm that
> the great hassle that is UB significantly benefits the implementation?
What great hassle is there with UB? Either you can do something in Standard
C++, or you can't. Simple as.
If one writes portable code whose behaviour is not defined by the C++
Standard, then that's _their_ problem.
--
Frederick Gotham
> Ouch. Unless this is a joke, I can only be happy that your opinion isn't
> shared by many :o). Why would you think undefined (I think you really
> meant "unspecified") behavior is a good thing?
Well, if we make it undefined behaviour to cast a random integer value to a
"pointer to a double", to store the max value in it, and to increment it,
then the implementation doesn't have to worry about what to do in case of:
++( *(double*)RandomInt() = numeric_limits<double>::max() );
--
Frederick Gotham
I am struggling to see how things like malloc can be implemented without
'magic'. It is a fundamental principle of the C library, and hence the
C++ one that Standard Library elements can be implemented any way the
implementor chooses and that includes compiler 'magic.'
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[...]
> I don't think anyone here is advocating a core language that somehow
> prevents powerful libraries from being written. D's core support for
> arrays doesn't in the slightest prevent someone from writing a vector
> class any more than C++'s core arrays prevent it. There just isn't much
> point to writing a vector class in D, since the core arrays are good enough.
And there isn't any point to adding a new array type to the C++
core language, because std::vector is good enough. Which may
or may not be true, depending on what you are doing, but the
point is: in C++, you do have std::vector. It's legitimate to
compare it to the core arrays in D, if they serve the same
purpose (and even without knowing D, I'd wager that the
declaration syntax for multi-dimension arrays is better), but
that comparison should be based on actual features (like the
declaration syntax), and not whether the support itself is in
the core language or in the library.
--
James Kanze (GABI Software) email:james...@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
>> 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. Moreover, I wasn't aware that fully-managed
> (e.g. no unsafe/PInvoke), CLS-compliant C# contained any UB. Does it? I
> also think pure ECMAScript is safe in that regard.
If the language is absolutely free of any UB then you basically cannot
implement its own library in it - with I/O being the crucial part.
Of course, it is possible to define a language without UB and give it a
library that is "reach enough", but such languages are not what we would
call "system-programming languages" (try to find one).
And there is nothing like "reach enough library" anyway.
If the language is supposed to be used in things like implementation of
whole operating systems, then some "reasonable" dose of UB is in order.
Of course, it's good if it's as controlled and confined as possible, but
you cannot eliminate it entirely - that's where "reasonable" comes in.
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
> 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...@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
> > Ouch. Unless this is a joke, I can only be happy that your opinion isn't
> > shared by many :o). Why would you think undefined (I think you really
> > meant "unspecified") behavior is a good thing?
>
> Well, if we make it undefined behaviour to cast a random integer value to a
> "pointer to a double", to store the max value in it, and to increment it,
> then the implementation doesn't have to worry about what to do in case of:
> ++( *(double*)RandomInt() = numeric_limits<double>::max() );
I think that there are two types of undefined behavior. I have
no problem with the undefined behavior that results from a
reinterpret_cast, and it is necessary in order to support things
like memory mapped I/O. On the other hand, I find it most
disconcerting that an expression like *p = (*q) ++ is undefined
behavior if p and q happen to point to the same object. And
while strictly speaking not undefined behavior, it find it most
unacceptable that something like "f( std::auto_ptr( new X ),
std::auto_ptr( new Y ) )" is not exception safe.
These sort of things trap up beginners. And non-beginners as
well. Most of us have enough other problems to keep us busy
without having to constantly worry about such nagging
inconsistencies.
--
James Kanze (GABI Software) email:james...@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
--
It's also the most naive:-). If you're loosing one bit
precision per iteration, and you're iterating a couple of
million times, you're going to have to increase the precision a
lot.
And please take this in the somewhat humorous veine it is meant.
Increasing precision is a solution sometimes, and I'm pretty
sure that you do understand the problems, and know enough to
verify that it is the correct solution in your case. But just
as obviously, it's not a silver bullet, and it won't really help
the naive user.
> Any compiler that doesn't at least provide the full precision
> of the underlying hardware cannot be taken seriously as a tool for doing
> serious numerical analysis. It tells me the compiler vendor has some
> agenda other than paying attention to the numerics crowd, and I wouldn't
> use such a tool for serious numerical work.
I think the problem is somewhat more complex. If you use long
double on an Intel, you do not have the guard bits and other
stuff that helps ensure correct rounding. As I understand it,
the idea behind extended precision was that it should be used
for intermediate results, and not for storing data---the idea is
that an expression like a*b/c will always give the "correct"
results if the correct results fit in a double.
Of course, this leads to confusion as well, since we don't
always know when the compiler will spill to memory, and when it
will keep the value in a register (with extended precision).
[...]
> Unlike C++, a conforming D compiler is *required* to provide a type
> representing the max precision the underlying hardware is capable of.
For what definition of "the underlying hardware is capable of"?
With proper software support, the underlying hardware is capable
of just about any precision I care to ask of it. Obviously,
this isn't what you mean, but while I think what you mean may be
obvious on most general purpose machines, I'm not sure that it
is precise enough for a standard.
The C++ standard, of course, follows the lead of C, and allows
the compiler to use extended precision in intermediate results,
without requiring it. The results can be surprising, to put it
mildly.
> And btw, g++ does offer 80 bit long doubles on the x86. Kudos
> to the gcc implementors.
I'm willing to bet that even VC++ uses extended precision on an
x86, even if it won't allow you to declare a variable of that
type. Not doing so slows down the math processor considerably.
--
James Kanze (GABI Software) email:james...@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
> any library can be implemented in any language.
To buy into that idea, you have to believe that the expressiveness of
a library's API and its performance characteristics are not part of
the library design itself.
You can write Blitz++ in FORTRAN? I don't think so. If you do that,
it ceases to be Blitz++, and becomes something else.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
Mirek
--
> It would also be unfair to consider library support as good as core
> language support for (at least) two reasons:
>
> 1) Syntax.
> 2) Convenience.
Not necessarily. My ideal language would allow me to create library
support whose syntax and convenience are, in most cases, just as good
as that of the best possible core-language design.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
This explains it better than I can:
http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf
> Furthermore, what is the relevance to library versus built-in?
None. The relevance is to the lack of an imaginary type for C++ (library
or built-in) and what such lack says about serious numerical analysis use.
Note that C99 does address this and includes an imaginary type. So does D.
--
I didn't argue C++ didn't have a string type. I argued that:
1) library features are not part of the core language.
2) C++ (and D) do not have good enough core features to be able to
create a library string (and vector, complex and associative arrays)
that are good enough to compete with core support for such.
3) String, complex, vector and associative arrays are ubiquitous enough
that the extra goodies one can get with a core feature make them
worthwhile to put in the core language.
I tend to feel that what makes a language dirty is when it's loaded with
special cases and arcane rules. A clean language is not necessarily one
with a small number of features, it is one with features that are
orthogonal yet fit together in a predictable and sensible manner.
> I believe that's where James and I disagree with Walter.
> If you have a core language support that allows std::string to be
> efficiently implemented as a library, that means that other similar classes
> can be efficiently implemented as well. By someone other than the compiler
> writer.
>
> The fact that it can be done as a library only, with no specific magic,
> actually shows that the language is stronger, not weaker.
D can, as well as C++ can, create library defined strings, vectors, etc.
I get the impression you feel that D somehow sacrificed the ability to
create user defined types by adding core support for arrays and strings.
> The fact that Walter designs and implements his own language,
> puts him in a
> different position than most of us. Perhaps that influences his point of
> view? Or maybe his views is the reason for doing it?
Actually, it was using languages that did support strings and arrays
much better than C++ that led me to want much better than what could be
done with a library. Maybe it's a coincidence that such languages are
almost always considered to be easier to learn, use and more productive
to program in than C++. Strings and arrays are ubiquitously used, so
even small improvements in their usability can pay big dividends in the
long run.
> I am very happy when I can implement, or extend, some feature without
> specific compiler support.
There's no way you're going to get std::string, std::vector or
std::complex to work as well as core support for such with existing C++
core features.
But I do have a couple challenges for you <g>.
1) Extend std::string to support UTF-8.
2) Extend std::string to support strings with embedded 0's.
But dlsym() which is a POSIX function returns a void * which often
needs to be cast back to a pointer to a function.
It is useful to know therefore that a compiler on a POSIX system can be
written to allow the cast to succeed to not break all the current
existing code that does this cast, whilst at the same time not
enforcing it onto all systems in general where void* might not be big
enough to hold a function pointer.
(Yes, you can code around that by exporting an instance of a variable
rather than a function, assuming your library is written in C++ and not
C. Do not forget though that C++ allows linkage with C libraries too).
[...]
| > I am very happy when I can implement, or extend, some feature without
| > specific compiler support.
|
| There's no way you're going to get std::string, std::vector or
| std::complex to work as well as core support for such with existing C++
| core features.
So, the question is: Can there be better library implementations, or
can the core language be extended to allow better library
implementation? (e.g. allow for literal of user-defined types),
or do you think that there are *intrinsinc* reasons why they must be
core languages? If yes, could you elaborate on those logical,
intrinsinc, reasons?
--
Gabriel Dos Reis
g...@integrable-solutions.net
Forgive me if I failed to find the quote you intended in that long document.
The closest I found was an assertion:
"... anomalies are unavoidable if Complex Arithmetic operates on pairs
(x, y) instead of notional sums x + ?·y of real and imaginary
variables."
To my mind that explains nothing, just reasserting the earlier assertion.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
Earlier versions of VC++ did save all 80 bits if you used long double
variables. Newer versions do not, claiming consistency over all Windows
versions (on different hardware).
Walter will also have some problems implementing D on 64-bit Windows, where
the OS doesn't save the x87 registers on a task switch. Someone decided that
it was enough to save the *other* set of floating point registers.
Bo Persson
Microsoft fixed that shortcoming.
See page 15.
--
I don't see why there needs to be undefined behavior in this instance,
or even the more general case.
Foo foo; // Well-Defined.
Foo* foo = new Foo; // Well-Defined.
Foo* foo = dlsym<Foo>(); // "Would be" Well-Defined, if it existed.
If the cast/process fails, you could do one of two things:
a) Throw (as does dynamic_cast by reference).
b) Return NULL (as does dynamic_cast by pointer).
See? No need for UB.
C is an arcane, unsafe, weakly-typed, very user-unfriendly language. C++
is not C :P.
Cheers,
-Al.
He already has. (Dynamic) Strings and (Dynamic) Arrays are just as
common and important in the vast majority of programs as Integers.
Integers are an intrinsic part of the language, yet they don't need to.
I see no indication that a language couldn't get away with a single type
-- bit -- and everything else left to the library. Thus, the same
argument applies to strings and arrays.
To be fair, std::string and std::vector are fairly impressive bits of
work, considering how they are constrained. But their deficiencies show
up everywhere.
Can you imagine having to do:
#include <integer>
// Binary for 32, because remember, you don't have int literals.
typedef std::integer<0, 0, 1, 0, 0, 0, 0, 0> int32;
void displayAnswer(const int32& answer) {
cout << "The answer to the life is: " << answer << endl;
}
const int32 main() {
try {
cout << "2 + 2 = " << int32(1, 0) + int32(1, 0);
cout << endl;
displayAnswer(int32(1, 0, 1, 0, 1, 0));
} catch (...) {
return int32(1);
}
return int32(0);
}
For even trivial programs? It'd get real messy in a hurry. Similar
hassle is incurred currently because of the lack of native dynamic
arrays and strings. I think better support for these is very important.
Here's one radical suggestion for the next C++ standard:
string literals could be of type std::string (instead of const char*).
string literals prefixed with L could be of type std::wstring (vs. const
wchar_t*).
array literals could be of type std::vector (instead of T*).
These are already part of the language, so why not rely on them?
Just food for thought.
Cheers,
-Al.
--
A compiler will always be more powerful than what's possible with the
library, for the intrinsic reason that one can code the compiler to do
whatever one wants to. With a library, you're stuck with what the
compiler chooses to make available. I think that's pretty obvious, since
there are no examples of languages where libraries are as powerful as
the compiler. If it was possible, out of the thousands of languages
invented, certainly one of them would have done so?
To improve upon the current abilities to create user defined types, one can:
1) allow user defined literals
2) allow user defined syntax
3) allow user defined semantics
Currently, C++ (and D) only allow (3), and only to a limited extent.
You've alluded to a C++ proposal for (1), I haven't seen it so have no
useful comment about it. I know that D, at least, will not have user
defined tokens, for the reason that such would blow the legs off of
third party tools that process source without needing to be full blown
compilers.
I don't think (2) can ever happen with C++, for the reason that it's
very hard to see how user defined syntax could ever be retrofitted in to
a language that is already the hardest language in existence to parse
(by a wide margin).
--
No, the very fact that it is even possible to write a non-portable
program is a problem that could only exist because the C++ "Standard"
is incomplete. In other words, what the Standard euphemistically calls
"undefined behavior" is nothing more than those areas of the C++
language that have yet to be filled in. And if those areas were ever to
be filled in, then concerns about "portable code" would all evaporate -
because every C++ program would be portable.
After all, there is more than a slight absurdity in the very term
"undefined behavior". Hasn't anyone ever wondered how exactly the C++
Standard is able to find so much undefined behavior in the execution of
the most deterministic finite state automaton ever invented - the
modern computer?
And to make matters worse, the C++ Standards Committee does not appear
to have made any significant effort at eliminating even a few of the
more preposterous cases of undefined behavior in the current C++
Standard (can't a modern computer even shift bits in a predictable
way?). Even more troubling than the inaction on this front, is that few
- if any - of those involved in C++0X process seem to appreciate the
seriousness of the problem. More than any other single factor, it is
the undefined behavior in C++ that is most likely to end C++ long
career as a major programming language and could do so in very short
amount of time.
It is important to understand that undefined behavior in C++ is not a
threat because it makes C++ programmers yearn to program in other
languages (though who knows? it may), nor does it make C++ less
efficient than other languages (actually it usually has the opposite
effect). Rather, the threat posed by undefined behavior is purely one
of economics. A computer language with completely defined behavior
(such as Java) translates into cheaper programmers (because they are
less skilled) translates into the same or fewer programming defects
(because programming mistakes are harder to make and more easily
detected in time) and even translates into a shorter development cycle
(because undefined behavior may mask bugs that take longer to find then
a program whose behavior is known to be completely defined). Cheaper,
better, faster - those are the threats to C++'s continued relevance.
Those of us who are C++ programmers may be tempted - as a response - to
deride the programming skills of, say, a Java or C# programmer, or to
criticize those languages for any number of shortcomings when compared
to C++ - and although we may well be justified in our opinions - our
being right will not be enough to save the C++ language from market
forces. Because I believe that it is those who pay to have software
written, not those who are paid to write software - who will decide the
fate of programming languages in this day and age. And if I am correct
(and I'm as big a fan of C++ as anyone), then - unless something more
is done - C++'s days as a major programming language are numbered.
Greg
--
Well, what you snipped from my response was from page 15.
Could you be a /little bit/ more specific, please, Walter?
E.g., a quote would be nice, if it isn't too much text (or graphics).
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[...]
| Hasn't anyone ever wondered how exactly the C++
| Standard is able to find so much undefined behavior in the execution of
| the most deterministic finite state automaton ever invented - the
| modern computer?
(1) they are not deterministic.
(2) "undefined behaviour" has a very specific meaning technical in the C++
definition text. Look for it in the first clause.
--
Gabriel Dos Reis
g...@integrable-solutions.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
| Gabriel Dos Reis wrote:
| > Walter Bright <wal...@digitalmars-nospamm.com> writes:
| >
| > [...]
| >
| > | > I am very happy when I can implement, or extend, some feature without
| > | > specific compiler support.
| > |
| > | There's no way you're going to get std::string, std::vector or
| > | std::complex to work as well as core support for such with existing C++
| > | core features.
| >
| > So, the question is: Can there be better library implementations, or
| > can the core language be extended to allow better library
| > implementation? (e.g. allow for literal of user-defined types),
| > or do you think that there are *intrinsinc* reasons why they must be
| > core languages? If yes, could you elaborate on those logical,
| > intrinsinc, reasons?
| >
|
| He already has.
Sorry, I was looking for logical, intrinsic, reasons. If he had, I've
missed it. Upon reading you reply, I searched again; I'm afraid I
must have missed it again.
| (Dynamic) Strings and (Dynamic) Arrays are just as
| common and important in the vast majority of programs as Integers.
Dynamic strings and dynamic arrays are important; I'm not sure they are
just as important as integers. But considering, for the sake of the
argument, that they are equality important, it does not necessarily
follow that they must be intrinsic in the language, if the language
provides general effective abstraction tools to define strings and
arrays in library efficiently.
| Integers are an intrinsic part of the language, yet they don't need to.
|
| I see no indication that a language couldn't get away with a single type
| -- bit -- and everything else left to the library. Thus, the same
| argument applies to strings and arrays.
I'm sure you can exhibit a logical, intrinsic, reason without
resorting to proof by analogy -- which is considered by many as fraud.
| To be fair, std::string and std::vector are fairly impressive bits of
| work, considering how they are constrained. But their deficiencies show
| up everywhere.
Are their deficiencies intrinsically linguistic that cannot be
repaired, or are they library design artefacts?
| Can you imagine having to do:
|
| #include <integer>
|
| // Binary for 32, because remember, you don't have int literals.
| typedef std::integer<0, 0, 1, 0, 0, 0, 0, 0> int32;
I don't know what you mean by that.
I tried it on my compiler, it choked with:
al.C:1:19: error: integer: No such file or directory
al.C:4: error: expected initializer before '<' token
al.C:6: error: expected ',' or '...' before '&' token
al.C:6: error: ISO C++ forbids declaration of 'int32' with no type
al.C: In function 'void displayAnswer(int)':
al.C:7: error: 'cout' was not declared in this scope
al.C:7: error: 'answer' was not declared in this scope
al.C:7: error: 'endl' was not declared in this scope
al.C: At global scope:
al.C:10: error: 'int32' does not name a type
| void displayAnswer(const int32& answer) {
| cout << "The answer to the life is: " << answer << endl;
| }
|
| const int32 main() {
| try {
| cout << "2 + 2 = " << int32(1, 0) + int32(1, 0);
| cout << endl;
| displayAnswer(int32(1, 0, 1, 0, 1, 0));
|
| } catch (...) {
| return int32(1);
| }
|
| return int32(0);
| }
Again, please explain the logical idea you wanted to express.
--
Gabriel Dos Reis
g...@integrable-solutions.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
| Gabriel Dos Reis wrote:
| > So, the question is: Can there be better library implementations, or
| > can the core language be extended to allow better library
| > implementation? (e.g. allow for literal of user-defined types),
| > or do you think that there are *intrinsinc* reasons why they must be
| > core languages? If yes, could you elaborate on those logical,
| > intrinsinc, reasons?
|
| A compiler will always be more powerful than what's possible with the
| library, for the intrinsic reason that one can code the compiler to do
| whatever one wants to. With a library, you're stuck with what the
| compiler chooses to make available.
But even for a core language feature, one is also stuck with what the
compiler writer has chosen to optimize for, i.e. make available.
In 2006, not every C++ compiler supports all core C++98 or C++03
functionalities.
Users of popular C++ compilers are stuck with what compilers have
decided to make available as language features.
For a library solution, I've seen compiler steadily improving support
for library functionalities -- think of GCC and its support for C
library functions. I'm afraid your speculation is countered by actual
data.
| I think that's pretty obvious, since
no, it is not.
| there are no examples of languages where libraries are as powerful as
| the compiler.
I see libraries as being more powerful than compilers in the sense
that libraries allow for development, refinement, of several solutions
to the a given problem, with at least the same efficiency as compiler,
in a extremely shorter time than compilers. I have been using several
implementations of complex classes way long before my favorite compilers
decided to have an intrinsic type for complex numbers.
Similarly for vectors.
| If it was possible, out of the thousands of languages
| invented, certainly one of them would have done so?
Some have done quite a remarkable job at it; you just need to admit
it. That is a separate problem.
| To improve upon the current abilities to create user defined types, one can:
|
| 1) allow user defined literals
| 2) allow user defined syntax
| 3) allow user defined semantics
|
| Currently, C++ (and D) only allow (3), and only to a limited extent.
|
| You've alluded to a C++ proposal for (1), I haven't seen it so have no
| useful comment about it.
It has been kept not a secret for a while now.
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2116.pdf
| I know that D, at least, will not have user
| defined tokens, for the reason that such would blow the legs off of
| third party tools that process source without needing to be full blown
| compilers.
That is more a problem with D's design philosophy than an intrinsically
linguistic issue.
| I don't think (2) can ever happen with C++, for the reason that it's
| very hard to see how user defined syntax could ever be retrofitted in to
| a language that is already the hardest language in existence to parse
| (by a wide margin).
I don't think your categorization of (2) is adequate. C++ has been
offering (3) for more than 2 decades now. There are several ways of
doing (2) without necessarily having user defined tokens. One of them
is to allow users to attach their meaning to tokens.
--
Gabriel Dos Reis
g...@integrable-solutions.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> > But dlsym() which is a POSIX function returns a void * which often
> > needs to be cast back to a pointer to a function.
> I don't see why there needs to be undefined behavior in this instance,
> or even the more general case.
> Foo foo; // Well-Defined.
> Foo* foo = new Foo; // Well-Defined.
> Foo* foo = dlsym<Foo>(); // "Would be" Well-Defined, if it existed.
If it existed. dlsym is `extern "C"': there is no C++ binding
for Posix.
> If the cast/process fails, you could do one of two things:
> a) Throw (as does dynamic_cast by reference).
> b) Return NULL (as does dynamic_cast by pointer).
> See? No need for UB.
> C is an arcane, unsafe, weakly-typed, very user-unfriendly language. C++
> is not C :P.
But dlsym is C. And dlsym returns a void*, which (typically)
points to a function. You can avoid the undefined behavior
entirely by declaring a pointer to function in the .so, using
dlsym to get the address of the pointer to function, and then
calling with two levels of indirection. Which doesn't help
lisibility. Or you can count on the fact that Posix defines
things that C++ and C leave undefined, and write something like:
int (*pf)() ;
reinterpret_cast< void*& >( pf ) = dlsym( ... ) ;
This is undefined behavior according to the C++ standard; you
cannot access a variable other than as its defined type (or as
an array of char or unsigned char). Posix, however, requires
that all pointers have the same size and representation, and so
indirectly, defines this behavior.
--
James Kanze (GABI Software) email:james...@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
| Alf P. Steinbach wrote:
| > * Walter Bright:
| >> Alf P. Steinbach wrote:
| >>> But even if so, how does an Imaginary type help with that, when x+i*y
| >>> can always be represented as Complex(x,y) and vice versa?
| >>
| >> This explains it better than I can:
| >> http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf
| >
| > Forgive me if I failed to find the quote you intended in that long
| > document.
|
| See page 15.
I'm sure you can give us an explanation in simple terms for those of
us who are struggling in removing anti-Sun rants, just to get to the
technical arguments.
--
Gabriel Dos Reis
g...@integrable-solutions.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> A compiler will always be more powerful than what's possible with the
> library, for the intrinsic reason that one can code the compiler to do
> whatever one wants to. With a library, you're stuck with what the
> compiler chooses to make available. I think that's pretty obvious, since
> there are no examples of languages where libraries are as powerful as
> the compiler. If it was possible, out of the thousands of languages
> invented, certainly one of them would have done so?
I'm not certain what you're trying to say. In many functional
languages, the distinction between what is compiled and what is
part of the core language is very vague; in Lisp, the language
existed as a library only before there was a compiler. The
distinction is clearer in C++, although there are vague points,
like std::type_info.
I think it's true that in most procedural languages today, there
is no way of defining totally new syntax without modifying the
compiler, but this is a constraint of the particular languages,
and not something fundamental. The macro pre-processor for
Intels ASM 86, for example, allowed defining new syntax; a
function was called by matching a pattern, and the function
definition defined that pattern. It can be done. It has been
done. (But of course, at present, C++ doesn't do it.)
> To improve upon the current abilities to create user defined types, one can:
> 1) allow user defined literals
> 2) allow user defined syntax
> 3) allow user defined semantics
> Currently, C++ (and D) only allow (3), and only to a limited extent.
I believe that there is a proposal before the committee to
support 1---the question was discussed, at any rate.
> You've alluded to a C++ proposal for (1), I haven't seen it so have no
> useful comment about it. I know that D, at least, will not have user
> defined tokens, for the reason that such would blow the legs off of
> third party tools that process source without needing to be full blown
> compilers.
For every advantage, there are drawbacks. Since C++ has the
preprocessor it has, the legs (and even a bit higher) are
already blown off of third party tools that process source code,
so the added cost would be less.
If you point is just that language design (and library design)
is a very difficult balancing act, I've no problem agreeing. If
you're claiming that the standard string type in D is superior
to that in C++, I can only say that I wouldn't be surprised
(even without knowing the standard string type in D), but that
surprisingly, std::string actually works a lot better in
practice than one would think it should in theory.
> I don't think (2) can ever happen with C++, for the reason that it's
> very hard to see how user defined syntax could ever be retrofitted in to
> a language that is already the hardest language in existence to parse
> (by a wide margin).
(2) already exists in C++:
#define IF if (
#define THEN ) {
#define ELSE } else {
#define ENDIF }
// ...
Which is, of course, one of the reasons why C++ is the hardest
language in existence to parse.
--
James Kanze (GABI Software) email:james...@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
It would only be portable to those systems where the stricter specification
could be implemented.
As a developer you can also avoid som UB by restricting your intended target
to a subset of the existing machines. Frederick's problem here can be
avoided by specifying a minimum of 17 bits for type int.
I started my career programming 8-bit Z80 machines, and now have a dual-core
Athlon 64. I don't really care if my programs port easily between these two
machines. They aren't used for the same things anyway.
>
> After all, there is more than a slight absurdity in the very term
> "undefined behavior". Hasn't anyone ever wondered how exactly the
> C++ Standard is able to find so much undefined behavior in the
> execution of the most deterministic finite state automaton ever
> invented - the modern computer?
Computers are different. By not specifying each low level detail, C++ can be
*efficiently* implemented on more types of computers.
>
> And to make matters worse, the C++ Standards Committee does not
> appear to have made any significant effort at eliminating even a
> few of the more preposterous cases of undefined behavior in the
> current C++ Standard (can't a modern computer even shift bits in a
> predictable way?).
No, they cannot. Specifically, different members of the Intel x86 series
shift by a different amount, when the shift count is larger than the
register width. Even though they use the same binary instruction.
So the C++ standard says that the result is undefined. How do we fix that?
> It is important to understand that undefined behavior in C++ is not
> a threat because it makes C++ programmers yearn to program in other
> languages (though who knows? it may), nor does it make C++ less
> efficient than other languages (actually it usually has the opposite
> effect). Rather, the threat posed by undefined behavior is purely
> one of economics. A computer language with completely defined
> behavior (such as Java) translates into cheaper programmers
> (because they are less skilled) translates into the same or fewer
> programming defects (because programming mistakes are harder to
> make and more easily detected in time) and even translates into a
> shorter development cycle (because undefined behavior may mask bugs
> that take longer to find then a program whose behavior is known to
> be completely defined). Cheaper, better, faster - those are the
> threats to C++'s continued relevance.
On the mainframe I program for, IBM had to add special Java processors to
make it run fast enough, because the behaviour of their other hardware
didn't exactly fit the Java spec. Talk about EXPENSIVE!
Bo Persson
> But I do have a couple challenges for you <g>.
> 2) Extend std::string to support strings with embedded 0's.
Doesn't std::string support exactly that by default?
regards
--
jb
(reply address in rot13, unscramble first)
And what you seem to miss is that C++ is a general purpose programming
language designed to be useful on many platforms. There are two major
areas of undefined behaviour:
1) Places where requiring diagnosis is very expensive (or in some cases,
equivalent to solving the halting problem). This is particularly true of
problems arising from separate compilation. Some possible breaches of
the ODR are very subtle (though any well taught programmer will avoid
them)
2) Places where portability is essentially impossible because of
different hardware having different requirements.
It is interesting to note that even languages like Java that target a
single platform (the JVM) exhibit undefined behaviour. At least C++ has
the honesty to identify the problem areas.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects
> | I don't think (2) can ever happen with C++, for the reason that it's
> | very hard to see how user defined syntax could ever be retrofitted in to
> | a language that is already the hardest language in existence to parse
> | (by a wide margin).
>
> I don't think your categorization of (2) is adequate. C++ has been
> offering (3) for more than 2 decades now. There are several ways of
> doing (2) without necessarily having user defined tokens. One of them
> is to allow users to attach their meaning to tokens.
One interesting approach for (2) is the Scala (http://scala.epfl.ch) one.
It would be interesting to see how well it could be imported in C++. They
don't really have user specified syntax, but the langage syntax is flexible
enough to be able to define repeat and until so that
repeat {
some code here
} until (cond);
does the same as
do {
some code here
} while (!cond);
in C++. And at first look it seems to be that an efficient implementation
is possible. A possible problem is the understandability of error
messages.
Yours,
--
Jean-Marc
[snip]
>
> It is important to understand that undefined behavior in C++ is not a
> threat because it makes C++ programmers yearn to program in other
> languages (though who knows? it may), nor does it make C++ less
> efficient than other languages (actually it usually has the opposite
> effect). Rather, the threat posed by undefined behavior is purely one
> of economics. A computer language with completely defined behavior
> (such as Java) translates into cheaper programmers (because they are
> less skilled) translates into the same or fewer programming defects
> (because programming mistakes are harder to make and more easily
> detected in time) and even translates into a shorter development cycle
> (because undefined behavior may mask bugs that take longer to find then
> a program whose behavior is known to be completely defined). Cheaper,
> better, faster - those are the threats to C++'s continued relevance.
>
Yes, I see your points, but
1. It is not that useful to compare Java with C++ here. The two
languages evolve in quite different ways. There is no one single
company/vendor can dominate the behaviors of C++.
2. Fact 1: even we had a standard (yes, lots of UB) almost 10 years
ago, we do not have a 100% standard compliant compiler.
3. Fact 2: We do not have an standard ABI, which makes it almost
impossible to remove all the UBs in the C++ standard. These
issues are out of the control of C++ committee in my mind.
4. I am just worrying about that even we have a completely defined
standard, it will become a second class standard. Just think
about export keyword, instead of trying to add it, one major
compiler vendor was trying to remove it. Another vendor disabled
it before shipping it.
To repeat myself, I see your points, but I do not think this is
possible in recent future.
> Hasn't anyone ever wondered how exactly the C++
> Standard is able to find so much undefined behavior in the execution of
> the most deterministic finite state automaton ever invented - the
> modern computer?
What do you mean by "the" modern computer ?
--
pa at panix dot com
On Nov 22, 11:10 am, "Greg Herlihy" <gre...@pacbell.net> wrote:
> A computer language with completely defined behavior
> (such as Java) translates into cheaper programmers (because they are
> less skilled) translates into the same or fewer programming defects
> (because programming mistakes are harder to make and more easily
> detected in time) and even translates into a shorter development cycle
> (because undefined behavior may mask bugs that take longer to find then
> a program whose behavior is known to be completely defined).
In practice, the result can be the opposite.
C++ compilers will very often turn undefined behaviour into a core dump
(wherever it is practical to do so on the platform in question).
In some other languages of note, the result of defining this behaviour
has been that exceptions are thrown
a) where there's no sensible means of recovery and
b) those exceptions can get swallowed up in exception handlers, so
that the program limps on in an undefined state, making for extremely
hard to catch bugs
I think there *is* too much undefined behaviour in C++, but simply
having all behaviour defined isn't necessarily an improvement.
James
>> If one writes portable code whose behaviour is not defined by the C++
>> Standard, then that's _their_ problem.
>
> No, the very fact that it is even possible to write a non-portable
> program is a problem that could only exist because the C++ "Standard"
> is incomplete. In other words, what the Standard euphemistically calls
> "undefined behavior" is nothing more than those areas of the C++
> language that have yet to be filled in. And if those areas were ever to
> be filled in, then concerns about "portable code" would all evaporate -
> because every C++ program would be portable.
The naivety astounds me! We could rid Standard C++ of all its undefined
behaviour, but then it wouldn't be nearly half as powerful!
Consider system code that does something like:
*(unsigned*)0x0000007F = OUTPUT_ENABLE|INPUT_FREEZE|FAIL_BIT_OFF;
This statement might have a very particular purpose on a particular system.
But do you think the C++ Standard should have to define its behaviour?
Three choices:
(1) Necessitate the implementation to define its behaviour.
(2) Prevent it.
(3) Leave its behaviour as undefined.
Option 1 will be a pain in the neck for compiler implementors. Why should
the developers of the new Playstation compiler sit around worrying about
programmers writing to arbitrary memory addresses?
Option 2 strips C++ of its power. Now we can't do what we wanted to do on
the implementation in question.
Option 3 is a compromise. We don't annoy the compiler developers, yet at
the same time C++ retains its power.
Seems to me like Option 3 is just fine.
--
Frederick Gotham
"The behavior is undefined if the right operand is negative, or greater than
or equal to the length in bits of the promoted left operand."
Why not just define the behavior?
If the right operand is negative, then its the same as a left-shift, by the
absolute value.
If its greater than or equal to the length in bits of the promoted left
operand, then its -1 if the number was negative, otherwise 0.
I don't really care what definition is chosen. Pick something reasonable.
Then, whatever hardware instructions are available should be used to make it
so.
terry
--
The trouble comes from the definition of things like log and sqrt for
complex numbers involving the sign of 0:
log(-0+0i) = -inf + i*Pi
log(0+0i) = -inf + 0i
sqrt(-x+0i) = i*sqrt(x)
sqrt(-x-0i) = -i*sqrt(x)
In other words, the sign of 0 makes a difference. When there is an
implicit 0, such as when a real or imaginary is converted to a complex,
which do you choose, -0 or +0? With a separate real type, we can
propagate through our algorithm the knowledge that it should not depend
on the sign of the (nonexistent) imaginary part. With no separate
imaginary type, we cannot correspondingly do this for the sign of the
(nonexistent) real part. We have to choose, -0 or +0, and our algorithms
lose that knowledge.
Furthermore, consider the arithmetic:
0*inf = NaN
-0*inf = NaN
But what if the 0 is an implicit 0? Then we want:
0*inf = 0
because consider multiplying
(0+inf*i)*0
The result we expect is
(0*0 + 0*inf*i)
or
(0+NaN*i).
The result we get with implicit 0 insertion (represented by X) is
(0*0 + 0*Xi + 0*inf*i + Xi*inf*i)
(0 + 0i + NaN*i - NaN)
(NaN+NaN*i).
Oops.
Without a separate imaginary type, there is no way to distinguish an
implicit 0 from an actual 0.
Here's some more reading:
http://www.open-std.org/jtc1/sc22/wg11/docs/n490.pdf
--
That's what I said.
> For a library solution, I've seen compiler steadily improving support
> for library functionalities -- think of GCC and its support for C
> library functions. I'm afraid your speculation is countered by actual
> data.
Ok, show me a language that is so user extensible so that, say, I can
construct a library so powerful that it can exactly emulate other
computer languages. In other words, where is language X that can accept
C++, Pascal, C#, Lisp, etc., source code just be adding on a powerful
library? Steadily improving support for libraries hardly constitutes
making libraries as powerful as the compiler. That's like saying if I
climb a mountain, I'm making progress towards the moon.
> | I think that's pretty obvious, since
>
> no, it is not.
If you think it can be done, by all means go for it.
> | If it was possible, out of the thousands of languages
> | invented, certainly one of them would have done so?
> Some have done quite a remarkable job at it; you just need to admit
> it. That is a separate problem.
I'd love to see a language where you could, say, add the ability to
compile C++ source by adding a library.
> http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2116.pdf
Thank you for the convenient reference. It's a good proposal. But I
don't think it really allows for user defined literals; what it does is
just do more advanced constant folding so you can have functions (and
constructors) in constant expressions. For example, the proposal still
does not allow:
complex foo = x + 3i; // 3i is an imaginary type
or:
Bigint x = 1238471289347189237489012734897123847182347182;
or even:
const Bigint x = Bigint("1238471289347189237489012734897123847182347182");
> | I know that D, at least, will not have user
> | defined tokens, for the reason that such would blow the legs off of
> | third party tools that process source without needing to be full blown
> | compilers.
>
> That is more a problem with D's design philosophy than an intrinsically
> linguistic issue.
It's hardly unique to D. C++ doesn't allow user defined tokens, either
(and neither does your C++ extension proposal). I know of no successful
computer language that does. I don't even know of any computer language
that does.
> | I don't think (2) can ever happen with C++, for the reason that it's
> | very hard to see how user defined syntax could ever be retrofitted in to
> | a language that is already the hardest language in existence to parse
> | (by a wide margin).
>
> I don't think your categorization of (2) is adequate. C++ has been
> offering (3) for more than 2 decades now.
It's very limited support for (3). There is no, for example, support for
user defined name lookup semantics. (And there shouldn't be!)
> There are several ways of
> doing (2) without necessarily having user defined tokens.
I separated out the issue of user defined syntax (1) from user defined
tokens (2).
> One of them is to allow users to attach their meaning to tokens.
I foresee a great future for new meanings for the 'static' keyword <g>.
--
Theoretically it does. The problems come about when one tries to make a
reasonable implementation that is able to also deal with 0 terminated
strings, which std::string must.
--
> [...]
> | Hasn't anyone ever wondered how exactly the C++
> | Standard is able to find so much undefined behavior in the execution of
> | the most deterministic finite state automaton ever invented - the
> | modern computer?
> (1) they are not deterministic.
It depends on the definition of deterministic. The entire
machine responds in a deterministic manner to external stimuli.
The external stimuli (e.g. exactly when the clock pulse which
causes a change between threads) aren't in any way
deterministic, of course, and the C++ language has no way of
taking the entire machine into accout, so it is also at the
liberty of arbitrary actions in the OS (like not enough memory
being available to increase stack size).
> (2) "undefined behaviour" has a very specific meaning technical in the C++
> definition text. Look for it in the first clause.
And other languages use other terms. Off hand, I don't know of
any language which doesn't have some undefined behavior. The
only real difference is that some do not have the courage to
admit it. (And some were developed before much thought had been
given to the concept. The Fortran language specification may
not use the word, but it definitly describes program constructs
which are illegal, but do not require a diagnostic---and which
in real life act very much like what C and C++ call undefined
behavior.)
--
James Kanze (Gabi Software) email: james...@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
--
No extension necessary. Got any problems with
const char literal[]="abc\x00cba\x00";
std::string str(literal,sizeof(literal)-1);
?
Regards,
Vladimir
> > >> I agree with the need for getting rid of undefined
> > >> behavior as much as possible, but in a systems oriented
> > >> language it's hard to see how it can be gotten rid of
> > >> completely.
> > > My opinion is the total opposite: Leave behaviour as
> > > undefined all over the place giving plenty of freedom to
> > > the implementation.
> > Ouch. Unless this is a joke, I can only be happy that your opinion isn't
> > shared by many :o). Why would you think undefined (I think you really
> > meant "unspecified") behavior is a good thing?
> casting a void * to a pointer to a function is undefined behaviour.
No it's not. It requires a diagnostic.
> But dlsym() which is a POSIX function returns a void * which often
> needs to be cast back to a pointer to a function.
Yes. But even Posix says not to cast the return value to a
void* (since Posix requires, indirectly, that the C compiler
refuse to compile the code if you do so). But it's true that
using the return value of dlsym() requires undefined behavior:
void (*pf)() ;
*(reinterpret_cast< void** >( &pf )) = dlsym( ... ) ;
(This is undefined behavior, since the cast itself is legal, but
using the results of it are undefined behavior.)
--
James Kanze (Gabi Software) email: james...@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
> > Can someone with a C++ implementation background actually confirm that
> > the great hassle that is UB significantly benefits the implementation?
> What great hassle is there with UB? Either you can do something in Standard
> C++, or you can't. Simple as.
And it is preferable that the compiler tell you when you err,
and try to do something that you can't. (A lot of the time it
does: try accessing a variable that isn't declared, for example.
Or assigning to a constant.)
> If one writes portable code whose behaviour is not defined by the C++
> Standard, then that's _their_ problem.
Actually, it's more their employers problem. Or the problem of
however has to maintain the software.
The real problem of course, is that programs are written by
human beings. And human beings make mistakes. At least I do; I
would never intentionnally write code which was undefined on the
platforms I target (although I do make use of things which are
undefined by the C++ standard, like dlopen). But I've been
known to make mistakes.
Of course, if everyone on your team is significantly more
qualified in C++ than I am, maybe different rules apply. (But
with no false modesty, I've yet to encounter such a team.)
> And what you seem to miss is that C++ is a general purpose programming
> language designed to be useful on many platforms. There are two major
> areas of undefined behaviour:
> 1) Places where requiring diagnosis is very expensive (or in some cases,
> equivalent to solving the halting problem). This is particularly true of
> problems arising from separate compilation. Some possible breaches of
> the ODR are very subtle (though any well taught programmer will avoid
> them)
> 2) Places where portability is essentially impossible because of
> different hardware having different requirements.
3) Places where someone guessed that sixies based optimization
technology might be able to gain a couple of microseconds (which
would be nanoseconds today) if the behavior wasn't specified.
IMHO, you 2) is essential, and interestingly enough, doesn't
really cause problems. I think compilers could do better with
regards to 1), but it's difficult to formulate the standard in
such a way that they are required to. And 3) is an
embarrasement to the language.
> It is interesting to note that even languages like Java that target a
> single platform (the JVM) exhibit undefined behaviour. At least C++ has
> the honesty to identify the problem areas.
In all probability, the next version of the standard will add 4)
threading problems. (Which in fact enters into your point 1).
Except that unlike most of 1) today, I don't think that
compilers can do much to detect it.)
--
James Kanze (Gabi Software) email: james...@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
--
[...]
> | I think that's pretty obvious, since
> no, it is not.
> | there are no examples of languages where libraries are as powerful as
> | the compiler.
> I see libraries as being more powerful than compilers in the sense
> that libraries allow for development, refinement, of several solutions
> to the a given problem, with at least the same efficiency as compiler,
> in a extremely shorter time than compilers. I have been using several
> implementations of complex classes way long before my favorite compilers
> decided to have an intrinsic type for complex numbers.
> Similarly for vectors.
I let that statement go, since Walter didn't bother to define
"more powerful", and without that definition, the statement is
meaningless. The obvious meaning is obviously not what he
meant. I know of libraries which can manage a GUI or an HTML
connection---now that's real power, and I've never seen anything
like that in a language.
Or does D have language primitives to open a window or create a
button?
--
James Kanze (Gabi Software) email: james...@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
--
I don't know D well enough to judge that. I just feel that if you say that
it works better with compiler support, that is bad news for library writers.
Perhaps we then cannot write good enough libraries for other types either?
Perhaps my aversion to compiler magic goes all the way back to my first
experience with Pascal. Easy to learn, and everything. Among other features,
it has read and write statements that looks just like procedures, where you
can have any number of parameters, in any order, and even add some
formatting hints. Very nice!
WRITE('The result is '; result:3:2, '. Processing time ', time:5, '
seconds.');
Now, how do I write that kind of an output procedure for my user-defined
types? Of course I cannot, it is all compiler magic, and only works for
built-in types! Blah!
So I don't like built-in types. :-)
>
>
>> The fact that Walter designs and implements his own language,
>> puts him in a
>> different position than most of us. Perhaps that influences his
>> point of view? Or maybe his views is the reason for doing it?
>
> Actually, it was using languages that did support strings and arrays
> much better than C++ that led me to want much better than what
> could be done with a library. Maybe it's a coincidence that such
> languages are almost always considered to be easier to learn, use
> and more productive to program in than C++. Strings and arrays are
> ubiquitously used, so even small improvements in their usability
> can pay big dividends in the long run.
>
>
>> I am very happy when I can implement, or extend, some feature
>> without specific compiler support.
>
> There's no way you're going to get std::string, std::vector or
> std::complex to work as well as core support for such with existing
> C++ core features.
In that case I would very much prefer if we could add the necessary core
features, rather than add the types to the core language. (I have noticed
that you have done some of that in D, but not enough obviously).
>
> But I do have a couple challenges for you <g>.
>
> 1) Extend std::string to support UTF-8.
Don't know. Probably can't be done.
>
> 2) Extend std::string to support strings with embedded 0's.
It can handle that, as long as you don't try do convert to or from char*.
Haven't found much use for it though.
Bo Persson
Nevertheless, more precision buys you more computations you can do
before having to deal with roundoff problems. Often, it's enough.
> And please take this in the somewhat humorous veine it is meant.
> Increasing precision is a solution sometimes, and I'm pretty
> sure that you do understand the problems, and know enough to
> verify that it is the correct solution in your case. But just
> as obviously, it's not a silver bullet, and it won't really help
> the naive user.
It will help the naive user simply because less often will he fall into
the roundoff swamp. And yes, any serious numerical analyst must take
steps to ensure that roundoff errors are not dominating his results,
regardless of the precision.
>> Any compiler that doesn't at least provide the full precision
>> of the underlying hardware cannot be taken seriously as a tool for doing
>> serious numerical analysis. It tells me the compiler vendor has some
>> agenda other than paying attention to the numerics crowd, and I wouldn't
>> use such a tool for serious numerical work.
>
> I think the problem is somewhat more complex. If you use long
> double on an Intel, you do not have the guard bits and other
> stuff
Are you sure about that?
> that helps ensure correct rounding.
Rounding is a kludge to soften the blow of too few bits. More bits is
better.
> As I understand it,
> the idea behind extended precision was that it should be used
> for intermediate results, and not for storing data---the idea is
> that an expression like a*b/c will always give the "correct"
> results if the correct results fit in a double.
If you store a double to memory, you lose guard bits and sticky bits.
Those bits are not stored in the FPU registers, either. They only exist
when, say, an ADD is being computed and the result is adjusted to fit
into the bits of the destination register. In other words, the
calculation rounded to fit the 80 bit registers. Then, it gets rounded
again when converted to a double to write into memory.
It's not better to round twice than to round once. More bits is better
when dealing with anything but the final result printed. Rounding should
be delayed as long as possible.
Here's an exercise for you. Do a chain of floating point calculations
with your calculator. Do it once by writing out the intermediate results
rounded to 2 decimal places, then reentering that value for the next
calculation. Do the whole thing again by using the full 10 digits on its
display.
You'll see what I'm talking about.
>> Unlike C++, a conforming D compiler is *required* to provide a type
>> representing the max precision the underlying hardware is capable of.
> For what definition of "the underlying hardware is capable of"?
> Obviously,
> this isn't what you mean, but while I think what you mean may be
> obvious on most general purpose machines, I'm not sure that it
> is precise enough for a standard.
I'm writing a newsgroup posting, not a legalese document that someone is
going to try to subvert.
> The C++ standard, of course, follows the lead of C, and allows
> the compiler to use extended precision in intermediate results,
> without requiring it. The results can be surprising, to put it
> mildly.
I know why the standard is written that way, but I simply do not agree
with the philosophy of dumbing down the language to capability of the
minimum machine it is defined to run on. If I buy a machine with 128 bit
floats, dad gum I want to use those bits. I don't care that the VAX has
less precision, I didn't buy a VAX. Why would I want to use a tool
dumbed down to VAX precision?
At least Java relented (after heavy pushback from users) with requiring
roundoff to 64 bits for all intermediate results. I'm just not so sure
the pushback was for numerical accuracy reasons, or just because it's
slow on the x86 to do that rounding.
>> And btw, g++ does offer 80 bit long doubles on the x86. Kudos
>> to the gcc implementors.
> I'm willing to bet that even VC++ uses extended precision on an
> x86, even if it won't allow you to declare a variable of that
> type. Not doing so slows down the math processor considerably.
While better than nothing, I don't consider that as support for extended
precision. Furthermore, I was very disappointed that while the x64 adds
all kinds of fancy floating point support, it completely omits extended
precision both for intermediate values and for types (other than legacy
support for the old instructions). I was hoping to see a 128 bit
floating point type.
| Alf P. Steinbach wrote:
| > But even if so, how does an Imaginary type help with that, when x+i*y
| > can always be represented as Complex(x,y) and vice versa?
|
| This explains it better than I can:
| http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf
Proof by authority.
OK, let's walk throught this.
C++'s library has operators overloaded for mixed operands, so no
wasteful arithmetic. It is just as in:
[...]
James Gosling has proposed. Kahans imaginary class allows real and
complex to mix without forcing coercions of real to complex. Thus his
classes avoid a little wasteful arithmetic ( with zero
imaginary parts ) that compilers can have trouble optimizing
away. Other than that, with overloaded infix arithmetic operators, you
can't tell the difference between Kahans syntax and Goslings.
Futhermore C99 standard type _Complex (equivalent of std::complex) has
arithmetics specified to take care of the branches and discontinuities.
So, there must be something more to your arguments than you have
said. It would very useful if you could articulate them for some of us
that are ignorant in numerics, instead of invoking proof by authority.
Thanks,
--
Gabriel Dos Reis
g...@integrable-solutions.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
Assuming the underlying hardware doesn't define such behaviour, the
compiler would have to generate a code like this for (X << Y):
if (Y < 0)
evaluate X >> Y instead
else if (Y >= bit_sizeof(X))
if (X < 0)
return -1
else
return 0
else
evaluate X << Y
Not all programs need/can afford this overhead. When the input is known
to be in a certain range, the program can skip the check. Otherwise, the
program can do the check itself. This is the merit that leaving some
corner cases undefined gives.
--
Seungbeom Kim
> Here's some Undefined Behavior from the C++ Standard that I have (which
> might be old) from 5.8-1.
>
> "The behavior is undefined if the right operand is negative, or greater
> than
>
> or equal to the length in bits of the promoted left operand."
>
I assume you're describing operator>> on integral types here.
> Why not just define the behavior?
> If the right operand is negative, then its the same as a left-shift, by
> the absolute value.
> If its greater than or equal to the length in bits of the promoted left
> operand, then its -1 if the number was negative, otherwise 0.
> I don't really care what definition is chosen. Pick something reasonable.
> Then, whatever hardware instructions are available should be used to make
> it
>
Thing is that with UB in the standard, the compiler can implement operator>>
with a single machine instruction. With your definition, operator>> on
Intel x86 becomes a test and branch to code that negates the right operand
and continues in operator<<, then two tests and branches for the case where
the length in bits isn't long enough, then (once all the error cases are
past), the same single machine instruction as before.
In this particular case, the well-defined case is also the common case; if
you need the more complex code, it's not hard to write it as code like
(untested for illustration only):
// Assuming 8-bit chars
template<typename T, typename S> T shiftright(T x, S y)
{
if(y < 0)
{
return shiftleft(x,-y); // definition of shiftleft is for the reader
}
if(y > (8 * sizeof(T))
{
if(x < 0)
{
return -1;
}
else
{
return 0;
}
}
return x >> y;
}
Bear in mind that on x86 (one of the most common architectures on people's
desktops), the compiler has to generate code like this for your proposed
definition of operator>>.
--
Simon Farnsworth
Well I have a candidate language: Forth. I am not going to go into
details here but I certainly implemented not only user defined semantics
but user defined syntax in Forth. Of course and Threaded Interpreted
Language is going to be very different to the common mainstream
languages but TILs are very powerful beasts.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
> Gabriel Dos Reis wrote:
>> So, the question is: Can there be better library implementations, or
>> can the core language be extended to allow better library
>> implementation? (e.g. allow for literal of user-defined types),
>> or do you think that there are *intrinsinc* reasons why they must be
>> core languages? If yes, could you elaborate on those logical,
>> intrinsinc, reasons?
>
> A compiler will always be more powerful than what's possible with the
> library, for the intrinsic reason that one can code the compiler to do
> whatever one wants to. With a library, you're stuck with what the
> compiler chooses to make available. I think that's pretty obvious, since
> there are no examples of languages where libraries are as powerful as
> the compiler.
FORTH.
And no, I'm not kidding.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
> James Kanze wrote:
>> But the argument that C++ doesn't have a string type is false.
>> It does.
>
> I didn't argue C++ didn't have a string type. I argued that:
>
> 1) library features are not part of the core language.
>
> 2) C++ (and D) do not have good enough core features to be able to
> create a library string (and vector, complex and associative arrays)
> that are good enough to compete with core support for such.
That, I buy. However...
> 3) String, complex, vector and associative arrays are ubiquitous enough
> that the extra goodies one can get with a core feature make them
> worthwhile to put in the core language.
....what does "put it in the core language" really mean? If you look
at Python, for example, the only part of string, list, and dict that
is truly and irremedially "in the core language" is the syntax for
literals. The rest could, in principle, be written in Python. Of
course, you'd need strings, lists, and dicts of some kind to do that,
but then Python doesn't have the low-level facilities of a systems
programming language, which would allow us to write those parts. D
doesn't have that limitation.
> | I know that D, at least, will not have user
> | defined tokens, for the reason that such would blow the legs off of
> | third party tools that process source without needing to be full blown
> | compilers.
>
> That is more a problem with D's design philosophy than an intrinsically
> linguistic issue.
Or a feature. It definitely could be seen as a problematic
consequence of C++'s design philosophy that third party tools for C++
are in short supply, and many of those that do exist still don't have
legs.
First, let me apologize for that post. Yes, I was only thinking of
signed-right shift.
Reading my post, I could barely discern that. Sorry.
Doesn't most hardware reasonably define these operations, so that the
runtime impact isn't quite so severe?
That's not rhetorical. I don't know. Hardware should behave better too.
One should expect to (possibly) give up performance in favor of defined
behavior when using shift with signed types.
If shift were only defined for unsigned and implicit conversion from
unsigned to signed were defined better,
then life would be easier (for me).
In my experience, the right hand operator (the shift value, Y) is typically
constant anyway.
So the compiler can generate fast, well-defined code.
If X and Y are unsigned, then things are better too.
return (Y < BitSizeof(X) ? (X<<Y) : 0;
I suppose compilers today can keep track of the possible range of
expressions, so the compiler may be able to infer that Y < BitSize(X) and
avoid the runtime check.
Not all projects can afford this undefined behavior.
Most C++ programmers have never read the standard.
They just expect reasonable looking code that compiles to work.
Its sad, but its reality.
So undefined behavior is desirable for performance reasons?
This requires the programmer to know more.
That is exactly why Java is so palatable. It lets me be lazy. Java forces
the hardware to behave "normally".
And in most cases, I don't really care about performance, because I can
demonstrate to the bosses with benchmarks and charts that we NEED a
better/faster processor.
I don't get blamed, the hardware does. This puts more emphasis on
processor/compiler selection.
In the case of the undefined behavior in C++, newbies (and most oldbies)
write software that looks correct, but isn't.
Code reviews don't catch it, and it takes weeks and weeks of wasted schedule
time to find all of these subtle bugs.
In these cases, anxiety is high and people lose their jobs. C++ gets
blamed.
Of course, one could argue that they deserve to lose their jobs, because
they didn't take their jobs seriously in the first place.
You know, focusing on meetings, process, and politics, and not bothering to
grok the standard.
With C++ I'm able to make a SafeInt class that does define this behavior and
other overflow/underflow cases, at the cost of performance.
That's cool. I never have the time to do that. Lazy again. If I made one,
no one would want to learn to use it. I wouldn't use it either, because
I"ve read the standard and have learned how to avoid these pitfalls. And I
secretly adore efficiency.
Bjarne Stroustrup implied that C++ would be enjoyable, not necessarily
easier.
I get the two concepts confused.
terry
--
> Ok, show me a language that is so user extensible so that, say, I can
> construct a library so powerful that it can exactly emulate other
> computer languages. In other words, where is language X that can accept
> C++, Pascal, C#, Lisp, etc., source code just be adding on a powerful
> library?
FORTH
> Steadily improving support for libraries hardly constitutes making
> libraries as powerful as the compiler. That's like saying if I climb
> a mountain, I'm making progress towards the moon.
Yeah, but computer languages don't really exploit all the the syntax
variability of those different languages. For example, pascal-style
comments vs. C++-style comments doesn't make any significant
difference in the expressive power of the two languages, so it isn't
important to be able to exactly emulate all of those languages.
What's important is to be able to write sufficiently expressive APIs,
for some definition of "sufficiently expressive." I don't believe C++
or D has been built with enough flexibility to allow what I consider
"sufficient."
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> Ok, show me a language that is so user extensible so that, say, I can
> construct a library so powerful that it can exactly emulate other
> computer languages. In other words, where is language X that can accept
> C++, Pascal, C#, Lisp, etc., source code just be adding on a powerful
> library?
FORTH. Just don't ask me to write any of those libraries! :)
> Steadily improving support for libraries hardly constitutes making
> libraries as powerful as the compiler. That's like saying if I climb
> a mountain, I'm making progress towards the moon.
Yeah, but computer languages don't really exploit all the the syntax
variability of those different languages. For example, pascal-style
comments vs. C++-style comments doesn't make any significant
difference in the expressive power of the two languages, so it isn't
important to be able to exactly emulate all of those languages.
What's important is to be able to write sufficiently expressive
library APIs, for some definition of "sufficiently expressive." I
don't believe C++ or D has been built with enough flexibility to allow
what I consider "sufficient."
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
See my reply to Alf P. Steinbach dated 11/22/2006 2:29 PM in this thread.
BTW, Prof. Kahan is the person behind the design of the 8087 floating
point CPU chip, as well as the IEEE 754 floating point specification. If
there is any authority on computer floating point, it'd be him. Although
argument by authority is a logical fallacy, I'd do my homework before
disagreeing with him on floating point issues.
http://www.dr-chuck.com/dr-chuck/papers/columns/r3114.pdf
--
Doing so would require:
1) adding user defined tokens
2) adding user defined syntax
While technically possible, I suspect that such a language would be
unusable in practice. It'd be like trying to shave holding a razor blade
in your hands. An infinitely customizable language would have no
touchstone, no point of commonality between one user's code and another's.
Did you ever write a Forth vocabulary? I have and among other things
implemented Logo on a Forth system.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects
[...]
| > For a library solution, I've seen compiler steadily improving support
| > for library functionalities -- think of GCC and its support for C
| > library functions. I'm afraid your speculation is countered by actual
| > data.
|
| Ok, show me a language that is so user extensible so that, say, I can
| construct a library so powerful that it can exactly emulate other
| computer languages.
I don't think that was the point I'm disputing. If you would prefer
to change topic, that is fine by me; but, let's make sure we start a
new thread and adequately change the "Subject:" too.
The question was not a language that is powerful enought to emulate
any other language. The point I was disputing was:
# A compiler will always be more powerful than what's possible with the
# library, for the intrinsic reason that one can code the compiler to do
# whatever one wants to. With a library, you're stuck with what the
# compiler chooses to make available.
[...]
| > | I think that's pretty obvious, since
| >
| > no, it is not.
|
| If you think it can be done, by all means go for it.
Again, you made a claim that some *allegation was obvious*.
I'm saying that the allegation was not obvious. That is a different
claim from from "it can be done".
| > | If it was possible, out of the thousands of languages
| > | invented, certainly one of them would have done so?
| > Some have done quite a remarkable job at it; you just need to admit
| > it. That is a separate problem.
|
| I'd love to see a language where you could, say, add the ability to
| compile C++ source by adding a library.
Are you insuating that it is impossible to have a C++ compiler as
library component in a C++ program?
| > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2116.pdf
|
| Thank you for the convenient reference. It's a good proposal. But I
| don't think it really allows for user defined literals; what it does is
| just do more advanced constant folding so you can have functions (and
| constructors) in constant expressions. For example, the proposal still
| does not allow:
|
| complex foo = x + 3i; // 3i is an imaginary type
struct imaginary {
constexpr explicit imaginary(double x = 0.0) : val(x) { }
friend constexpr imaginary
operator*(double re, imaginary im)
{ return imaginary(re * im.val); }
friend constexpr complex
operator+(double re, imaginary im)
{ return complex(re, im.val); }
// ...
private:
double val;
};
constexpr imaginary i(1.0); // constant expression of type imaginary
complex foo = x + 3 * i; // 3 * i is a constant expression of
// type imaginary
?
[...]
| > One of them is to allow users to attach their meaning to tokens.
|
| I foresee a great future for new meanings for the 'static' keyword <g>.
That is too easy a prediction.
--
Gabriel Dos Reis
g...@integrable-solutions.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
Has anyone proven this by writing a FORTH library that can accept C++
source code? Pascal code? C# code? Lisp code?
> What's important is to be able to write sufficiently expressive APIs,
> for some definition of "sufficiently expressive." I don't believe C++
> or D has been built with enough flexibility to allow what I consider
> "sufficient."
As I suggested to Bo Persson, such a "mother of all languages" may not
be that usable.
After all, why aren't you using FORTH?
--
I think you answered your question <g>. The only thing I can think of to
add is that Python may need to put such basic things it its core
language for performance reasons.
A constant theme I hear from heavy Python programmers is they have to be
adept at C because they have to write bits and pieces of their app in C
and hook them into the Python engine, because doing it in 100% Python is
too slow.
Neither D nor C++ have that problem.
--
| Gabriel Dos Reis wrote:
| > So, there must be something more to your arguments than you have
| > said.
|
| See my reply to Alf P. Steinbach dated 11/22/2006 2:29 PM in this thread.
I think I sent my message long before your reply appeared on my
newsserver, and I believe my message had been in the moderation for
some time. The usual stuff for a moderated group.
| BTW, Prof. Kahan is the person behind the design of the 8087 floating
| point CPU chip, as well as the IEEE 754 floating point specification.
As if I did not know.
But, the 8087 floating point implementation does not meet unanimous
consensus -- and this not just from ignorant programmers.
| If
| there is any authority on computer floating point, it'd be him. Although
| argument by authority is a logical fallacy,
Yes, argument by authority is a logical fallacy; that is why I was
excepting you to logically explain your points without having to
appeal "but Prof. Kahan says so".
--
Gabriel Dos Reis
g...@integrable-solutions.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
(Late in the thread, but this cannot be let slip away.) Whatever
happened to all languages that do manage to completely do away with
undefined behavior?
I'm asking this again: it would be best if we all refrained from "I'll
qualify it on-demand" statements.
Andrei
--