Generic programming is receiving more attention now-a-days. I am new to
functional programming, and I came to know that Haskell supports
polymorphic procedures and polytypes. Can somebody provide more
information on that or point me to some references/resources? I am also
looking at implementation details: is it that the implementation of
parametric polymorphism in functional languages a compile-time
mechanism (like C++)?
-Ganesh
|
|
0
|
|
|
|
Reply
|
sgganesh (28)
|
4/14/2005 6:39:22 AM |
|
Ganesh,
> Generic programming is receiving more attention now-a-days. I am new to
> functional programming, and I came to know that Haskell supports
> polymorphic procedures and polytypes. Can somebody provide more
> information on that or point me to some references/resources? I am also
> looking at implementation details: is it that the implementation of
> parametric polymorphism in functional languages a compile-time
> mechanism (like C++)?
It should be noted that the term 'generic programming' is actually a bit
overloaded: in the object-oriented world the term is usuallly used to
refer to programming with parametric polymorphism. In functional languages
like Haskell and ML parametric polymorphism is kind of taken for granted.
In these languages, the term 'generic programming' tends to be used for
language extensions that go beyond conventional forms of polymorphism.
Examples of these include structural polymorphism as implemented by PolyP
[1] and Generic Haskell [2], and the 'Scrap Your Boilerplate' approach.
I understand that it is non-generic---i.e., parametric---polymorphism you
are interested in. As said the parametric polymorphism is really pretty
basic in Haskell; therefore, any tutorial on the language is likely to
cover the subject; see, for example, Bird [3] or Hudak [4].
In Haskell (and ML) parameteric polymorphism is
definitely a compile-time mechanism. However, a comparison to templates in
C++ does not really hold, for AFAIK most C++ compilers do not perform
direct
checks on code containing template syntax, but rather desugar it before
processing. In Haskell, parametric polymorphism takes a much more
prominent position. Extensions for higher-ranked polymorphism even allow
polymorphic functions to be treated as first-class citizens.
Haskell programs are statically typed. That is, all type checks are
performed at compile time, and, consequently, types play no role at run
time. Implementation details thus mostly involve type checking and type
inference. If you would like to delve into the theory, I can recommend
Pierce's text book [5].
HTH,
Stefan
[1] http://www.cs.chalmers.se/~patrikj/poly/polyp/
[2] http://www.generic-haskell.org
[3] Richard Bird. Introduction to Functional Programming using Haskell.
Prentice Hall Europe, London, second edition, 1998.
[4] Paul Hudak. The Haskell School of Expression, Learning Functional
Programming Through Multimedia. Cambridge University Press, Cambridge,
2000.
[5] Benjamin C. Pierce. Types and Programming Languages. MIT Press,
Cambridge, Massachusetts, 2002.
|
|
0
|
|
|
|
Reply
|
sholderm (22)
|
4/14/2005 7:15:06 AM
|
|
sgganesh@gmail.com writes:
> Generic programming is receiving more attention now-a-days. I am new to
> functional programming, and I came to know that Haskell supports
> polymorphic procedures and polytypes. Can somebody provide more
> information on that or point me to some references/resources? I am also
> looking at implementation details: is it that the implementation of
> parametric polymorphism in functional languages a compile-time
> mechanism (like C++)?
I'll add a bit to Stefans excellent overview regarding the last point:
In functional languages, parametric polymorphism is always
type-checked (or inferred) at compile time, as Stefan said. However,
the code can be implemented in several ways:
- The most common way is to use the same code for all instances of
the type. This requires data to be of uniform size, so all values
that do not fit a register are "boxed" by putting them in memory
and just passing a pointer. This is usually done always, not just
at calls to polymorphic functions, so there is no extra overhead in
calling a polymorphic function, though there is a general overhead
in maintaining the uniform representation overall. This is similar
to the way generics are implemented in Java, where it is restricted
(IIRC) to object types, as these have a uniform representation.
- Some implementations (e.g., MLTon) use C++-like compile-time
instantiation of polymorphic functions to all the types at which
they are used. This allows specialization to values of different
size etc. and does not require an overall uniform representation.
It can, however, require many nearly-identical copies of the same
code for different types. Unlike C++, most functional languages
prohibit polymrphic recursion, so the number of instances is
guaranteed to be finite (though it can be very large).
Note that this difference is of implementation, not of language. The
same language can, and indeed often do, implement polymorphic types
differently in different compilers. Likewise, you will see the same
language compiled to bytecode or native code in different compilers.
Torben
|
|
0
|
|
|
|
Reply
|
torbenm265 (216)
|
4/14/2005 7:49:30 AM
|
|
Wow! that was an excellent overview.
>>It should be noted that the term 'generic programming' is actually a
bit
>>overloaded: in the object-oriented world the term is usuallly used to
>>refer to programming with parametric polymorphism.
Yes, I was referring to that, and that provided by dynamic languages
like Smalltalk.
>> In functional languages
>>like Haskell and ML parametric polymorphism is kind of taken for
granted.
Why?
>>In these languages, the term 'generic programming' tends to be used
for
>>language extensions that go beyond conventional forms of
polymorphism.
Can you elaborate on that. Few examples on how it is unconventional?
Can it be implemented in OO languages like Smalltalk/C++? If not why?
>>Examples of these include structural polymorphism as implemented by
PolyP
>>[1] and Generic Haskell [2], and the 'Scrap Your Boilerplate'
approach.
I'm yet to go through the links. Can you explain me what is structural
polymorphism?
>>I understand that it is non-generic---i.e., parametric---polymorphism
you
>>are interested in.
I am interested in generic programming in general, but my knowledge is
limited to parametric types (as in C++) and dynamic typing (as in
Smalltalk).
>> As said the parametric polymorphism is really pretty
>>basic in Haskell; therefore, any tutorial on the language is likely
to
>>cover the subject; see, for example, Bird [3] or Hudak [4].
Why is that you consider as very basic? The ability to create
polymorphic functions/types and type inference seems to be pretty good
in Haskell. If I compare Haskell generics to that of .NET generics/Java
generics, the latter's support is trivial.
>> However, a comparison to templates in C++ does not really hold, for
AFAIK most >> C++ compilers do not perform direct checks on code
containing template syntax,
>> but rather desugar it before processing.
Which compilers you are referring to? Direct checks for non-dependent
types (ie those types that doesnt depend on template type parameters)
is made when a template is defined and checking for dependent types are
done when the template is instantiated. C++ infact enfoces direct
checks, but in two phases.
>>Haskell programs are statically typed. That is, all type checks are
>>performed at compile time, and, consequently, types play no role at
run
>>time.
Does it mean that the objects don't have runtime type information
associated with them?
-Ganesh
|
|
0
|
|
|
|
Reply
|
sgganesh (28)
|
4/14/2005 8:33:40 AM
|
|
>>This is similar to the way generics are implemented in Java, where
it is restricted
>> (IIRC) to object types, as these have a uniform representation.
I am not sure about this. AFAIK, in Java, the parameteric types are
provided for type-safety,
and the parameterization information is lost after compilation is done;
this is done for maintaining
backward compatibility with older versions of Java where generics was
not supported.
>> Unlike C++, most functional languages
>> prohibit polymrphic recursion, so the number of instances is
>> guaranteed to be finite (though it can be very large).
Why is there this limitation? Polymorphic recursion allows for new
advances (for C++) in
doing "meta-programming", and is this not possible with parametric
polymorphism with
functional languages?
-Ganesh
|
|
0
|
|
|
|
Reply
|
sgganesh (28)
|
4/14/2005 8:44:44 AM
|
|
sgganesh@gmail.com wrote:
>>>As said the parametric polymorphism is really pretty
>>>basic in Haskell; therefore, any tutorial on the language is likely to
>>>cover the subject; see, for example, Bird [3] or Hudak [4].
>
> Why is that you consider as very basic? The ability to create
> polymorphic functions/types and type inference seems to be pretty good
> in Haskell. If I compare Haskell generics to that of .NET generics/Java
> generics, the latter's support is trivial.
It's "basic" in the sense that
a) it has very simple syntax and
b) there are no special caveats associated with it.
For example, Java's generics have a lot of syntactic sugar associated
with them, and compile-time checks sometimes fail to catch typing errors
(i.e the type system is "consistent").
I know of no OO language with a consistent static type system. (Which
says a lot about the amount of typing knowledge in the ranks of OO
language designers... note that the Generic Java extension were done by
type system experts, but they had to remain compatible with what exists,
so I don't expect that this is really type-safe.)
>>> However, a comparison to templates in C++ does not really hold,
>>> for AFAIK most C++ compilers do not perform direct checks on code
>>> containing template syntax, but rather desugar it before
>>> processing.
>
> Which compilers you are referring to? Direct checks for non-dependent
> types (ie those types that doesnt depend on template type
> parameters) is made when a template is defined and checking for
> dependent types are done when the template is instantiated. C++
> infact enfoces direct checks, but in two phases.
Type-parametric code in Haskell or ML can be type-checked in isolation.
For C++, such code cannot be type-checked unless it is instantiated with
parameter values.
That's a direct consequence of C++ templates being Turing-complete. In
other words, in C++ templates, you can specify *any* kind of computation
to be executed at compile time (though that may be quite tricky), while
in typical FPLs, the parametric type system is carefully constrained to
be statically checkable (and hence not Turing-complete).
Note that there's a little white lie involved. C++ templates would be
Turing-complete if it were not restricted - I think there's a maximum
instantiation depth of about 16. So you get the worst of both worlds -
lack of static checkability and an (admittedly very loose) limit on what
you can do with templates.
One thing that I'd like to see in FPL parametricity is the ability to
instantiate with values. I'd really like to write types like
vector_space 'num_dimensions 'coordinate_type
which is possible in C++ (i.e. vector_space<<3, real>>) but not in
typical FPLs. (Main reason probably being that this would require
differentiation between compile-time and run-time evaluation. Today's
FPLs typically don't differentiate, leaving it to the compiler to decide
what can be precompiled and what can't - nailing down in a language spec
which expressions are guaranteed to evaluate at compile time and hence
are suitable as type parameters creates language design and compiler
implementation constraints that are difficult to change afterwards.)
>>> Haskell programs are statically typed. That is, all type checks
>>> are performed at compile time, and, consequently, types play no
>>> role at run time.
>
> Does it mean that the objects don't have runtime type information
> associated with them?
It wouldn't be needed to implement a run-time system.
In practice, many implementations choose to associate type information
anyway, for other reasons. For example, garbage collection *can* be done
without type information, but it becomes an order of magnitude more
complex and difficult.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
4/14/2005 10:48:06 AM
|
|
sgganesh@gmail.com writes:
> >>This is similar to the way generics are implemented in Java, where
> it is restricted
> >> (IIRC) to object types, as these have a uniform representation.
> I am not sure about this. AFAIK, in Java, the parameteric types are
> provided for type-safety,
> and the parameterization information is lost after compilation is done;
> this is done for maintaining
> backward compatibility with older versions of Java where generics was
> not supported.
Parameterization is indeed lost, but no specialized copies of generic
functions/methods are made, so generic data has to be uniform. DUe to
backwards compatibility (as you mention), they are hence limited to
types that already have uniform representation, namely objects (that
are represented as pointers to heap-allocated structures).
Furthermore, since the JVM doesn't know about generics, arguments to
generic functions have type "object" and results are explicitly
downcast to their original type.
> >> Unlike C++, most functional languages
> >> prohibit polymrphic recursion, so the number of instances is
> >> guaranteed to be finite (though it can be very large).
>
> Why is there this limitation? Polymorphic recursion allows for new
> advances (for C++) in
> doing "meta-programming", and is this not possible with parametric
> polymorphism with
> functional languages?
Most functional languages use type inference, and this is undecidable
in the presense of polymorphic recursion. Some functional languages
allow polymorphic recursion if the polymorphic type is specified, as
checking is then decidable. If you don't specialize polymorphic
functions, it is no problem if there is a statically unbounded number
of instances, as the same code is used for all. If instances are
specialized at compile-time, as in C++, compilation may not terminate.
C++ programmers have, apparently, learnt to accept nontermination of
compilation, so you could argue that functional programmers should
also do so, and open up for unrestricted polymorphic recursion.
However, one can argue that meta-programming as used in C++ is better
done with a two-level language, where you can simply annotate certain
functions to be executed at compile-time. There are type systems that
ensure type-safety of such meta-functions _before_ they are applied
(unlike in C++, where type-checking is postponed until all templates
are instantiated).
You can also do some degree of type-safe meta-programming with
Haskell-style type classes, basically by encoding the meta-information
as "phantom types", types that are only used to control the
meta-programming but are not actually used for any values.
Torben
|
|
0
|
|
|
|
Reply
|
torbenm265 (216)
|
4/14/2005 11:38:04 AM
|
|
Joachim Durchholz wrote:
>
> For example, Java's generics have a lot of syntactic sugar associated
> with them,
If it were just "sugar" then you didn't have to care, but it's the basic
syntax that is annoyingly heavy-weight. Plus, lack of type inference
forces you to use it all over the place.
> and compile-time checks sometimes fail to catch typing errors
> (i.e the type system is "consistent").
s/consistent/inconsistent/
> Type-parametric code in Haskell or ML can be type-checked in isolation.
>
> For C++, such code cannot be type-checked unless it is instantiated with
> parameter values.
>
> That's a direct consequence of C++ templates being Turing-complete.
It's rather a consequence of templates simply being untyped (e.g. no
signatures for template arguments).
> In practice, many implementations choose to associate type information
> anyway, for other reasons. For example, garbage collection *can* be done
> without type information, but it becomes an order of magnitude more
> complex and difficult.
This is not correct. Actually, it's the other way round: type-directed
GC is much more complicated. The argument *for* type-directed GC is the
ability to have more efficient data representation. Unfortunately, the
necessary overhead rarely pays off in practice. Consequently, very few
systems use type-directed garbage collection.
- Andreas
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
4/14/2005 11:55:26 AM
|
|
>>For example, Java's generics have a lot of syntactic sugar associated
>>with them, and compile-time checks sometimes fail to catch typing
errors
>>(i.e the type system is "consistent").
I read [Benjamin C. Pierce. Types and Programming Languages. MIT Press,
Cambridge, Massachusetts, 2002], which also argues that type systems in
OO
languages are not consistent, but I found that its in extremely corner
cases (like that of
subtyping problem with ?: operator).
But I am not convinced that OO languages are really "bad" enough that
their type systems
are broken.
>>Type-parametric code in Haskell or ML can be type-checked in
isolation.
that is indeed surprising for me. How can you typecheck on a parametric
type without knowing
the type with which it would be instantiated with? Thats the reason why
C++ postpones the check
for operations on "dependent" names.
>> I think there's a maximum instantiation depth of about 16.
C++ standard requires a mininum of 256 instantiation depth (which is
quite enough for safe practical use).
>>(Main reason probably being that this would require
>>differentiation between compile-time and run-time evaluation. Today's
>>FPLs typically don't differentiate, leaving it to the compiler to
decide
>>what can be precompiled and what can't - nailing down in a language
spec
>>which expressions are guaranteed to evaluate at compile time and
hence
>>are suitable as type parameters creates language design and compiler
>>implementation constraints that are difficult to change afterwards.)
Why do you consider that they non-type arguments need to be a constant
expression?
It is true in case of C++, because, the template instantiation is a
compile-time mechanism.
In Ada generics, non-type arguments can indeed be variables. I don't
see why you can't
do the same in a functional lang. (but I don't know much about FP, so I
can't be sure).
-Ganesh
|
|
0
|
|
|
|
Reply
|
sgganesh (28)
|
4/14/2005 12:58:19 PM
|
|
sgganesh@gmail.com wrote:
>>> For example, Java's generics have a lot of syntactic sugar
>>> associated with them, and compile-time checks sometimes fail to
>>> catch typing errors (i.e the type system is "inconsistent").
>
> I read [Benjamin C. Pierce. Types and Programming Languages. MIT
> Press, Cambridge, Massachusetts, 2002], which also argues that type
> systems in OO languages are not consistent, but I found that its in
> extremely corner cases (like that of subtyping problem with ?:
> operator).
>
> But I am not convinced that OO languages are really "bad" enough that
> their type systems are broken.
There are two problems at work here.
One is that true subtype relationships are far rarer than one would
think, particularly if mutable data is involved.
For example, all Rectangles are Squares. If Rectangles and Squares are
immutable, then this is indeed true, but the subtype relationship does
*not* hold for the classes MutableRectangle (wich a setWidthHeight
function) and MutableSquare (which cannot be a subclass of
MutableRectangle because it has no way of implementing setWidthHeight -
it would either have to break the contract of setWidthHeight or its own
invariant).
The other is that many OO language designers are ignorant of the real
semantics of subtyping, and learn of holes in their type systems only
long after they have nailed the language semantics down. At that point,
language designers usually resort to run-time checking and exception
throwing, if they acknowledge the problem at all.
I have seen two cases here:
1) Covariance and contravariance. Most languages allow overriding a
function result with a subtype (which is sound), but some (most notably
Eiffel) allow overriding parameters as well (and that's unsound).
For a trivial example:
class foo {
some_type attribute;
virtual set_attribute (some_type new_value) {
attribute = new_value;
}
}
class foo2 inherit bar {
some_subtype attribute;
virtual set_attribute (some_subtype new_value) {
attribute = new_value;
}
}
Now say we have some code that uses 'foo', like this:
do_something (foo x)
some_type value;
// Some complicated computation that fills some_type
foo.set_attribute (x);
then this is OK if do_something is passed in a parameter of type foo;
but if it gets an object of type foo2, that object wants to be set with
a value of type some_subtype, and do_something will most likely
miserably crash. (Or throw an exception. In neither case we have a
static type system.)
The gist of this all is that you effectively can't have a subtype with a
different mutable field. Which kills about 90% of all usable subtype
designs in my experience...
2) Parametricity
That's a very, very common type system design mistake. If type A is a
subtype of type B, i.e. A <: B, language designers seem to assume that
this implies array[A] <: array[B]. Again, this holds only if at least
one of array[] or A/B are immutable; if both are mutable, we get into
the same kind of trouble as in case 1. (It may even be that there are
cases where having one of array[] A/B mutable is enough to break type
safety. I haven't gone through the trouble of checking all cases here.)
>>> Type-parametric code in Haskell or ML can be type-checked in
>>> isolation.
> that is indeed surprising for me. How can you typecheck on a
> parametric type without knowing the type with which it would be
> instantiated with? Thats the reason why C++ postpones the check for
> operations on "dependent" names.
It's done :-))
I think it's mostly because FPLs tend to have far more uniform and
simple type systems. In particular, they support a very simple notion of
subtype if they have subtypes at all, and that makes things considerably
easier. (Most of what OO-style subtyping and dynamic binding does can be
done easily with higher-order functions, i.e. functions that can take
other functions as arguments, and that may return functions. And what
can't be done easily that way usually isn't really worth doing. That
said, I do miss some of the things that can be done in the OO way, but
it's not a serious loss - and definitely worth losing lots of typical OO
design problems.)
>>> I think there's a maximum instantiation depth of about 16.
>
> C++ standard requires a mininum of 256 instantiation depth (which is
> quite enough for safe practical use).
Ah, I wasn't sure about that.
Sure, it's enough for most practical uses. It's also enough to prevent
the C++ template system from being Turing-complete though.
E.g. without that restriction, it would have been possible to write
templates for vector spaces, and making sure that different numbers of
dimensions cause a compile-time error. Now we're effectively limited to
vector spaces with at most 256 dimensions (give or take a few depending
on exact circumstances).
>>> (Main reason probably being that this would require
>>> differentiation between compile-time and run-time evaluation.
>>> Today's FPLs typically don't differentiate, leaving it to the
>>> compiler to decide what can be precompiled and what can't -
>>> nailing down in a language spec which expressions are guaranteed
>>> to evaluate at compile time and hence are suitable as type
>>> parameters creates language design and compiler implementation
>>> constraints that are difficult to change afterwards.)
>
> Why do you consider that they non-type arguments need to be a
> constant expression?
Because the result of an instantiation can still be a type, which must
be statically checkable.
If I allow writing types that are evaluable only at run-time, the
compiler obviously can't statically check types.
For example, if I have
a: array<<5, real>>
b: array<<dims, real>>
where 'dims' is a variable that's filled from user input, the compiler
can't check whether a and b have the same type or not.
> It is true in case of C++, because, the template instantiation is a
> compile-time mechanism. In Ada generics, non-type arguments can
> indeed be variables. I don't see why you can't do the same in a
> functional lang. (but I don't know much about FP, so I can't be
> sure).
It's a question of policy.
Actually I'm pretty sure that the expressions allowed in Ada generics
are limited to being compile-time evaluable. With some quite rigid
(conservative) restrictions of what can go into them. I'm not sure about
today's variant of Ada, but the '92 version was very, very limited here
- IIRC it was just arithmetic operators and a small set of functions
from the standard library (such as abs and sign). Most definitely no
user-written functions allowed there. (That would require the compiler
to execute the user-written function to determine the value that would
go into the function. In other words, the compiler would have to provide
a complete execution environment as well, and if it's an imperative
language, this would mean that the compiler would have to run in the
same environment as the one it's compiling for... and *that* would mean
that the Ada compiler would have to go into the embedded
microcontrollers for which is was compiling - certainly not a realistic
option. Things are easier for languages that don't have or strictly
control side effects, because then the compiler can check that the
user-defined function doesn't rely on external influences and run the
thing in a sandbox; the worst that can happen is that the user function
doesn't terminate, in which case the compiler can simply declare that
the user function is in error. Simply aborting after a full CPU second
would probably be good enough *gg*)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
4/14/2005 2:16:46 PM
|
|
sgganesh@gmail.com wrote:
>
> But I am not convinced that OO languages are really "bad" enough that
> their type systems are broken.
Unfortunately, there is no such thing as a mildly broken type system -
it is either sound or it isn't.
>>>Type-parametric code in Haskell or ML can be type-checked in isolation.
>
> that is indeed surprising for me. How can you typecheck on a parametric
> type without knowing
> the type with which it would be instantiated with?
Because either type checking is fully independent of the concrete type,
or a mechanism like the type class constraints in Haskell provides all
necessary information.
In C++, no type information is available at all about template
parameters (they are fully abstract), still the body isn't independent
from it (not even parsing!), so you loose. Note that generics in Java
took a more reasonable approach here.
>>>I think there's a maximum instantiation depth of about 16.
>
> C++ standard requires a mininum of 256 instantiation depth (which is
> quite enough for safe practical use).
The minimum requirement for recursive instantiation is 17 (see Annex B
of the standard). And only recursion provides for actual computation.
> Why do you consider that they non-type arguments need to be a constant
> expression?
> It is true in case of C++, because, the template instantiation is a
> compile-time mechanism.
If type equivalence is dependent on these arguments, then they must be
compile-time computable, otherwise the compiler wouldn't know what types
are compatible. This is the case in C++.
Ada generics work more like (S)ML functors - you generate new instances
from them *explicitly*, and all of them are considered different anyway.
So the identity of types does not really depend on the concrete
arguments (whether types or values).
- Andreas
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
4/14/2005 2:53:22 PM
|
|
torbenm@diku.dk (Torben �gidius Mogensen) writes:
> Unlike C++, most functional languages prohibit polymrphic
> recursion, so the number of instances is guaranteed to be finite
> (though it can be very large).
It's the other way around. C++ doesn't allow polymorphic recursion and
its model of templates can't support this. Haskell allows it, as long
as the type is declared explicitly. OCaml and SML don't allow it but
they could be extended to allow it.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
4/14/2005 5:05:11 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> sgganesh@gmail.com wrote:
> > It is true in case of C++, because, the template instantiation is a
> > compile-time mechanism. In Ada generics, non-type arguments can
> > indeed be variables. I don't see why you can't do the same in a
> > functional lang. (but I don't know much about FP, so I can't be
> > sure).
>
> It's a question of policy.
>
> Actually I'm pretty sure that the expressions allowed in Ada generics
> are limited to being compile-time evaluable.
No, that's not true. In Ada, one can pass run-time values to a generic.
They are evaluated at, well, run time as you might guess.
>... With some quite rigid
> (conservative) restrictions of what can go into them. I'm not sure about
> today's variant of Ada, but the '92 version was very, very limited
>here
There is no '92 version of Ada. The first version was Ada 83, the
current version is Ada 95, and Ada 2005 is coming along. All these
versions of the Ada language allow to pass dynamic values to a generic
package.
> - IIRC it was just arithmetic operators and a small set of functions
> from the standard library (such as abs and sign). Most definitely no
> user-written functions allowed there. (That would require the compiler
> to execute the user-written function to determine the value that would
> go into the function. In other words, the compiler would have to provide
> a complete execution environment as well, and if it's an imperative
> language, this would mean that the compiler would have to run in the
> same environment as the one it's compiling for... and *that* would mean
> that the Ada compiler would have to go into the embedded
> microcontrollers for which is was compiling - certainly not a realistic
> option. Things are easier for languages that don't have or strictly
> control side effects, because then the compiler can check that the
> user-defined function doesn't rely on external influences and run the
> thing in a sandbox; the worst that can happen is that the user function
> doesn't terminate, in which case the compiler can simply declare that
> the user function is in error. Simply aborting after a full CPU second
> would probably be good enough *gg*)
Yes, I agree that "Things are easier for languages that don't
have... side effects".
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
4/14/2005 11:39:33 PM
|
|
>>>>>I think there's a maximum instantiation depth of about 16.
>>> C++ standard requires a mininum of 256 instantiation depth (which
is
>>> quite enough for safe practical use).
>>The minimum requirement for recursive instantiation is 17 (see Annex
B
>>of the standard). And only recursion provides for actual computation.
Oops! I was wrong.
>>Ada generics work more like (S)ML functors - you generate new
instances
>>from them *explicitly*, and all of them are considered different
anyway.
The types of two instances of a generic unit for a same type/value
instantiated at runtime are
different! Isn't that bad; for example, I can't even assign or compare
directly since they are
of different types.
-Ganesh
|
|
0
|
|
|
|
Reply
|
sgganesh (28)
|
4/15/2005 5:48:33 AM
|
|
> But I am not convinced that OO languages are really "bad" enough that
> their type systems are broken.
>>I have seen two cases here:
I agree with both of them that they are flaws in the type system.
I have a question releated to the second case you pointed out:
For arrays and subtypes, in Java, it leads to throwing an exception in
case where we attempt
to assign a object of derived type to a array of a super class (which
leads to throwing an exception).
Is this a case of flaw in type system of Java?
-Ganesh
|
|
0
|
|
|
|
Reply
|
sgganesh (28)
|
4/15/2005 6:01:04 AM
|
|
>>C++ doesn't allow polymorphic recursion and
>>its model of templates can't support this.
I thought polymorphic recursion means recursive template instantiation.
Is it not; in
that case, what is polymorphic recursion (sorry I am not familiar with
FP terminology)?
-Ganesh
|
|
0
|
|
|
|
Reply
|
sgganesh (28)
|
4/15/2005 6:05:18 AM
|
|
Ganesh,
> I have a question releated to the second case you pointed out:
> For arrays and subtypes, in Java, it leads to throwing an exception in
> case where we attempt
> to assign a object of derived type to a array of a super class (which
> leads to throwing an exception).
> Is this a case of flaw in type system of Java?
It sure is. The support for generics in the .NET world is slightly better,
for it allows to define whether type parameters are covariant,
contravariant, or invariant; furthermore, the usage of these parameters
is checked accordingly. (This is implemented in the so-called Common Type
System, but
unfortunately not exposed in surface languages as C# and VB.)
A very accessible explanation of the problems with Java generics is
provided by Angelika Langer [1].
HTH,
Stefan
[1]
http://www.langer.camelot.de/Articles/Papers/JavaGenerics/ArraysInJavaGenerics.htm
|
|
0
|
|
|
|
Reply
|
sholderm (22)
|
4/15/2005 6:58:50 AM
|
|
Ganesh,
On 14 Apr 2005 sgganesh@gmail.com wrote:
> I thought polymorphic recursion means recursive template instantiation.
> Is it not; in
> that case, what is polymorphic recursion (sorry I am not familiar with
> FP terminology)?
Polymorphic recursion occurs when a polymorphic function is used
polymorphically within its own definition. Haskell allows
polymorphic-recursive functions, but only if those are decorated with
explicit type signatures.
Consider, for instance, the following---contrived---example:
f a = let x = f False
y = f 0
in a
(This is really just a complex way to define the identity function. ;))
In its own definition, f is applied to both a value of type Bool and a
numeric value: so, f is used polymorphically within its own defintion.
Hence, f exploits polymorphic recursion.
On its own, f would be rejected by a Haskell type checker. However, if we
add an explicit signature
f :: a -> a
the program passed type checking.
HTH,
Stefan
|
|
0
|
|
|
|
Reply
|
sholderm (22)
|
4/15/2005 7:14:18 AM
|
|
Ganesh,
> I'm yet to go through the links. Can you explain me what is structural
> polymorphism?
The main idea is that one can define generic functions by induction over
the
structure of types. (Whereas 'normal', non-generic functions are defined
by induction on the structure of type.)
As an example, parametricity [1] states that it is not possible to define
a parameterically polymorphic function
eq :: a -> a -> Bool
that checks equality of values for each type; such a function then can
only be constant or diverging.
In Generic Haskell [2], for instance, data types can be treated as if they
were defined in terms of only three basic types:
data Unit = Unit
data Sum a b = Inl a | Inr b
data Prod a b = Prod a b
Types are now viewed as sums of products.
For instance the type of parametric lists
data List a = Nil | Cons a (List a)
is viewed as
type List' a = Sum Unit (Prod a (List a))
Generic functions are no defined by giving cases for only the three
special types:
eq {| a :: * |} ::
(eq {| a |}) => a -> a ->
Bool
eq {| Unit |} Unit Unit = True
eq {| Sum a b |} (Inl a1) (Inl a2) = eq {| a |} a1 a2
eq {| Sum a b |} (Inl a1) (Inr b2) = False
eq {| Sum a b |} (Inr b1) (Inl a2) = False
eq {| Sum a b |} (Inr b1) (Inr b2) = eq {| b |} b1 b2
eq {| Prod a b |} (Prod a1 b1) (Prod a2 b2) =
eq {| a |} a1 a2 && eq {| b |} b1 b2
Now we have a equality function that does work for (almost) all types.
Well, this really is a very short introduction to the subject, but I hope
you got the idea.
HTH,
Stefan
[1] http://homepages.inf.ed.ac.uk/wadler/topics/parametricity.html
[2] http://www.generic-haskell.org
|
|
0
|
|
|
|
Reply
|
sholderm (22)
|
4/15/2005 7:28:26 AM
|
|
sgganesh@gmail.com wrote:
>
>>>Ada generics work more like (S)ML functors - you generate new instances
>>>from them *explicitly*, and all of them are considered different anyway.
>
> The types of two instances of a generic unit for a same type/value
> instantiated at runtime are
> different! Isn't that bad; for example, I can't even assign or compare
> directly since they are of different types.
In practice, it's not too much of a problem. You just have to share the
instantiation between all clients that use it. In ML, the module system
even provides sophisticated means to express this sharing across
abstraction boundaries (but ML also has plain polymorphism, where you
don't need explicit instantiation).
The C++ model certainly is somewhat more flexible, but you pay with a
number of restrictions (like compile-time arguments only). Worse, in the
face of separate compilation it leads to nasty problems with coherence
(enforcement of the "one definition rule" in C++ speak). That lead to
the addition of ad-hoc mechanisms for template "export" and explicit
instantiation (effectively moving it towards the other model), but as of
today, they still not solve these problems satisfactory, as far as I am
aware of it.
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
4/15/2005 8:55:39 AM
|
|
sgganesh@gmail.com wrote:
> >>C++ doesn't allow polymorphic recursion and
> >>its model of templates can't support this.
> I thought polymorphic recursion means recursive template
instantiation.
> Is it not; in
> that case, what is polymorphic recursion (sorry I am not familiar
with
> FP terminology)?
In general there seems to be some terminological confusion.
As others have said:
"generics" as it is used in most OO situations usually refers to
parametric polymorphism
What OO people usually refer to as "polymorphism" is usually more
specifically refered to as subtype polymorphism or inclusion
polymorphism (of course, as others have mentioned, usually a "subclass"
relationship is used rather than subtype which causes issues)
"generics" as used in FP usually refers to things like polytypic
programming (as others have mentioned, see e.g. Generic Haskell)
Something no one seems to have explicitly mentioned:
What C++ templates provide is not parametric polymorphism; at best it
could be said to include parametric polymorphism as a subcase. For
example, the template function
template <typename A> A min(A x,A y){ return x < y ? x : y; }
has (obviously) the (C++) type, template <typename A> A min(A,A); which
looks like min :: forall a.(a,a) -> a, which is definitely not the
case, the type is more like Haskell's min :: Ord a =>(a,a) -> a.
Essentially, min is not parametric in A (i.e. it lacks the
parametricity property), min will not work for any type but only those
that define operator< and even then the behavior will vary with the
definition of operator<.
Polymorphic recursion refers to calling a polymorphic function
recursively at a different type. This can't be implemented as template
instantiation as it would correspond to an infinitely deep recursion.
|
|
0
|
|
|
|
Reply
|
ddarius (161)
|
4/15/2005 8:05:54 PM
|
|
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> wrote:
>>>> C++ doesn't allow polymorphic recursion and its model of
>>>> templates can't support this.
and Darius wrote:
> Polymorphic recursion refers to calling a polymorphic function
> recursively at a different type. This can't be implemented as template
> instantiation as it would correspond to an infinitely deep recursion.
I think the statement is too strong. C++ doesn't support polymorphic
recursion for infinite type sequences. However, there are some valid
programs that contain polymorphic recursion. For example,
template <typename T>
void polymorphic(T x, T y) {
if (x == y) {
polymorphic("grumble", "mumble");
}
}
Ok, that's a bit contrived. Here's a more likely (and more useful)
example:
template <typename T>
ostream& operator<<(ostream& out, const list<T>& list)
{
typename list<T>::const_iterator it(list.begin()), end(list.end());
for (; it != end; it++)
out << *it << ' ';
return out;
}
list<list<int> > l;
...
cout << l;
Here's an example that's actually invalid:
template <typename T>
int poly(T x) {
if (false) {
poly(list<T>());
}
return 0;
}
Compare the similar(ly useless) Haskell function
poly :: a -> Int
poly x = let _ = poly [x] in 0
which is allowed.
Jeremy.
|
|
0
|
|
|
|
Reply
|
jeremy63 (294)
|
4/15/2005 10:10:11 PM
|
|
Robert A Duff wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
>>sgganesh@gmail.com wrote:
>>
>>> It is true in case of C++, because, the template instantiation is
>>> a compile-time mechanism. In Ada generics, non-type arguments can
>>> indeed be variables. I don't see why you can't do the same in a
>>> functional lang. (but I don't know much about FP, so I can't be
>>> sure).
>>
>> It's a question of policy.
>>
>> Actually I'm pretty sure that the expressions allowed in Ada
>> generics are limited to being compile-time evaluable.
>
> No, that's not true. In Ada, one can pass run-time values to a generic.
> They are evaluated at, well, run time as you might guess.
Non-type parameters if sgganesh is right.
(I overlooked that myself. My statements on restrictions over generic
types were meant for type-relevant parameters, such as array index
ranges, bounds for range types, or precisions for numeric non-integral
types. Sorry for not making this clear from the outset.)
>>... With some quite rigid
>>(conservative) restrictions of what can go into them. I'm not sure about
>>today's variant of Ada, but the '92 version was very, very limited
>>here
>
> There is no '92 version of Ada. The first version was Ada 83, the
> current version is Ada 95, and Ada 2005 is coming along.
Oh, right. I meant the '83 version.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
4/16/2005 9:44:57 AM
|
|
sgganesh@gmail.com wrote:
>> But I am not convinced that OO languages are really "bad" enough
>> that their type systems are broken.
>
>>>I have seen two cases here:
>
> I agree with both of them that they are flaws in the type system.
>
> I have a question releated to the second case you pointed out:
> For arrays and subtypes, in Java, it leads to throwing an exception in
> case where we attempt
> to assign a object of derived type to a array of a super class (which
> leads to throwing an exception).
> Is this a case of flaw in type system of Java?
I haven't checked it myself, but I have heard reports that Java doesn't
always throw exceptions when it should. If that's true, I consider that
a flaw in Java's type system.
Throwing exceptions in itself is not a type system flaw, but it makes
the type system less static. I think Java is more dynamic than it should be.
The typical OO type system flaws are a result of OO language designer
having to pick one of three evils:
1) accepting an unsound (flawed) type system,
2) excluding the majority of subtyping opportunities,
3) or using a rather weak type system that relies on run-time checking
and exceptions.
Most aim for (3), still get a certain amount of (2), and while trying to
reconcile these two they also get a certain amount of (1). (The only OO
language where I never heard about typing issues was Smalltalk. It
immediately opted for (3) and whole-heartedly embraced it.)
I see a fourth solution: avoid mutable data. Point (2) almost vanishes,
(1) can be fully done, and (3) can be reduced by at lest one order of
magnitude, and all without straining the ingenuity of the language
designer. Functional languages have shown what can be done with
immutable data, with loss in efficiency only in borderline cases (and
even these are being tackled right now).
(This all sounds as if OO could get away by simply adopting immutable
data. The trouble is that it turns out that the core OO mechanism,
dynamic binding, becomes far less valuable under an immutable regime.
But that's something that the OO language community will find out on
itself *evil grin*.)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
4/16/2005 9:57:08 AM
|
|
Stefan Holdermans wrote:
> Consider, for instance, the following---contrived---example:
>
> f a = let x = f False
> y = f 0
> in a
>
> (This is really just a complex way to define the identity function.
;))
Isn't this a bad example a recursive polymorphism? None of the
variables in the let statement are used in the in statement so why
should the compiler even bother with the let statement?
|
|
0
|
|
|
|
Reply
|
JohnCreighton_ (173)
|
4/16/2005 7:32:51 PM
|
|
Stefan Holdermans wrote:
> f a = let x = f False
> y = f 0
> in a
>
> In its own definition, f is applied to both a value of type Bool and a
> numeric value: so, f is used polymorphically within its own defintion.
> Hence, f exploits polymorphic recursion.
The interesting thing about polymorphic recursion, though, is that a single
function can be used at unboundedly many different types at run time. For
example:
-- I'm sure Chris Okasaki has a cleverer name for this datatype
data ExpList a = ExpCons a (ExpList (a,a))
-- example: ExpCons 1 (ExpCons (17,23) (ExpCons ((0,1),(42,666)) ...))
-- :: ExpList Int
indexExpList :: ExpList a -> Int -> a
indexExpList (ExpCons x xs) n
| n == 0 = x
| odd n = fst (indexExpList xs ((n-1) `div` 2))
| even n = snd (indexExpList xs ((n-2) `div` 2))
If you explicitly call indexExpList with type
(ExpList Char -> Int -> Char), it may, depending on the runtime value of the
Int argument, call itself at (ExpList (Char,Char) -> Int -> (Char,Char)),
(ExpList ((Char,Char),(Char,Char)) -> Int -> ((Char,Char),(Char,Char))), and
so on indefinitely. This is impossible with C++'s template mechanism: the
compiler would have to generate infinitely many versions of indexExpList.
-- Ben
|
|
0
|
|
|
|
Reply
|
br276deleteme (118)
|
4/20/2005 10:31:10 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> Robert A Duff wrote:
> > Joachim Durchholz <jo@durchholz.org> writes:
> >
> >>sgganesh@gmail.com wrote:
> >>
> >>> It is true in case of C++, because, the template instantiation is
> >>> a compile-time mechanism. In Ada generics, non-type arguments can
> >>> indeed be variables. I don't see why you can't do the same in a
> >>> functional lang. (but I don't know much about FP, so I can't be
> >>> sure).
> >> It's a question of policy.
> >>
> >> Actually I'm pretty sure that the expressions allowed in Ada
> >> generics are limited to being compile-time evaluable.
> > No, that's not true. In Ada, one can pass run-time values to a
> > generic.
> > They are evaluated at, well, run time as you might guess.
>
> Non-type parameters if sgganesh is right.
>
> (I overlooked that myself. My statements on restrictions over generic
> types were meant for type-relevant parameters, such as array index
> ranges, bounds for range types, or precisions for numeric non-integral
> types. Sorry for not making this clear from the outset.)
I'm not sure exactly what you mean. In Ada, bounds of arrays and
subranges of integer, enumeration, floating and fixed-point types can be
dynamic. And you can pass this dynamic information to a generic unit.
Precisions of floating and fixed-point types are static.
(As in "type T is digits 6;" or "type T is delta 0.01;".)
> >>... With some quite rigid
> >>(conservative) restrictions of what can go into them. I'm not sure about
> >>today's variant of Ada, but the '92 version was very, very limited
> >>here
> > There is no '92 version of Ada. The first version was Ada 83, the
> > current version is Ada 95, and Ada 2005 is coming along.
>
> Oh, right. I meant the '83 version.
What I said above is true of that version, and still true in later
versions.
By the way, the next version is supposed to be finished this year, as
far as producing a new Reference Manual. However, it's not clear
whether it will be Ada 2005 or 2006. ISO take months to go from a
final version to an officially approved standard. This process involvs
voting at several levels of beurocracy.
- Bob
P.S. Sorry for chatting about Ada in a functional newsgroup. ;-)
Just to say something relevant: I agree with sgganesh that
you could do similar things in a functional language.
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
4/21/2005 4:04:35 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> sgganesh@gmail.com wrote:
>
> >> But I am not convinced that OO languages are really "bad" enough
> >> that their type systems are broken.
> >
> >>>I have seen two cases here:
> > I agree with both of them that they are flaws in the type system.
> > I have a question releated to the second case you pointed out:
> > For arrays and subtypes, in Java, it leads to throwing an exception in
> > case where we attempt
> > to assign a object of derived type to a array of a super class (which
> > leads to throwing an exception).
> > Is this a case of flaw in type system of Java?
>
> I haven't checked it myself, but I have heard reports that Java doesn't
> always throw exceptions when it should. If that's true, I consider that
> a flaw in Java's type system.
Not sure what you mean by "when it should". One could argue that if
integer arithmetic overflows, it should throw an exception. Java wraps
around instead. If you're counting the number of widgets, wrap-around
arithmetic gives wrong answers. Is that an example?
(Of course, one could also argue that arithmetic should be arbitrary
range.)
I believe the array case mentioned by sgganesh is caused by Java's lack
of generics (in the original version of Java, anyway).
> Throwing exceptions in itself is not a type system flaw, but it makes
> the type system less static. I think Java is more dynamic than it should
> be.
I agree. But there will always be some "error" situations that can only
be detected dynamically, and the language has to do *something*: throw
an exception, return "bottom", return an arbitrary wrong answer...
> The typical OO type system flaws are a result of OO language designer
> having to pick one of three evils:
> 1) accepting an unsound (flawed) type system,
> 2) excluding the majority of subtyping opportunities,
> 3) or using a rather weak type system that relies on run-time checking
> and exceptions.
> Most aim for (3), still get a certain amount of (2), and while trying to
> reconcile these two they also get a certain amount of (1). (The only OO
> language where I never heard about typing issues was Smalltalk. It
> immediately opted for (3) and whole-heartedly embraced it.)
I think Java's type system is just as sound as Smalltalk's.
But then there are things that you can't do in the language.
(You can't very well write the garbage collector in the language
itself, if the language requires all arrays to be allocated
in a garbage-collected heap.)
> I see a fourth solution: avoid mutable data. Point (2) almost vanishes,
> (1) can be fully done, and (3) can be reduced by at lest one order of
> magnitude, and all without straining the ingenuity of the language
> designer. Functional languages have shown what can be done with
> immutable data, with loss in efficiency only in borderline cases (and
> even these are being tackled right now).
>
> (This all sounds as if OO could get away by simply adopting immutable
> data. The trouble is that it turns out that the core OO mechanism,
> dynamic binding, becomes far less valuable under an immutable
> regime. But that's something that the OO language community will find
> out on itself *evil grin*.)
;-)
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
4/21/2005 4:14:48 PM
|
|
Robert A Duff wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
>>sgganesh@gmail.com wrote:
>>
>>
>>>>But I am not convinced that OO languages are really "bad" enough
>>>>that their type systems are broken.
>>>>>I have seen two cases here:
>>>
>>>I agree with both of them that they are flaws in the type system.
>>>I have a question releated to the second case you pointed out:
>>>For arrays and subtypes, in Java, it leads to throwing an exception in
>>>case where we attempt
>>>to assign a object of derived type to a array of a super class (which
>>>leads to throwing an exception).
>>>Is this a case of flaw in type system of Java?
>>
>>I haven't checked it myself, but I have heard reports that Java doesn't
>>always throw exceptions when it should. If that's true, I consider that
>>a flaw in Java's type system.
>
> Not sure what you mean by "when it should". One could argue that if
> integer arithmetic overflows, it should throw an exception. Java wraps
> around instead. If you're counting the number of widgets, wrap-around
> arithmetic gives wrong answers. Is that an example?
No, not at all. This subthread is about type errors, i.e. values
assigned to names that don't belong to the declared type of the name.
Whether integer arithmetic is wrap-around or not is just a question of
what axioms are in use. Neither wrap-around nor exceptions are even near
to the Real Thing (nor is unlimited-size arithmetic, in case anyone
asks) - all fail to do proper integer arithmetic, though some will fail
sooner or later.
> (Of course, one could also argue that arithmetic should be arbitrary
> range.)
>
> I believe the array case mentioned by sgganesh is caused by Java's lack
> of generics (in the original version of Java, anyway).
Yes, but arrays are built-in generics, and their semantics is (AFAIK)
unchanged. What I heard (really not more than a rumor, though it sounded
quite convincing at that time) was that there was some type hole
associated with arrays, and that rumor predates Generic Java by more
than a year IIRC.
Again, I don't know any details, and forgot what keywords to feed to
Google to find anything substantial. It's a rumor, and unfounded right
now. I'd love to see somebody find evidence that supports or contradicts it.
>>Throwing exceptions in itself is not a type system flaw, but it makes
>>the type system less static. I think Java is more dynamic than it should
>>be.
>
> I agree. But there will always be some "error" situations that can only
> be detected dynamically, and the language has to do *something*: throw
> an exception, return "bottom", return an arbitrary wrong answer...
Well, arbitrary wrong answer is the worst of all alternatives.
Note that a Haskell function will never "return bottom". It's a
theoretical construct, nothing that a Haskell program will ever return.
If a value of bottom is ever constructed, the Haskell program will abort
with an error (or throw an exception, which is a way of not returning a
result - no, exceptions aren't considered a "result" in any meaningful
sense in Haskell).
>>The typical OO type system flaws are a result of OO language designer
>>having to pick one of three evils:
>>1) accepting an unsound (flawed) type system,
>>2) excluding the majority of subtyping opportunities,
>>3) or using a rather weak type system that relies on run-time checking
>>and exceptions.
>>Most aim for (3), still get a certain amount of (2), and while trying to
>>reconcile these two they also get a certain amount of (1). (The only OO
>>language where I never heard about typing issues was Smalltalk. It
>>immediately opted for (3) and whole-heartedly embraced it.)
>
> I think Java's type system is just as sound as Smalltalk's.
Given that Java's type system is 100% sound by virtue of its triviality,
I'd be *very* surprised if that held. (Even dynamic types in Smalltalk
aren't what most people think. The only useful way to define the type of
a Smalltalk objects seems to be "the set of messages that it doesn't
respond to with a #DoesNotUnderstand reply", and that's utterly
unrelated to classes, though - of course - classes still create related
types.)
> But then there are things that you can't do in the language.
> (You can't very well write the garbage collector in the language
> itself, if the language requires all arrays to be allocated
> in a garbage-collected heap.)
Not sure how that relates to typing.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
4/21/2005 5:29:52 PM
|
|
Joachim Durchholz wrote:
> Whether integer arithmetic is wrap-around or not is just a question of
> what axioms are in use. Neither wrap-around nor exceptions are even near
> to the Real Thing (nor is unlimited-size arithmetic, in case anyone
> asks) - all fail to do proper integer arithmetic, though some will fail
> sooner or later.
Hmm, why does unlimited size arithmetic fail? Because of the
limitations of computer memory? Or something more insidious?
Matt
|
|
0
|
|
|
|
Reply
|
angagon (2)
|
4/21/2005 7:10:29 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> Robert A Duff wrote:
>
> > Joachim Durchholz <jo@durchholz.org> writes:
> >
> >>sgganesh@gmail.com wrote:
> >>
> >>
> >>>>But I am not convinced that OO languages are really "bad" enough
> >>>>that their type systems are broken.
> >>>>>I have seen two cases here:
> >>>
> >>>I agree with both of them that they are flaws in the type system.
> >>>I have a question releated to the second case you pointed out:
> >>>For arrays and subtypes, in Java, it leads to throwing an exception in
> >>>case where we attempt
> >>>to assign a object of derived type to a array of a super class (which
> >>>leads to throwing an exception).
> >>>Is this a case of flaw in type system of Java?
> >>
> >>I haven't checked it myself, but I have heard reports that Java doesn't
> >>always throw exceptions when it should. If that's true, I consider that
> >>a flaw in Java's type system.
> > Not sure what you mean by "when it should". One could argue that if
> > integer arithmetic overflows, it should throw an exception. Java wraps
> > around instead. If you're counting the number of widgets, wrap-around
> > arithmetic gives wrong answers. Is that an example?
>
> No, not at all. This subthread is about type errors, i.e. values
> assigned to names that don't belong to the declared type of the name.
It's very difficult to talk about these things, because there's no
standard terminology. Every language has its own notion of "type".
Is divide-by-zero a "type error"? Depends on which language we're
talking about. But we're trying to talk about languages in general, and
there's no commonly agreed-upon (language independent) notion of "type".
It's easy to create a sound type system, if we have just one type.
The 'sh' language (I mean, Bourne shell in Unix) does that.
But it's not very useful, as a type system.
Sigh.
> Whether integer arithmetic is wrap-around or not is just a question of
> what axioms are in use.
OK, but it illustrates the fact that some type systems are more useful
than others. We could define zero-divided-by-zero to always return 17.
It's well defined, but in practise, it hides bugs, by giving wrong
answers. Better to raise an exception.
>... Neither wrap-around nor exceptions are even near
> to the Real Thing (nor is unlimited-size arithmetic, in case anyone
> asks) - all fail to do proper integer arithmetic, though some will fail
> sooner or later.
Indeed, but failing on numbers above 2**31-1 is very different from
failing on 2**(2**31), in practise. That is, "out of memory" is very
different from an arbitrary hardware-oriented restriction.
> > (Of course, one could also argue that arithmetic should be arbitrary
> > range.)
> > I believe the array case mentioned by sgganesh is caused by Java's lack
> > of generics (in the original version of Java, anyway).
>
> Yes, but arrays are built-in generics, and their semantics is (AFAIK)
> unchanged. What I heard (really not more than a rumor, though it sounded
> quite convincing at that time) was that there was some type hole
> associated with arrays, and that rumor predates Generic Java by more
> than a year IIRC.
>
> Again, I don't know any details, and forgot what keywords to feed to
> Google to find anything substantial. It's a rumor, and unfounded right
> now. I'd love to see somebody find evidence that supports or contradicts
> it.
I'd like to know precisely what that unfounded rumor *is*. Then some
Java expert could confirm or deny. (Not me -- I'm not a Java expert, at
least not on the latest version of the language.)
> >>Throwing exceptions in itself is not a type system flaw, but it makes
> >>the type system less static. I think Java is more dynamic than it should
> >>be.
> > I agree. But there will always be some "error" situations that can
> > only
> > be detected dynamically, and the language has to do *something*: throw
> > an exception, return "bottom", return an arbitrary wrong answer...
>
> Well, arbitrary wrong answer is the worst of all alternatives.
Indeed.
> Note that a Haskell function will never "return bottom". It's a
> theoretical construct, nothing that a Haskell program will ever
> return. If a value of bottom is ever constructed, the Haskell program
> will abort with an error (or throw an exception, which is a way of not
> returning a result - no, exceptions aren't considered a "result" in any
> meaningful sense in Haskell).
>
> >>The typical OO type system flaws are a result of OO language designer
> >>having to pick one of three evils:
> >>1) accepting an unsound (flawed) type system,
> >>2) excluding the majority of subtyping opportunities,
> >>3) or using a rather weak type system that relies on run-time checking
> >>and exceptions.
> >>Most aim for (3), still get a certain amount of (2), and while trying to
> >>reconcile these two they also get a certain amount of (1). (The only OO
> >>language where I never heard about typing issues was Smalltalk. It
> >>immediately opted for (3) and whole-heartedly embraced it.)
> > I think Java's type system is just as sound as Smalltalk's.
>
> Given that Java's type system is 100% sound by virtue of its triviality,
> I'd be *very* surprised if that held. (Even dynamic types in Smalltalk
> aren't what most people think. The only useful way to define the type of
> a Smalltalk objects seems to be "the set of messages that it doesn't
> respond to with a #DoesNotUnderstand reply", and that's utterly
> unrelated to classes, though - of course - classes still create related
> types.)
Again, one way to understand Smalltalk's type system is that there's one
type (object), and the type system is sound in that respect (you can't
create pointers to junk bits, as you can in C).
> > But then there are things that you can't do in the language.
> > (You can't very well write the garbage collector in the language
> > itself, if the language requires all arrays to be allocated
> > in a garbage-collected heap.)
>
> Not sure how that relates to typing.
You mentioned above, "1) accepting an unsound (flawed) type system".
Seems bad. But I just meant to say that if you want to write a GC,
you pretty-much have to accept that. I'm all for type checking, but I
don't know how to write a GC in a type-safe way (neither static nor
dynamic typing).
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
4/21/2005 8:23:10 PM
|
|
>
> Yes, but arrays are built-in generics, and their semantics is (AFAIK)
> unchanged. What I heard (really not more than a rumor, though it sounded
> quite convincing at that time) was that there was some type hole
> associated with arrays, and that rumor predates Generic Java by more
> than a year IIRC.
A "type hole" associated with arrays : no contravariance ?
|
|
0
|
|
|
|
Reply
|
tmartin637
|
4/21/2005 10:37:50 PM
|
|
>>I believe the array case mentioned by sgganesh is caused by Java's
lack
>>of generics (in the original version of Java, anyway).
Might be I have to be specific about what I meant:
$ cat typedefect1.java
class A {}
class B extends A {}
class typedefect1 {
public static void main(String [] s) {
A arr[] = new B[10];
arr[1] = new A();
}
}
$ javac typedefect1.java
$ java typedefect1
Exception in thread "main" java.lang.ArrayStoreException
at typedefect1.main(typedefect1.java:8)
$ cat typedefect2.java
interface CommonI {}
class X implements CommonI {}
class Y implements CommonI {}
class typedefect2 {
public static void main(String [] s) {
X x = new X();
Y y = new Y();
CommonI ci = true ? x : y;
}
}
$ javac typedefect2.java
typedefect2.java:11: incompatible types
found : Y
required: X
CommonI ci = true ? x : y;
^
1 error
There are many Gurus here, who understand type systems well,
can you confirm if these are typedefects in Java? For me, both appear
to be defects in type system of Java.
-Ganesh
|
|
0
|
|
|
|
Reply
|
sgganesh (28)
|
4/22/2005 8:22:13 AM
|
|
Robert,
> I'd like to know precisely what that unfounded rumor *is*. Then some
> Java expert could confirm or deny. (Not me -- I'm not a Java expert, at
> least not on the latest version of the language.)
I think the previous poster was referring to Java arrays being covariant
instead of contravariant.
Arrays being covariant means that when T1 is a subtype of T2,
T1 <: T2,
then T1[] is a subtype of T2,
T1[] <: T2[].
For instance, because
String <: Object,
we have
String[] <: Object[].
This means that we can declare and initialize
Object[] objs = new String[2];
and then, at compile time, it's perfectly legal to have
objs[0] = new Object(); // run-time error
You can see why covariance is an undesirable property for the array type
constructor.
If arrays would behave contravariantly, there would be no problem. So
T1 <: T2
would imply
T2[] <: T1[]
and
Object[] objs = new String[2]; // compile-time error
would not even be possible.
Furthermore, the we could have
String[] strs = new Object[2];
which is perfectly safe but not possible now.
So, I don't think it's a "rumour", and I certainly don't think it's
"unfounded". But perhaps this was not the issue that the previous poster
was referring to.
HTH,
Stefan
|
|
0
|
|
|
|
Reply
|
sholderm (22)
|
4/22/2005 8:36:05 AM
|
|
Stefan Holdermans <sholderm@students.cs.uu.nl> writes:
> If arrays would behave contravariantly, there would be no problem.
[...]
> Furthermore, the we could have
>
> String[] strs = new Object[2];
>
> which is perfectly safe but not possible now.
It's not safe. strs[0] would not be guaranteed to be a string if you
filled the array while it was seen as an object array.
Mutable arrays are by their nature invariant. But this choice for Java
would make impossible to write code which works for any array whose
element type is a subtype of T. By moving some checks to run time it
gains expressiveness: its type system is too weak to express this kind
of polymorphism, so it prefers to distinguish correct from incorrect
at run time than to disallow both.
Probably a better solution would be to support quantifiers over type
variables. This would complicate the type system and it would still be
sometimes too weak, but it would allow to express a large enough class
of programs that the "hole" could be removed. Perhaps generics now
allow this, I'm not familiar enough with their details.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
4/22/2005 9:46:07 AM
|
|
Marcin,
> Probably a better solution would be to support quantifiers over type
> variables. This would complicate the type system and it would still be
> sometimes too weak, but it would allow to express a large enough class
> of programs that the "hole" could be removed. Perhaps generics now
> allow this, I'm not familiar enough with their details.
I'm not sure how it's implemented in Java, but I do know that Microsoft's
CTS supports polarities for type variables; they are not available in
source languages like C# or VB.NET, though.
Regards,
Stefan
|
|
0
|
|
|
|
Reply
|
sholderm (22)
|
4/22/2005 11:33:58 AM
|
|
> Perhaps generics now allow this, I'm not familiar enough with their
> details.
Yes, they do.
Covariance : ClassName<? extends BaseType>
Contravariance : ClassName<? super BaseType>
However, the type of built-in arrays is not updated in order to be
comptible with the former version.
--
Thierry.
|
|
0
|
|
|
|
Reply
|
tmartin637
|
4/22/2005 9:14:48 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
[...]
| Note that there's a little white lie involved. C++ templates would be
| Turing-complete if it were not restricted - I think there's a maximum
| instantiation depth of about 16.
Some myths have long life.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/26/2005 11:44:12 AM
|
|
sgganesh@gmail.com writes:
[...]
| >> I think there's a maximum instantiation depth of about 16.
| C++ standard requires a mininum of 256 instantiation depth (which is
| quite enough for safe practical use).
That is not true either. See past extensive dicsussion in
comp.lang.scheme. The C++ standard states only that there is an
implementation defined limit -- value of which is not stated, especially
it does not require the limit to be finite, even though practical
considerations will make it.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/26/2005 11:50:04 AM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| The C++ model certainly is somewhat more flexible, but you pay with a
| number of restrictions (like compile-time arguments only). Worse, in
| the face of separate compilation it leads to nasty problems with
| coherence (enforcement of the "one definition rule" in C++
| speak). That lead to the addition of ad-hoc mechanisms for template
| "export" and explicit instantiation (effectively moving it towards the
| other model), but as of today, they still not solve these problems
| satisfactory, as far as I am aware of it.
Since day one of C++ template design, separate compilation of templates
has always been there. During C++ standardization, a diversion appeared
where suddenly a number of implementers have decided to implement only
the semantics of "inclusion model" (possibly because of absence of
prior experience with that "new" form of compilation). Then, there
was a "fight" to bring separate compilation back, as it was originally
part of the design. "export" was a compromise for that.
Explicit instantiation has always been part of the design and they are
not addition of ad-hoc mechanisms.
Surely, C++ template implementations pose real challenges which are
far beyond simply filling structures with pointer to functions and
claiming "genericity". Sadly, it looks like academic literature does
not offer better :-((
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/26/2005 12:03:17 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> sgganesh@gmail.com writes:
>
> [...]
>
> | >> I think there's a maximum instantiation depth of about 16.
> | C++ standard requires a mininum of 256 instantiation depth (which is
> | quite enough for safe practical use).
>
> That is not true either. See past extensive dicsussion in
> comp.lang.scheme. The C++ standard states only that there is an
> implementation defined limit -- value of which is not stated, especially
> it does not require the limit to be finite, even though practical
> considerations will make it.
I thought the standard gives a lower bound on that limit. (Correct me
if I am wrong.)
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
5/26/2005 12:16:00 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> |
> | > sgganesh@gmail.com writes:
> | >
> | > [...]
> | >
> | > | >> I think there's a maximum instantiation depth of about 16.
> | > | C++ standard requires a mininum of 256 instantiation depth (which is
> | > | quite enough for safe practical use).
> | >
> | > That is not true either. See past extensive dicsussion in
> | > comp.lang.scheme. The C++ standard states only that there is an
> | > implementation defined limit -- value of which is not stated, especially
> | > it does not require the limit to be finite, even though practical
> | > considerations will make it.
> |
> | I thought the standard gives a lower bound on that limit. (Correct me
> | if I am wrong.)
>
> It does not give a lower limit. What happens is that in the
> *informative* annexe B, it says a lower bound of 17 -- but that does
> not have any normative effect. To quote people directly involved in
> this business "it was 'pulled out of a hat'", but it was made sure it
> wasn't a power of 2 -- so that people don't draw wrong conclusions
> about its relevance. As I pointed out, 17 isn't that arbitrary, it
> has many mathematical properties :-)
>
> Last time, someone raised (in the C++ committee) similar issue about
> that limit it was agreed that it should be either removed the number or
> increased to another arbitrary number. Then someone pointed out the
> following facts (that was in 2003 and I haven't conducted a recent
> survey) about compilers in production use:
>
> EDG eccp: 64
> gcc 2.x: 17 (adjustible)
> gcc 3.x: 500 (adjustible)
> HP aCC: 255
> MSVC 7: 1031
> SunPro: 128
>
> -- Gaby
What does the standard say (in an "*informative* annexe" or wherever)
what the lower bound on the limit on recursion depth for function- and
method-calls is? What about nesting depth of "{ }" blocks? After all,
in practice these are bounded, too.
If it doesn't say anything about those, why has template recursion
been treated differently?
By the way, if you say that it isn't "normative", does that mean that
a compiler that limits it to, say, 1, would be a conforming C++
compiler? If not, why not?
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
5/26/2005 3:34:25 PM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > sgganesh@gmail.com writes:
| >
| > [...]
| >
| > | >> I think there's a maximum instantiation depth of about 16.
| > | C++ standard requires a mininum of 256 instantiation depth (which is
| > | quite enough for safe practical use).
| >
| > That is not true either. See past extensive dicsussion in
| > comp.lang.scheme. The C++ standard states only that there is an
| > implementation defined limit -- value of which is not stated, especially
| > it does not require the limit to be finite, even though practical
| > considerations will make it.
|
| I thought the standard gives a lower bound on that limit. (Correct me
| if I am wrong.)
It does not give a lower limit. What happens is that in the
*informative* annexe B, it says a lower bound of 17 -- but that does
not have any normative effect. To quote people directly involved in
this business "it was 'pulled out of a hat'", but it was made sure it
wasn't a power of 2 -- so that people don't draw wrong conclusions
about its relevance. As I pointed out, 17 isn't that arbitrary, it
has many mathematical properties :-)
Last time, someone raised (in the C++ committee) similar issue about
that limit it was agreed that it should be either removed the number or
increased to another arbitrary number. Then someone pointed out the
following facts (that was in 2003 and I haven't conducted a recent
survey) about compilers in production use:
EDG eccp: 64
gcc 2.x: 17 (adjustible)
gcc 3.x: 500 (adjustible)
HP aCC: 255
MSVC 7: 1031
SunPro: 128
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/26/2005 4:24:51 PM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Matthias Blume <find@my.address.elsewhere> writes:
| >
| > | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
| > |
| > | > sgganesh@gmail.com writes:
| > | >
| > | > [...]
| > | >
| > | > | >> I think there's a maximum instantiation depth of about 16.
| > | > | C++ standard requires a mininum of 256 instantiation depth (which is
| > | > | quite enough for safe practical use).
| > | >
| > | > That is not true either. See past extensive dicsussion in
| > | > comp.lang.scheme. The C++ standard states only that there is an
| > | > implementation defined limit -- value of which is not stated, especially
| > | > it does not require the limit to be finite, even though practical
| > | > considerations will make it.
| > |
| > | I thought the standard gives a lower bound on that limit. (Correct me
| > | if I am wrong.)
| >
| > It does not give a lower limit. What happens is that in the
| > *informative* annexe B, it says a lower bound of 17 -- but that does
| > not have any normative effect. To quote people directly involved in
| > this business "it was 'pulled out of a hat'", but it was made sure it
| > wasn't a power of 2 -- so that people don't draw wrong conclusions
| > about its relevance. As I pointed out, 17 isn't that arbitrary, it
| > has many mathematical properties :-)
| >
| > Last time, someone raised (in the C++ committee) similar issue about
| > that limit it was agreed that it should be either removed the number or
| > increased to another arbitrary number. Then someone pointed out the
| > following facts (that was in 2003 and I haven't conducted a recent
| > survey) about compilers in production use:
| >
| > EDG eccp: 64
| > gcc 2.x: 17 (adjustible)
| > gcc 3.x: 500 (adjustible)
| > HP aCC: 255
| > MSVC 7: 1031
| > SunPro: 128
| >
| > -- Gaby
|
| What does the standard say (in an "*informative* annexe" or wherever)
| what the lower bound on the limit on recursion depth for function- and
| method-calls is? What about nesting depth of "{ }" blocks? After all,
| in practice these are bounded, too.
Annex B
(informative)
Implementation quantities
1 Because computers are finite, C++ implementations are inevitably
limited in the size of the programs they can successfully
process. Every implementation shall document those limitations
where known. This documentation may cite fixed limits where they
exist, say how to compute variable limits as a function of
available resources, or say that fixed limits do not exist or are
unknown.
2 The limits may constrain quantities that include those described
below or others. The bracketed number following each quantity is
recommended as the minimum for that quantity. However, these
quantities are only guidelines and do not determine compliance.
-- Nesting levels of compound statements, iteration control
structures, and selection control structures [256].
-- Nesting levels of conditional inclusion [256].
-- Pointer, array, and function declarators (in any combination)
modifying an arithmetic, structure, union, or incomplete type
in a declaration [256].
-- Nesting levels of parenthesized expressions within a full
expression [256].
-- Number of characters in an internal identifier or macro name
[1 024].
-- Number of characters in an external identifier [1 024].
-- External identifiers in one translation unit [65 536].
-- Identifiers with block scope declared in one block [1 024].
-- Macro identifiers simultaneously defined in one translation
unit [65 536].
-- Parameters in one function definition [256].
-- Arguments in one function call [256].
-- Parameters in one macro definition [256].
-- Arguments in one macro invocation [256].
-- Characters in one logical source line [65 536].
-- Characters in a character string literal or wide string
literal (after concatenation) [65 536].
-- Size of an object [262 144].
-- Nesting levels for #include files [256].
-- Case labels for a switch statement (excluding those for any
nested switch statements) [16 384].
-- Data members in a single class, structure, or union [16 384].
-- Enumeration constants in a single enumeration [4 096].
-- Levels of nested class, structure, or union definitions in a
single struct-declaration-list [256].
-- Functions registered by atexit()[32].
-- Direct and indirect base classes [16 384].
-- Direct base classes for a single class [1 024].
-- Members declared in a single class [4 096].
-- Final overriding virtual functions in a class, accessible or
not [16 384].
-- Direct and indirect virtual bases of a class [1 024].
-- Static members of a class [1 024].
-- Friend declarations in a class [4 096].
-- Access control declarations in a class [4 096].
-- Member initializers in a constructor definition [6 144].
-- Scope qualifications of one identifier [256].
-- Nested external specifications [1 024].
-- Template arguments in a template declaration [1 024].
-- Recursively nested template instantiations [17].
-- Handlers per try block [256].
-- Throw specifications on a single function declaration [256].
| If it doesn't say anything about those, why has template recursion
| been treated differently?
|
| By the way, if you say that it isn't "normative", does that mean that
| a compiler that limits it to, say, 1, would be a conforming C++
| compiler? If not, why not?
A compiler can set the limit to 1, it would be conformant in that
regard. Whether it would be useful is a different question :-)
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/26/2005 9:54:42 PM
|
|
Gabriel Dos Reis wrote:
>
> | The C++ model certainly is somewhat more flexible, but you pay with a
> | number of restrictions (like compile-time arguments only). Worse, in
> | the face of separate compilation it leads to nasty problems with
> | coherence (enforcement of the "one definition rule" in C++
> | speak). That lead to the addition of ad-hoc mechanisms for template
> | "export" and explicit instantiation (effectively moving it towards the
> | other model), but as of today, they still not solve these problems
> | satisfactory, as far as I am aware of it.
>
> Since day one of C++ template design, separate compilation of templates
> has always been there. During C++ standardization, a diversion appeared
> where suddenly a number of implementers have decided to implement only
> the semantics of "inclusion model" (possibly because of absence of
> prior experience with that "new" form of compilation). Then, there
> was a "fight" to bring separate compilation back, as it was originally
> part of the design. "export" was a compromise for that.
Thanks for the clarification, although it doesn't quite contradict what
I said in the quoted text. AFAICS, the coherence problem is still a
fundamental one, and can only be addressed at link time.
Moreover, has anything changed about the fact that even a decade after
its introduction at most one existing implementation seems to be dealing
with "export" properly? I don't think it is unfair to say that true
separate compilation mostly was (and unfortunately still is) wishful
thinking more than reality.
> Explicit instantiation has always been part of the design and they are
> not addition of ad-hoc mechanisms.
If I remember correctly from D&E (or ARM?), first versions of templates
didn't have it, but I may be mistaken. In any case, I stand by my claim
that it is an ad-hoc mechanism.
> Surely, C++ template implementations pose real challenges which are
> far beyond simply filling structures with pointer to functions and
> claiming "genericity". Sadly, it looks like academic literature does
> not offer better :-((
I suppose that depends on your definition of "better". Of course, you
won't find anything that subsumes all that templates do (not least
because that may not exactly be deemed desirable). But you will
definitely find "academic" languages that offer comparable mechanisms
that are even more expressive along certain axes, while staying much
more structured and principled. Type classes come to mind immediately,
which - incidentally - /can/ be compiled into tuples of functions.
Note that the inability to do the latter for templates might rather be a
consequence of their unstructured nature (plus the lack of closures and
other issues of C++) rather than of their expressiveness.
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
5/30/2005 10:03:50 AM
|
|
Gabriel Dos Reis wrote:
>
> | If it doesn't say anything about those, why has template recursion
> | been treated differently?
> |
> | By the way, if you say that it isn't "normative", does that mean that
> | a compiler that limits it to, say, 1, would be a conforming C++
> | compiler? If not, why not?
>
> A compiler can set the limit to 1, it would be conformant in that
> regard. Whether it would be useful is a different question :-)
Then the situation is, in fact, worse than I anticipated.
What's the value of a standard if it doesn't even guarantee that you can
make practical use of some feature at all??
The usual quality-of-implementation argument is moot in that respect. By
that argument, we wouldn't need a normative standard in the first place.
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
5/30/2005 10:06:52 AM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| Gabriel Dos Reis wrote:
| > | If it doesn't say anything about those, why has template
| > recursion
| > | been treated differently?
| > | | By the way, if you say that it isn't "normative", does that mean
| > that
| > | a compiler that limits it to, say, 1, would be a conforming C++
| > | compiler? If not, why not?
| > A compiler can set the limit to 1, it would be conformant in that
| > regard. Whether it would be useful is a different question :-)
|
| Then the situation is, in fact, worse than I anticipated.
Quite possible. As I have been trying to taint this whole discussion
with a little of reality, have you found any C++ compiler in
production use/existence that set that limit to 1? Or is it just pure
speculation?
| What's the value of a standard if it doesn't even guarantee that you
| can make practical use of some feature at all??
Oh, neither the C (nor the C++) standard guarantees that a C (or C++)
compiler will accept and run the following program
int main(void) { return 0; }
still the respective standards have value for interested parties. It
might just be that there are people using them and people talking
about people using them.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/30/2005 9:45:56 PM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
[...]
| > Surely, C++ template implementations pose real challenges which are
| > far beyond simply filling structures with pointer to functions and
| > claiming "genericity". Sadly, it looks like academic literature does
| > not offer better :-((
|
| I suppose that depends on your definition of "better". Of course, you
| won't find anything that subsumes all that templates do (not least
| because that may not exactly be deemed desirable). But you will
| definitely find "academic" languages that offer comparable mechanisms
| that are even more expressive along certain axes, while staying much
| more structured and principled. Type classes come to mind immediately,
| which - incidentally - /can/ be compiled into tuples of functions.
I think I specifically dismissed compilation into tuples of functions
on the ground that it does not match the expressive power offered by
templates. There is a urban legend that C or C++ designers or
implementers obviously don't quite understand functional programming
languages and features and implementations. That legend, for large
part, is unfounded.
| Note that the inability to do the latter for templates might rather be
| a consequence of their unstructured nature (plus the lack of closures
| and other issues of C++) rather than of their expressiveness.
As a well known Swiss Army instruction goes, when the terrain and the
map differ -- trust the terrain. No doubt some programming languages
are invented to prove a point, but I've come to realize that the C++
templates were designed to solve a problem. I'm not claiming it is
perfect (and I'm hoping for improvements) but theoretical
"unstructure" arguments without considering constraints offer little
clue.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/30/2005 10:03:22 PM
|
|
Gabriel Dos Reis wrote:
>
> | > Surely, C++ template implementations pose real challenges which are
> | > far beyond simply filling structures with pointer to functions and
> | > claiming "genericity". Sadly, it looks like academic literature does
> | > not offer better :-((
> |
> | I suppose that depends on your definition of "better". Of course, you
> | won't find anything that subsumes all that templates do (not least
> | because that may not exactly be deemed desirable). But you will
> | definitely find "academic" languages that offer comparable mechanisms
> | that are even more expressive along certain axes, while staying much
> | more structured and principled. Type classes come to mind immediately,
> | which - incidentally - /can/ be compiled into tuples of functions.
>
> I think I specifically dismissed compilation into tuples of functions
> on the ground that it does not match the expressive power offered by
> templates.
Yes, and I tried to point out (quote below) that this is a faulty
argument. I even believe that with some tweaks a clean-ups you could
apply that technique to something close enough to templates. That you
cannot do so in C++ is a consequence of the ad-hoc nature of many of its
other features that in multiplicity preclude a systematic approach to
template compilation other than macro expansion. For starters, its
baroque, context-dependent scoping and name resolution rules, on top of
highly ambiguous syntax.
> There is a urban legend that C or C++ designers or
> implementers obviously don't quite understand functional programming
> languages and features and implementations. That legend, for large
> part, is unfounded.
OK, I take your word for it. Certain aspects of C++ - particularly with
respect to typing - certainly make that hard to believe.
> | Note that the inability to do the latter for templates might rather be
> | a consequence of their unstructured nature (plus the lack of closures
> | and other issues of C++) rather than of their expressiveness.
>
> As a well known Swiss Army instruction goes, when the terrain and the
> map differ -- trust the terrain. No doubt some programming languages
> are invented to prove a point, but I've come to realize that the C++
> templates were designed to solve a problem.
I read that as implicitly claiming that the same would not be true for
similar features in FPLs or other "academic" languages. That does not
quite support your previous point about urban legends... ;-)
> I'm not claiming it is
> perfect (and I'm hoping for improvements) but theoretical
> "unstructure" arguments without considering constraints offer little
> clue.
Oh, I am aware of the constraints. Does not lead me to like the outcome,
though. The problem are these constraints to start with, templates just
add to the complexity.
- Andreas
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
5/31/2005 9:26:49 AM
|
|
I recently came across this in a web discussion forum, and thought it
kind of cute (even if the author is possibly sincere, and the typo an
accident):
| C++ is one of those few languages that allow you to do low-level
| stuff, compiles to compact and efficient code, yet also has concise
| powerful syntax (how many languages allow you to specify matrix
| multiplication by saying a + b?).
-kzm
--
If I haven't seen further, it is by standing in the footprints of giants
|
|
0
|
|
|
|
Reply
|
news2 (145)
|
5/31/2005 9:37:50 AM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| Gabriel Dos Reis wrote:
| > | > Surely, C++ template implementations pose real challenges which
| > are
| > | > far beyond simply filling structures with pointer to functions and
| > | > claiming "genericity". Sadly, it looks like academic literature does
| > | > not offer better :-((
| > | | I suppose that depends on your definition of "better". Of
| > course, you
| > | won't find anything that subsumes all that templates do (not least
| > | because that may not exactly be deemed desirable). But you will
| > | definitely find "academic" languages that offer comparable mechanisms
| > | that are even more expressive along certain axes, while staying much
| > | more structured and principled. Type classes come to mind immediately,
| > | which - incidentally - /can/ be compiled into tuples of functions.
| > I think I specifically dismissed compilation into tuples of functions
| > on the ground that it does not match the expressive power offered by
| > templates.
|
| Yes, and I tried to point out (quote below) that this is a faulty
| argument.
I think, you made that statement without actually showing why it is so.
Clearly, compiling to tuple of functions is already supported by
C++ in form of virtual functions. Templates, by design, were based on
the idea that when instantiated they should match the code as if it was
hand crafted directly. It is hard, near to impossible to match that
zero-overhead if you comile to a tuple of functions with current
compiler technology. It is very tempting to hide the inefficency of
tuple of functions behing the angle-bracket notation, as is done by
some languages. But, in the case of C++ that is a real concern and a
direct part of C++ template success. It is not an argument, It is
report of a fact. See below.
| I even believe that with some tweaks a clean-ups you could
| apply that technique to something close enough to templates. That you
What specifically are those "twaeks and clean-ups"? That is not an
argumentative question, as this is an area I have high interest in and
open to suggestions.
| cannot do so in C++ is a consequence of the ad-hoc nature of many of
| its other features that in multiplicity preclude a systematic approach
| to template compilation other than macro expansion. For starters, its
| baroque, context-dependent scoping and name resolution rules, on top
| of highly ambiguous syntax.
Oh, the syntax is not the problem to separate compilation. It is not
what precludes compilation to tuple of functions. The dependent name
resolution is necessary if one ever wanted to meaningfully abstract
over anything. You earlier metioned type classes, but that is exactly
what they do -- the name in those cases designate pointer to member
fields of tuples. And use of type classes is context dependent too.
So, exactly what are those solutions? Handwaving does not give me a clue.
[...]
| > | Note that the inability to do the latter for templates might rather be
| > | a consequence of their unstructured nature (plus the lack of closures
| > | and other issues of C++) rather than of their expressiveness.
| > As a well known Swiss Army instruction goes, when the terrain and the
| > map differ -- trust the terrain. No doubt some programming languages
| > are invented to prove a point, but I've come to realize that the C++
| > templates were designed to solve a problem.
|
| I read that as implicitly claiming that the same would not be true for
| similar features in FPLs or other "academic" languages. That does not
| quite support your previous point about urban legends... ;-)
Well, I certainly cannot stop you from reading the way you want ;-)
What I claim is that, C++ templates were primarily designed to solve a
problem (that of being able to write a paramterized function or class
that, when instantiated, matches the efficiency of un-parameterized one).
They were not designed to prove a point that it is possible to compile
parameterized form separately. If that were the aim, then clearly the
C++ designers knew how to do it.
| > I'm not claiming it is
| > perfect (and I'm hoping for improvements) but theoretical
| > "unstructure" arguments without considering constraints offer little
| > clue.
|
| Oh, I am aware of the constraints. Does not lead me to like the
| outcome, though.
But given the constraints, do you have a better solution?
(Compiling to tuple of functions does not meet the constraints).
We have listed what appear to us to be the most important constraints
here:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
| The problem are these constraints to start with,
| templates just add to the complexity.
It can be argued that templates add complexity, but so does any new
language functionalities or "tweaks and clean-ups" in some sense. So,
the issue must not be just that of adding complexity. Certainly,
cost/benefits is an evaluating criteria.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/31/2005 11:36:02 AM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
>> There is a urban legend that C or C++ designers or
>> implementers obviously don't quite understand functional programming
>> languages and features and implementations. That legend, for large
>> part, is unfounded.
>
> OK, I take your word for it. Certain aspects of C++ - particularly
> with respect to typing - certainly make that hard to believe.
Seconded. Also, for me, having /listened/ to one of the C++ designers
speak publicly and touch upon this subject makes it even harder to
believe.
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
5/31/2005 12:23:26 PM
|
|
Gabriel Dos Reis wrote:
> But given the constraints, do you have a better solution?
> (Compiling to tuple of functions does not meet the constraints).
>
> We have listed what appear to us to be the most important constraints
> here:
>
> http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
Well, if being compatible with C++ is a constraint, then you pretty much
have to live with all the problems that C++ templates carry.
However, I think Andreas is comparing things along a different axis.
It's not "how would a saner/checkable/better C++ template system look
like", it's about the power/expressivity/safety of mechanisms that are
different from C++ templates but offer similar abstraction facilities.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
5/31/2005 12:37:47 PM
|
|
Gabriel Dos Reis wrote:
> Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
>
> | Gabriel Dos Reis wrote:
> | > | If it doesn't say anything about those, why has template
> | > recursion
> | > | been treated differently?
> | > | | By the way, if you say that it isn't "normative", does that mean
> | > that
> | > | a compiler that limits it to, say, 1, would be a conforming C++
> | > | compiler? If not, why not?
> | > A compiler can set the limit to 1, it would be conformant in that
> | > regard. Whether it would be useful is a different question :-)
> |
> | Then the situation is, in fact, worse than I anticipated.
>
> Quite possible. As I have been trying to taint this whole discussion
> with a little of reality, have you found any C++ compiler in
> production use/existence that set that limit to 1? Or is it just pure
> speculation?
The existence of such limits isn't too interesting for hand-written
code, since most of the limitations listed can be overcome by rewriting
the code.
However, the way Annex B does not make promises, and the list of things
that are in it, that's all very bad for generated code. It's easy to
have more than 256 nested parentheses in an expression, or to go beyond
any of the other limits that a C++ compiler may have and be compliant.
I'm quite puzzled why C++ has such a long list of limited resources. In
a modern system, it would be easy to lift all these restrictions (and
replace them with the blanket "limited by available memory" statement).
Templates are different. Template instantiation can recurse, so
termination isn't decidable. For that reason, it makes sense to limit
recursion depth (or instantiation depth).
That recursion was felt to be necessary says something about the limited
expressivity of templates though. If templates-without-recursion were
more expressive, recursion wouldn't have been deemed necessary. (FPLs
have instantiation mechanisms that are powerful enough for practical use
but don't run into that undecidability trap. A typical FPL compiler
indeed has just one limitation: available memory.)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
5/31/2005 12:48:02 PM
|
|
Gabriel Dos Reis wrote:
>
> Clearly, compiling to tuple of functions is already supported by
> C++ in form of virtual functions. Templates, by design, were based on
> the idea that when instantiated they should match the code as if it was
> hand crafted directly. It is hard, near to impossible to match that
> zero-overhead if you comile to a tuple of functions with current
> compiler technology. It is very tempting to hide the inefficency of
> tuple of functions behing the angle-bracket notation, as is done by
> some languages. But, in the case of C++ that is a real concern and a
> direct part of C++ template success. It is not an argument, It is
> report of a fact. See below.
You cannot expect to arrive at a good language when you don't separate
issues of semantics and implementation properly.
The root of many of the problems with C++ obviously is that most of its
design process was driven by that sort of premature optimisation. With
all kinds of hidden assumptions about "current compiler technology".
Regarding the latter, monomorphisation is a well-known optimisation
technique for getting rid of implicit arguments passed to polymorphic
definitions. It is not specifically hard to implement.
> | I even believe that with some tweaks a clean-ups you could
> | apply that technique to something close enough to templates. That you
>
> What specifically are those "twaeks and clean-ups"?
Most prominently, giving proper typing to template parameters, to avoid
any dependency of a templates meaning on the context of instantiation.
And no: "concepts" don't cut it. I always thought they adhere to a scary
notion of "flexibility" instead of imposing some proper structure.
> | cannot do so in C++ is a consequence of the ad-hoc nature of many of
> | its other features that in multiplicity preclude a systematic approach
> | to template compilation other than macro expansion. For starters, its
> | baroque, context-dependent scoping and name resolution rules, on top
> | of highly ambiguous syntax.
>
> Oh, the syntax is not the problem to separate compilation.
It is part of it. If we ignore Perl, then no other modern language has
context-sensitive parsing as bad as C++ has it, and that surely is part
of the reason to require a macro-based approach (and clutches like
"typename").
> The dependent name
> resolution is necessary if one ever wanted to meaningfully abstract
> over anything. You earlier metioned type classes, but that is exactly
> what they do -- the name in those cases designate pointer to member
> fields of tuples. And use of type classes is context dependent too.
Not at all on the same level. One problem in C++ e.g. is resolution of
overloaded operators, which can refer to different definitions (global
or member), depending on what is available. Another one is
disambiguation of declarations and expressions, etc.
In other words, you not only have overloaded /names/ in C++, you have
(heavily) overloaded and hence ambiguous /syntax/ - which is much worse.
> What I claim is that, C++ templates were primarily designed to solve a
> problem (that of being able to write a paramterized function or class
> that, when instantiated, matches the efficiency of un-parameterized one).
> They were not designed to prove a point that it is possible to compile
> parameterized form separately. If that were the aim, then clearly the
> C++ designers knew how to do it.
Didn't you say in your previous post that separate compilation /was/ an aim?
> | Oh, I am aware of the constraints. Does not lead me to like the
> | outcome, though.
>
> But given the constraints, do you have a better solution?
No. But IMO the constraints are not put up wisely.
> (Compiling to tuple of functions does not meet the constraints).
>
> We have listed what appear to us to be the most important constraints
> here:
>
> http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
And I just noted that this document proposes use of tuples of functions
for enabling separate compilation of templates. :-)
My favorite quote from it still is:
| The C++ templates are fundamentally more abstract and flexible than
| type-based approaches (with its inspiration in math rather than in
| type theory).
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
5/31/2005 12:51:49 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Clearly, compiling to tuple of functions is already supported by
> C++ in form of virtual functions.
"Compiling to a tuple of functions" in and of itself is not the goal.
The goal is to type-check and compile separately.
> Templates, by design, were based on
> the idea that when instantiated they should match the code as if it was
> hand crafted directly.
The SML module systems gives you all of theses:
* Functors are always type-checked separately and for functors that
type-check there is a guarantee that any argument that matches
the argument signature will lead to a successful instantiation.
* If desired, functors can be compiled separately (usually using
the tuples of functions approach).
* Functors can be implemented using the "macro-expansion" approach,
yielding code that is as efficient as hard-crafted code.
There exist at least two implementations for either strategy of
implementing functors in SML.
> It is hard, near to impossible to match that
> zero-overhead if you comile to a tuple of functions with current
> compiler technology.
See above. "Tuple of functions" is not the ultimate goal but merely
one technique for compiling separately. Of course, separate
compilation nearly always has a certain overhead since at the time of
compiling the code one does not have all the information that one
would have in the macro-expand case. It is a trade-off, and good
*language* design would give implementers a choice of which technology
they prefer.
> Well, I certainly cannot stop you from reading the way you want ;-)
> What I claim is that, C++ templates were primarily designed to solve a
> problem (that of being able to write a paramterized function or class
> that, when instantiated, matches the efficiency of un-parameterized one).
> They were not designed to prove a point that it is possible to compile
> parameterized form separately. If that were the aim, then clearly the
> C++ designers knew how to do it.
"Clearly?"
> But given the constraints, do you have a better solution?
> (Compiling to tuple of functions does not meet the constraints).
See above.
> We have listed what appear to us to be the most important constraints
> here:
>
> http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
Choice quote from this document:
"The C++ templates are fundamentally more abstract and flexible than
type-based approaches (with its inspiration in math rather than in type
theory)."
Remarkably, the notion of "concepts" that the document talks about at
length is (as far as I could tell) nothing more than what is commonly
known as a "kind". But I know, this is inspired by math, not by type
theory... *g*
Cheers,
Matthias
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
5/31/2005 12:57:02 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
| Gabriel Dos Reis wrote:
| > But given the constraints, do you have a better solution?
| > (Compiling to tuple of functions does not meet the constraints).
| > We have listed what appear to us to be the most important constraints
| > here:
| > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
|
| Well, if being compatible with C++ is a constraint, then you pretty
| much have to live with all the problems that C++ templates carry.
Breaking C++ is not a luxury we have, that is a fundamental constraint.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/31/2005 3:28:30 PM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| Gabriel Dos Reis wrote:
| > Clearly, compiling to tuple of functions is already supported by
| > C++ in form of virtual functions. Templates, by design, were based on
| > the idea that when instantiated they should match the code as if it was
| > hand crafted directly. It is hard, near to impossible to match that
| > zero-overhead if you comile to a tuple of functions with current
| > compiler technology. It is very tempting to hide the inefficiency of
| > tuple of functions behind the angle-bracket notation, as is done by
| > some languages. But, in the case of C++ that is a real concern and a
| > direct part of C++ template success. It is not an argument, It is
| > report of a fact. See below.
|
| You cannot expect to arrive at a good language when you don't separate
| issues of semantics and implementation properly.
That is a matter of opinion instead of fact. Whether a functionality
can be implemented, and be efficiently implemented has always been
part of the constraints -- that is the "designed to solve a problem part".
That is, the purpose was not just to add features, but consider ones
that can be efficiently implemented where C is supposed to run. If
implementations and efficiency were not a concern, C++ designers knew
how to do far better.
| The root of many of the problems with C++ obviously is that most of
| its design process was driven by that sort of premature
| optimisation.
Implementation constraint is not premature optimization.
| With all kinds of hidden assumptions about "current
| compiler technology".
Where is the hidden assumption about compiler technology. Again, this
is not argumentative. Each time we have a new functionality, one has
to explain how it can be implemented and people have to form idea
about its efficiency. That is no hidden assumption, that is no
premature optimization.
| Regarding the latter, monomorphisation is a well-known optimisation
| technique for getting rid of implicit arguments passed to polymorphic
| definitions. It is not specifically hard to implement.
Consider that C++ has a notion of separate compilation (largely
inherited from C) and has to work with most traditional linkers; how
do you concretely make that well-known optimization avaliable
everywhere C++ runs? The issues are not that simple, unless you
haven't tackle them for real.
| > | I even believe that with some tweaks a clean-ups you could
| > | apply that technique to something close enough to templates. That you
| > What specifically are those "tweaks and clean-ups"?
|
| Most prominently, giving proper typing to template parameters, to
| avoid any dependency of a templates meaning on the context of
| instantiation.
That is still handwaving. Exactly what do you call "proper typing"?
It is crucial to nail that down, especially when you claim that
"concept" doesn't cut it.
| And no: "concepts" don't cut it. I always thought they
| adhere to a scary notion of "flexibility" instead of imposing some
| proper structure.
Is that thought based on actual discussion with C++ designers, or
based on a perception of what it might mean, given the premise that
they don't quite quite understand language design?
| > | cannot do so in C++ is a consequence of the ad-hoc nature of many of
| > | its other features that in multiplicity preclude a systematic approach
| > | to template compilation other than macro expansion. For starters, its
| > | baroque, context-dependent scoping and name resolution rules, on top
| > | of highly ambiguous syntax.
| > Oh, the syntax is not the problem to separate compilation.
|
| It is part of it.
No, the template syntax is not part of the problem one encounters when
one tries to separately compile templates. C++ compilers have been
offering pure parsing long before they try to separately
compile templates.
| If we ignore Perl, then no other modern language has
| context-sensitive parsing as bad as C++ has it, and that surely is
| part of the reason to require a macro-based approach (and clutches
| like "typename").
Funny you mentioned that one. In previous mails, I wasn't quite sure
whether you were talking about the "typename" or ".template" curious
notation. The reason for the existence of that notation is a
manifestation of a curiosity inherited from C. Forget about template,
forget about C++ for a moment. Consider just the following plain C
f(a);
what is the meaning of the above. Before saying, it obviously is a
function call, consider whether it might also mean a variable
declaration. Either way, it depends on whether f has been declared to
name a type or not. Consider also
x * y;
what is its meaning? Before saying it obviously is a multiplication,
consider whether it could mean a variable declaration too. Either way,
it depends on whether x has been declared to name a type of not. The
context-sensitive parsing is not something template invented; it has
been there, in the base language.
Now, when you come to parsing templates -- independently of whether
separate compilation of templates is supported or, I'm just talking
about *parsing* -- there ought to be a way to resolve those
ambiguities (that exist independently of templates) if one is going to
abstract meaningfully over anything.
One can change the template syntax (and indeed, we've done that here
at TAMU, internally for the purpose of reasoning about C++) to make
the parsing "easier". That change does not affect the whole issue.
The basic issue is how does one separately check template uses (without
having the body), separately check template definitions (without having
the uses) and make sure that everything link together keeping in mind
the fourteen constraints we listed.
| > The dependent name
| > resolution is necessary if one ever wanted to meaningfully abstract
| > over anything. You earlier mentioned type classes, but that is exactly
| > what they do -- the name in those cases designate pointer to member
| > fields of tuples. And use of type classes is context dependent too.
|
| Not at all on the same level. One problem in C++ e.g. is resolution of
| overloaded operators, which can refer to different definitions (global
| or member), depending on what is available.
Yes, but you get the same with type classes. There is no free lunch.
If one wants to overload something, there out to be use of "evidence"
for proper resolution. Exactly which function is choosed follows
well-defined rules; it is not that those resolutions happen randomly.
If you're thinking of a specific case, please spell it out and don't be
afraid of loading me with details.
| Another one is
| disambiguation of declarations and expressions, etc.
As I explained above, that core disambiguation has nothing to do with
templates; that notion was inherited largely from C. For further
historical accounts, see D&E (or a recent posting on
comp.compilers).
| In other words, you not only have overloaded /names/ in C++, you have
| (heavily) overloaded and hence ambiguous /syntax/ - which is much
| worse.
But none of those are the consequences of template syntax.
Overloading for C++ was invented more than two decades ago, ambiguity
was inherited from C (the latter could have been abandoned but it was
contrary to the C++ design rules and constraints). Compilers, without
separately compiling templates, can do the disambiguation.
Since the core issue is that of separately compiling templates, it
would be nice if you forgot about the syntax for a moment (it is a
solved problem) and concentrate on the main issue :-)
| > What I claim is that, C++ templates were primarily designed to solve a
| > problem (that of being able to write a parameterized function or class
| > that, when instantiated, matches the efficiency of un-parameterized one).
| > They were not designed to prove a point that it is possible to compile
| > parameterized form separately. If that were the aim, then clearly the
| > C++ designers knew how to do it.
|
| Didn't you say in your previous post that separate compilation /was/ an aim?
I did say:
Since day one of C++ template design, separate compilation of templates
has always been there.
and I maintain it. Do you see a contradiction?
| > | Oh, I am aware of the constraints. Does not lead me to like the
| > | outcome, though.
| > But given the constraints, do you have a better solution?
|
| No.
:-(
| But IMO the constraints are not put up wisely.
Ah.
|
| > (Compiling to tuple of functions does not meet the constraints).
| > We have listed what appear to us to be the most important constraints
| > here:
| > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
|
| And I just noted that this document proposes use of tuples of
| functions for enabling separate compilation of templates. :-)
Maybe you did not read it correctly :-) Let me complete it with this
(from the document):
The constraints/concept facility must sustain and enhance the
compile-time evaluation and inlining that are the foundations of the
performance of classical template code.
That gives you the set of constraints we have.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/31/2005 4:40:27 PM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Clearly, compiling to tuple of functions is already supported by
| > C++ in form of virtual functions.
|
| "Compiling to a tuple of functions" in and of itself is not the goal.
| The goal is to type-check and compile separately.
Agreed.
| > Templates, by design, were based on
| > the idea that when instantiated they should match the code as if it was
| > hand crafted directly.
|
| The SML module systems gives you all of theses:
|
| * Functors are always type-checked separately and for functors that
| type-check there is a guarantee that any argument that matches
| the argument signature will lead to a successful instantiation.
| * If desired, functors can be compiled separately (usually using
| the tuples of functions approach).
| * Functors can be implemented using the "macro-expansion" approach,
| yielding code that is as efficient as hard-crafted code.
|
| There exist at least two implementations for either strategy of
| implementing functors in SML.
However, SML has a simpler type and expression system -- trying to
express everything in form of types, as done in (S)ML, severly limit
what can be expressed (talking only about the common cases) in C++.
In fact, that approach has been proposed several times long before I
got interest in the issue.
When I started my work in separate compilation of templates,
naturally I looked around trying to have an idea of the state of the
art. I actually, for a moment, opted to take the SML road. Untill I
discovered that it does not work for C++ -- at least if one works in
the fourteen constraints I aluded to earlier.
Then, very recently (in 2002), I went to see Xavier Leroy and had
fruitful discussions with him. One conclusion I came to after that
visit was that SML and OCaml take a nearly opposite direction to that
of C++ in this parameterization business. I would, however, refrain
from characterizing one as bad and the other as good. Most certainly
I have issues with both directions.
There is no way (at least I can't see any) at this point to reuse
their technologies without actually severely depart from the working
constraints.
In our several papers on the issue, we explained how just listing
entities by their types does not work for C++.
[...]
| > We have listed what appear to us to be the most important constraints
| > here:
| >
| > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
|
| Choice quote from this document:
|
| "The C++ templates are fundamentally more abstract and flexible than
| type-based approaches (with its inspiration in math rather than in type
| theory)."
|
| Remarkably, the notion of "concepts" that the document talks about at
| length is (as far as I could tell) nothing more than what is commonly
| known as a "kind". But I know, this is inspired by math, not by type
| theory... *g*
It is very tempting, without actually digging deep into the details of
templates, to think that the concept stuff is just "kind" known for a
century now.
And some people have suggested that before, so I'm not surprised by
your sarcasm :-).
But, in fact it is not.
Also, notice the distinction between C++ template, and the search for
a type system that accounts for the relations that template arguments
must satisfy.
The fundamental reason is that concepts are not constraints on list of
types. Template definitions define relations between their (explicit)
parameters (which can be types as well as ordinary values) and a set
of implicit parameters (those that are referred to as "dependent
names"). Concepts are expression of those relations -- which are
checked by the compiler at instantiation time. To date, I have not
seen anything in type theory that accounts for that, not even in the
most advanced dependent-type theories.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/31/2005 5:10:50 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
| Gabriel Dos Reis wrote:
|
| > Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| > | Gabriel Dos Reis wrote:
| > | > | If it doesn't say anything about those, why has template
| > | > recursion
| > | > | been treated differently?
| > | > | | By the way, if you say that it isn't "normative", does that mean
| > | > that
| > | > | a compiler that limits it to, say, 1, would be a conforming C++
| > | > | compiler? If not, why not?
| > | > A compiler can set the limit to 1, it would be conformant in that
| > | > regard. Whether it would be useful is a different question :-)
| > | | Then the situation is, in fact, worse than I anticipated.
| > Quite possible. As I have been trying to taint this whole discussion
| > with a little of reality, have you found any C++ compiler in
| > production use/existence that set that limit to 1? Or is it just pure
| > speculation?
|
| The existence of such limits isn't too interesting for hand-written
| code, since most of the limitations listed can be overcome by
| rewriting the code.
Well, you'll be amazed at knowing that lot of C++ programs
running out there are program generated, and I know of no report
that any of them got into this because of the informative note annex
B. Probably, a fact is that C++ compilers have to accomodate with
with real world and in reald world none of them have set the limit to
1 or 17 without allowing its user to raise it. If you have found any,
I would be interested (as future reference).
Maybe this whole issue is more a matter of abstract perception than
that of concrete ones.
| However, the way Annex B does not make promises, and the list of
| things that are in it, that's all very bad for generated code. It's
| easy to have more than 256 nested parentheses in an expression, or to
| go beyond any of the other limits that a C++ compiler may have and be
| compliant.
I hope you realized that 256 is not a normative limit, and Annex B
started with reminding that implementations must document their limits
(that requirement is already formulated in the normative part �1.9)
1.9 Program execution
1 The semantic descriptions in this International Standard define a
parameterized nondeterministic abstract machine. This
International Standard places no requirement on the structure of
conforming implementations. In particular, they need not copy or
emulate the structure of the abstract machine. Rather,
conforming implementations are required to emulate (only) the
observable behavior of the abstract machine as explained below.
2 Certain aspects and operations of the abstract machine are
described in this International Standard as implementation-defined
(for example, sizeof(int)). These constitute the parameters of the
abstract machine. Each implementation shall include documentation
describing its characteristics and behavior in these
respects. Such documentation shall define the instance of the
abstract machine that corresponds to that implementation (referred
to as the corresponding instance below).
| I'm quite puzzled why C++ has such a long list of limited
| resources.
Maybe it is because you haven't seen that of C :-). See below.
(I hope they are not problem for functional programming language
implementations that generate C codes ;-))
| In a modern system, it would be easy to lift all these
| restrictions (and replace them with the blanket "limited by available
| memory" statement).
one could, but the question: isn't that blanket statement already
part of the normative part? Seurely it is. The other thing is you
seem to believe that C++ must run only on "a modern system", something
that needs to be clarified. People involved in C++ standardization
felt that C++ should be able to run also on not so "modern systems".
I think we all agree that, if one sufficiently narrows its scope, one
could achieve nifty things. C++ has been trying not to narrow to much
its scope.
| Templates are different. Template instantiation can recurse, so
| termination isn't decidable. For that reason, it makes sense to limit
| recursion depth (or instantiation depth).
You could safely remove that number 17 from Annex B, it won't change
anything to the situation, because (C++ standard, �1.4/2)
-- If a program contains no violations of the rules in this
International Standard, a conforming implementation shall,
within its resource limits, accept and correctly execute that
program.
-- Gaby
From the C99 standard:
5.2.4.1 Translation limits
[#1] The implementation shall be able to translate and
execute at least one program that contains at least one
instance of every one of the following limits:13)
-- 127 nesting levels of blocks
-- 63 nesting levels of conditional inclusion
-- 12 pointer, array, and function declarators (in any
combinations) modifying an arithmetic, structure,
union, or incomplete type in a declaration
-- 63 nesting levels of parenthesized declarators within a
full declarator
-- 63 nesting levels of parenthesized expressions within a
full expression
-- 63 significant initial characters in an internal
identifier or a macro name (each universal character
name or extended source character is considered a
single character)
-- 31 significant initial characters in an external
identifier (each universal character name specifying a
short identifier of 0000FFFF or less is considered 6
characters, each universal character name specifying a
short identifier of 00010000 or more is considered 10
characters, and each extended source character is
considered the same number of characters as the
corresponding universal character name, if any)14)
-- 4095 external identifiers in one translation unit
-- 511 identifiers with block scope declared in one block
____________________
13)Implementations should avoid imposing fixed translation
limits whenever possible.
14)See ``future language directions'' (6.11.3).
-- 4095 macro identifiers simultaneously defined in one
preprocessing translation unit
-- 127 parameters in one function definition
-- 127 arguments in one function call
-- 127 parameters in one macro definition
-- 127 arguments in one macro invocation
-- 4095 characters in a logical source line
-- 4095 characters in a character string literal or wide
string literal (after concatenation)
-- 65535 bytes in an object (in a hosted environment only)
-- 15 nesting levels for #included files
-- 1023 case labels for a switch statement (excluding
those for any nested switch statements)
-- 1023 members in a single structure or union
-- 1023 enumeration constants in a single enumeration
-- 63 levels of nested structure or union definitions in a
single struct-declaration-list
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
5/31/2005 5:39:58 PM
|
|
Gabriel Dos Reis wrote:
>
> Implementation constraint is not premature optimization.
Constraints is not, but starting the whole design from the
implementation end is (which was the route for many things in C++, at
least that was my perception from lots of the discussion in D&E - YMMV).
> | With all kinds of hidden assumptions about "current
> | compiler technology".
>
> Where is the hidden assumption about compiler technology. Again, this
> is not argumentative.
There have been various occasions where the design of C++ was vastly
over-optimistic (e.g. separate compilation for templates) or
over-pessimistic (extreme emphasis on low-level features) with respect
to compilation technology.
> | Regarding the latter, monomorphisation is a well-known optimisation
> | technique for getting rid of implicit arguments passed to polymorphic
> | definitions. It is not specifically hard to implement.
>
> Consider that C++ has a notion of separate compilation (largely
> inherited from C) and has to work with most traditional linkers; how
> do you concretely make that well-known optimization avaliable
> everywhere C++ runs? The issues are not that simple, unless you
> haven't tackle them for real.
I don't deny at all that it's hard or impossible to achieve for C++.
> | > | I even believe that with some tweaks a clean-ups you could
> | > | apply that technique to something close enough to templates. That you
> | > What specifically are those "tweaks and clean-ups"?
> |
> | Most prominently, giving proper typing to template parameters, to
> | avoid any dependency of a templates meaning on the context of
> | instantiation.
>
> That is still handwaving. Exactly what do you call "proper typing"?
What you find in ML functors, for example. I know that this does not
apply to C++ as is, but that is not my point.
To answer most of your post, my point rather is that it is not
productive to try to pursue all these ideas in context of a language
that is so fundamentally at odds with it - one shouldn't build
skyscrapers on swampy ground. On the long run, a clean cut serves much
better. In the case of C++, that cut should have been done 20 years ago,
when the scalability problems of C became obvious enough. Instead, even
more and nastier problems were happily introduced.
> | And no: "concepts" don't cut it. I always thought they
> | adhere to a scary notion of "flexibility" instead of imposing some
> | proper structure.
>
> Is that thought based on actual discussion with C++ designers, or
> based on a perception of what it might mean, given the premise that
> they don't quite quite understand language design?
That's my personal opinion, based on experience with C++ as well as
languages that lack some of its alleged bits of extra flexibility, but
still provide more satisfactory overall support for genericity.
> | If we ignore Perl, then no other modern language has
> | context-sensitive parsing as bad as C++ has it, and that surely is
> | part of the reason to require a macro-based approach (and clutches
> | like "typename").
>
> Funny you mentioned that one. In previous mails, I wasn't quite sure
> whether you were talking about the "typename" or ".template" curious
> notation. The reason for the existence of that notation is a
> manifestation of a curiosity inherited from C.
Yes, I'm fully aware of that and the examples you give. I said it is the
ad-hoc nature of many other features that cause templates to be so
hairy, and I enumerated that one as an example.
> | > The dependent name
> | > resolution is necessary if one ever wanted to meaningfully abstract
> | > over anything. You earlier mentioned type classes, but that is exactly
> | > what they do -- the name in those cases designate pointer to member
> | > fields of tuples. And use of type classes is context dependent too.
> |
> | Not at all on the same level. One problem in C++ e.g. is resolution of
> | overloaded operators, which can refer to different definitions (global
> | or member), depending on what is available.
>
> Yes, but you get the same with type classes.
No, that's not correct. With type classes, an identifier uniquely refers
to either an ordinary value or a class method, there can only ever be
one in scope. (A class can be instantiated by different implementations,
but that is completely orthogonal to scoping.)
> If one wants to overload something, there out to be use of "evidence"
> for proper resolution. Exactly which function is choosed follows
> well-defined rules; it is not that those resolutions happen randomly.
> If you're thinking of a specific case, please spell it out and don't be
> afraid of loading me with details.
I was referring to C::operator+(D) vs operator+(C,D), which is a
completely ad-hoc form of syntactic overloading. Similarly, unrelated
definitions can apply for a conversion, you can overload functions with
templates, etc. Surely you know the hot spots better than me. It's no
suprise at all that no type theory one is willing to deal with will be
able to handle such arbitrariness.
> Since the core issue is that of separately compiling templates, it
> would be nice if you forgot about the syntax for a moment (it is a
> solved problem) and concentrate on the main issue :-)
But the syntactic overloading is what makes the obvious
"tuples-of-functions" approach to separate compilation impossible (or at
least very hard).
> | > What I claim is that, C++ templates were primarily designed to solve a
> | > problem (that of being able to write a parameterized function or class
> | > that, when instantiated, matches the efficiency of un-parameterized one).
> | > They were not designed to prove a point that it is possible to compile
> | > parameterized form separately. If that were the aim, then clearly the
> | > C++ designers knew how to do it.
> |
> | Didn't you say in your previous post that separate compilation /was/ an aim?
>
> I did say:
>
> Since day one of C++ template design, separate compilation of templates
> has always been there.
>
> and I maintain it. Do you see a contradiction?
At least I must apply a very twisted interpretation of your two
statements to not see one. ;-)
> | But IMO the constraints are not put up wisely.
>
> Ah.
Which means, to repeat the above picture, to rather start from scratch
than bother with adding 120 more storeys and balconies to an already
shaky piece of architecture under the constraint of not moving or fixing
a single leaking pipe. :-)
- Andreas
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
5/31/2005 6:16:09 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Joachim Durchholz <jo@durchholz.org> writes:
>
> | Gabriel Dos Reis wrote:
> | > But given the constraints, do you have a better solution?
> | > (Compiling to tuple of functions does not meet the constraints).
> | > We have listed what appear to us to be the most important constraints
> | > here:
> | > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
> |
> | Well, if being compatible with C++ is a constraint, then you pretty
> | much have to live with all the problems that C++ templates carry.
>
> Breaking C++ is not a luxury we have, that is a fundamental constraint.
Which means, we are basically screwed...
One day mankind (or at least the computer-literate part thereof) will
look back and shake its collective head at how much intellectual
resources were wasted on that horrible mistake called C++.
Cheers,
Matthias
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/1/2005 12:34:28 AM
|
|
Gabriel Dos Reis wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
> | Gabriel Dos Reis wrote:
> | > But given the constraints, do you have a better solution?
> | > (Compiling to tuple of functions does not meet the constraints).
> | > We have listed what appear to us to be the most important constraints
> | > here:
> | > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
> |
> | Well, if being compatible with C++ is a constraint, then you pretty
> | much have to live with all the problems that C++ templates carry.
>
> Breaking C++ is not a luxury we have, that is a fundamental constraint.
Well, let me utter a sacrilege... C++ is the PL/I of modern days. It's
trying to be everything to everyone, and adding too many ways to do the
same thing, failing to provide some key mechanisms that could replace
the existing ones (not that this failure is a fault of its designers:
they had to work with the insights that were available at the time of
design); with a baroque syntax and semantics that (almost) nobody
completely understands. Expressiveness taken too far, with guarantees
not keeping pace.
Algol was a grandiose improvement over PL/I. I expect some FPL to be a
grandiose improvement over C++ - not because it can do everything that
C++ can (that would end up with an even more baroque language), but
because it offers similar expressivity with a vastly reduced set of
primitive operations. SML structures and Haskell typeclasses are
proofs-of-concept for constructs that compare favorably with C++
templates: not Turing-complete (hence not as powerful in theory), but
powerful enough to anything that somebody would want to express within
the framework of a type system; with a semantics that's above the
(roughly) macro-substitution semantics of templates, hence better
amenable to giving guarantees both to compiler (for optimisation) and
human (for maintaining the code).
Just personal opinion. May be outdated tomorrow ;-)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/1/2005 12:55:19 PM
|
|
Joachim Durchholz wrote:
>
> Well, let me utter a sacrilege... C++ is the PL/I of modern days. It's
> trying to be everything to everyone, and adding too many ways to do the
> same thing, failing to provide some key mechanisms that could replace
> the existing ones (not that this failure is a fault of its designers:
> they had to work with the insights that were available at the time of
> design);
More than once they chose to ignore insights that were well established
for decades. To give just one example: Stroustrup consciously decided
against everybody's advice for designing a context-free syntax and
implementing the cfront parser using technology like Yacc. I dare say
that the result is catastrophic.
> Algol was a grandiose improvement over PL/I.
Um, Algol predates PL/I by almost a decade.
> SML structures and Haskell typeclasses are
> proofs-of-concept for constructs that compare favorably with C++
> templates: not Turing-complete (hence not as powerful in theory)
There are extensions to ML modules as well as to type classes that make
type checking undecidable. But at least it is clear where the boundaries
lie. Certain generalisations of type classes even turn it into a Turing
complete logic programming language.
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
6/1/2005 1:23:33 PM
|
|
Gabriel Dos Reis wrote:
> Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
>
> | You cannot expect to arrive at a good language when you don't separate
> | issues of semantics and implementation properly.
>
> That is a matter of opinion instead of fact.
No, it's hard fact.
I have programmed both in Eiffel and C++. Both languages are good
representatives for the static-typing OO view of the programming world.
Eiffel was designed for clarity of concepts, C++ was designed for
efficient compilation. This shows in many ways:
* The default for Eiffel member functions is that they are virtual.
Nonvirtual functions are a very rare exception. The additional dynamic
dispatch isn't a real issue, 90% of dispatching calls can be made static
- it's more difficult under separate compilation, and would probably
require some kind of smart linking (in a separate step before linking
with modules written in other languages), but it's all not quite rocket
science, and can be made as efficient as one would care.
* You can make virtual calls from within constructors. Actually
constructor functions are completely normal functions, except that they
can be called when an object is constructed initially. No fiddling with
automatic initialisation. This is *far* simpler than the set of rules
used in C++.
* Eiffel requires garbage collection. Now that makes Eiffel unsuitable
for HRT, but it makes it far more reliable - if a constructor throws an
exception, created objects are orphaned and will be reclaimed. In other
words, I don't have to worry about memory leaks - that's a *huge*
simplification for programmers. Besides, I wouldn't want to use C++ for
HRT either - and, no, "smart pointers" aren't a smart solution here,
deallocating an object may trigger a chain of deallocations and makes
deallocation less predictable (and queuing up the deallocations just
means that memory isn't freed at the time it becomes available, so we're
halfways back to the timing performance of traditional automatic GC, but
with a horribly slow interface that requires permanent updates in
reference counts). If I were to do HRT programming, I'd not use dynamic
memory allocation anyway - so neither C++ nor Eiffel fit the bill :-)
From my experience, I can't say that the Eiffel software that I worked
with "felt" noticeably slower than its C++ equivalent.
However, what took me weeks in Eiffel has taken me months in C++, and
the main culprits for that are the points above: I spent hours chasing
bugs with functions that should have been virtual (or nonvirtual), I
spent days chasing constructor bugs (whoever said that virtual calls
from a constructor should go to the function that's used in the place
where the constructor was written should be flogged with an iron whip -
now I have static, virtual, and half-virtual functions to deal with), I
spent weeks chasing dangling-pointer bugs.
In other words: Eiffel is *far* more efficient in programmer time (I can
even consider algorithmic improvements while my poor fellow C++
programmers are still chasing pointer bugs), and while it's admittedly
slower than C++, that's less a question of language design and more one
of man-centuries spent in writing optimising compilers. (The Eiffel
compilers that I worked with had no more than a few man-decades in them,
and not many of these. If C++ had that little effort in it, it would be
quite a lot slower. Actually early C++ compilers weren't very impressive...)
(For the record: in my eyes, improving C++ is a misguided attempt at
improving something that should better be left to rot. I know that this
is not feasible, simply because too much C++ software already has been
written, and easing the job of the maintainers is worth the effort...
but I don't think that adding new mechanisms to C++ templates is the way
to go. C++ already has a history of compilers that barely manage to
implement the language properly, of programmers not quite understanding
all those complex and wonderful mechanisms (many don't grok STL, which
is supposedly standard...) - adding yet another complex mechanism isn't
going to improve on these points.)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/1/2005 1:24:21 PM
|
|
Gabriel Dos Reis wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
> | However, the way Annex B does not make promises, and the list of
> | things that are in it, that's all very bad for generated code. It's
> | easy to have more than 256 nested parentheses in an expression, or to
> | go beyond any of the other limits that a C++ compiler may have and be
> | compliant.
>
> I hope you realized that 256 is not a normative limit,
Sure.
I'm also well aware that that 256 number listed is just an example of
such a limit - it could be 100, 20, 20,000, or "bounded only by memory".
> and Annex B
> started with reminding that implementations must document their limits
> (that requirement is already formulated in the normative part �1.9)
I don't object to the precision of Annex B - sometimes it's helpful to
specifically state what things are explicitly *not* guaranteed.
However, I would have found it far better if the language had specified
that no such limits are allowed (except for the obvious "limited by
available memory"). Right now, anybody who generates C++ programs will
have to consider all these limitations, and provide workarounds for them
- this *vastly* complicates code generation if done properly (so most
code-generating programs probably punt on the issue and rely on the C++
compiler to properly report if the table overflows).
> | I'm quite puzzled why C++ has such a long list of limited
> | resources.
>
> Maybe it is because you haven't seen that of C :-). See below.
> (I hope they are not problem for functional programming language
> implementations that generate C codes ;-))
Contrary to popular belief, C is not a good portable assembler. The
standard strategy for compiling FPLs nowadays seems to be machine code
generation.
> | In a modern system, it would be easy to lift all these
> | restrictions (and replace them with the blanket "limited by available
> | memory" statement).
>
> one could, but the question: isn't that blanket statement already
> part of the normative part? Seurely it is. The other thing is you
> seem to believe that C++ must run only on "a modern system", something
> that needs to be clarified. People involved in C++ standardization
> felt that C++ should be able to run also on not so "modern systems".
> I think we all agree that, if one sufficiently narrows its scope, one
> could achieve nifty things. C++ has been trying not to narrow to much
> its scope.
Hold it. I'd say that at C++ *compiler* can be expected to run on a
reasonably modern system. (Besides, I don't know of a C++ compiler that
doesn't require several dozen megabytes, so that's reality already.)
The compiled code could run on anything, from mainframe with gigabytes
of RAM to embedded processors. Actually compiling to a smaller machine
requires a smarter compiler, so I'd expect the performance of the
developer machine to go up if the target system resources go down.
Besides, compiling with no arbitrary limits should be standard software
technology today. I find it telling that C++ isn't advanced enough to
make getting rid of these a non-problem.
If I may contrast this with my Eiffel experience: the compiler indeed
had limits, but these were imposed by the run-time system, not by the
parser. I simply don't understand how anybody can write a parser that
will accept only a limited nesting depth, for example - don't they read
the Dragon Book anymore?
Well, whenever the topic of C++ parsing comes up, I learn something new
and disgusting about the language or its compilers.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/1/2005 1:43:42 PM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| Joachim Durchholz wrote:
| > Well, let me utter a sacrilege... C++ is the PL/I of modern
| > days. It's trying to be everything to everyone, and adding too many
| > ways to do the same thing, failing to provide some key mechanisms
| > that could replace the existing ones (not that this failure is a
| > fault of its designers: they had to work with the insights that were
| > available at the time of design);
|
| More than once they chose to ignore insights that were well
| established for decades. To give just one example: Stroustrup
| consciously decided against everybody's advice for designing a
| context-free syntax and implementing the cfront parser using
| technology like Yacc. I dare say that the result is catastrophic.
I'm having hard time figuring out whether your statement has any
factual basis. Please, don't be afraid to share your source/reference.
As before, I will try to inject, once again, a bit of facts in this
discussion. D&E, page 68-69
�3.3.2 Parsing C++
In 1982 when I first planned Cfront, I wanted to use a recursive
descent parser because I had experience writing and maintaining such
a beast, because I liked such parsers' ability to produce good
error messages, and because I liked the idea of having the full
power of a general purpose programming language available when
decisions had to be made in the parser. However, being a
conscientious young computer scientist I asked the experts. Al Aho
and Steve Johnson were in the Computer Science Research Center and
they, primarily Steve, convinced me that writing a parser by hand
was most old-fashioned, would be an inefficient use of my time,
would almost certainly result in a hard-to-understand and
hard-to maintain parser, and would be prone to unsystematic and
therefore unreliable error recovery. The right way was to use an
LALR(1) parser generator, so I used Al and Steve's YACC [Aho, 1986].
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/1/2005 6:08:37 PM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Joachim Durchholz <jo@durchholz.org> writes:
| >
| > | Gabriel Dos Reis wrote:
| > | > But given the constraints, do you have a better solution?
| > | > (Compiling to tuple of functions does not meet the constraints).
| > | > We have listed what appear to us to be the most important constraints
| > | > here:
| > | > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
| > |
| > | Well, if being compatible with C++ is a constraint, then you pretty
| > | much have to live with all the problems that C++ templates carry.
| >
| > Breaking C++ is not a luxury we have, that is a fundamental constraint.
|
| Which means, we are basically screwed...
Only if you decide that you;re defeated the you're screwed :-).
Personally, I think there are lot of things that can be improved and
we have done some of them. The only scare resource is time -- however,
it looks like myths and misconceptions about the facts are also time
sucker.
| One day mankind (or at least the computer-literate part thereof) will
| look back and shake its collective head at how much intellectual
| resources were wasted on that horrible mistake called C++.
I guess that would depend on how would they measure "waste" and "mistake".
(in this discussion, I've wated more intellectual resources trying to
inject facts in here than I've done working with C++ design and
implementations)
The functional programminng community has "owned" institutions for
over three decades now, yet...
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/1/2005 6:15:23 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
| Gabriel Dos Reis wrote:
|
| > Joachim Durchholz <jo@durchholz.org> writes:
| > | Gabriel Dos Reis wrote:
| > | > But given the constraints, do you have a better solution?
| > | > (Compiling to tuple of functions does not meet the constraints).
| > | > We have listed what appear to us to be the most important constraints
| > | > here:
| > | > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
| > | | Well, if being compatible with C++ is a constraint, then you
| > pretty
| > | much have to live with all the problems that C++ templates carry.
| > Breaking C++ is not a luxury we have, that is a fundamental
| > constraint.
|
| Well, let me utter a sacrilege... C++ is the PL/I of modern days. It's
| trying to be everything to everyone, and adding too many ways to do
Having been involved in C++ design and implementation discussions for
some time now, what I've figured out is that for many people it is
not doing enough. For the next version of C++, the C++ standard
Evolution Working Group had asked for "wishlist" for improvements from
the community. The list we got is quite long and looking over it, it
appears that clearly C++ was not providing enough for some people.
But I've also heard your rant some times. The reality is that, unless
you've been close enough (either as implementors leasting to users) or
designers (listening to users) trying to improve over things, it is
hard to assess the complexity and the tension between the variety of
interests. Furthermore, if the primary design aim has been to design a
beautiful language, I'm confident that C++ designers would have done a
better job.
| the same thing, failing to provide some key mechanisms that could
| replace the existing ones (not that this failure is a fault of its
| designers: they had to work with the insights that were available at
| the time of design); with a baroque syntax and semantics that (almost)
There is an account of C++ design history that I think anybody who
wants to make serious criticisms about quirks in C++ should read. In
particular, it has many discussions about the syntax issues in several
paragraphs (apart from the main section �2.8 Syntax Problems).
�2.8 Syntax Problems
Could I have "fixed" the most annoying deficiencies of the C syntax
and semantics at some point before C++ was made generally available?
Could I have done so without removing useful features (to C with
Classes' users in their environments -- as opposed to an ideal
world) or introducing incompatibilities that were unacceptable to C
programmers wanting to migrate to C with Classes? I think not. In
some cases, I tried, but I backed out my changes after receiving
complaints from outraged users.
[...]
The negative reaction to changes in this area from users was very
strong. they considered the "terseness" allowed by C essential to
the point of refusing to use a "fascist" language that required them
to write redundant type specifiers. I backed out the change. I
don't think I had a choice. Allowing that implicit int is the
source of many of the annoying problems with the C++ grammar today.
Note that the pressure came from users, not management or arm-chair
language experts. [...]
My eventual rationale for leaving things as they were was that any new
syntax would (temporarily at least) add complexity to a known mess.
Also, even though the old style is a boon to teachers of trivia and
to people who want to ridicule C, it is not a significant problem
for C programmers. In this case, I'm not sure if I did the right
thing, though. The agony to me and other C++ implementers,
documenters, and tool builders caused by the perversities of syntax
has been significant. Users can -- and do -- of course insulate
themselves from such problems by writing in a small easily understood
subset of the C/C++ declaration syntax (�7.2).
�2.8.3 The Importance of Syntax
[...]
A subtle aspect of C compatibility discussions is that old-time C
programmers are comfortable with the old ways of doing thing and can
therefore be quite intolerant of the incompatibilities needed to
support styles of programming that C wasn't designed for.
Conversely, non-C programmers usually underestimate the value C
programmers attribute to the C syntax.
| nobody completely understands. Expressiveness taken too far, with
| guarantees not keeping pace.
| Algol was a grandiose improvement over PL/I.
A time-travel problem?
| I expect some FPL to be a grandiose improvement over C++ -
I hope so too. The functional programming community has owned
institutions and spent wonderful resources there for over three
decades. It would be a terrible and unqualifiable waste if they could
not have a grandiose improvement of C++.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/1/2005 6:49:45 PM
|
|
Joachim Durchholz wrote:
> Gabriel Dos Reis wrote:
>
>> Breaking C++ is not a luxury we have, that is a fundamental constraint.
>
> Well, let me utter a sacrilege... C++ is the PL/I of modern days. It's
> trying to be everything to everyone, and adding too many ways to do the
> same thing, failing to provide some key mechanisms that could replace
> the existing ones (not that this failure is a fault of its designers:
> they had to work with the insights that were available at the time of
> design); with a baroque syntax and semantics that (almost) nobody
> completely understands.
Almost?
Andreas Rossberg wrote:
> Joachim Durchholz wrote:
> > Algol was a grandiose improvement over PL/I.
>
> Um, Algol predates PL/I by almost a decade.
Hence Tony Hoares's comment on Algol 60:
Here is a language so far ahead of its time, that it was not only an
improvement on its predecessors, but also on nearly all its successors.
[The quote is from 'Hints on Programming Language Design',
<http://www.iam.unibe.ch/~scg/Teaching/PS/PS-S05/Serie-1/Hoare_Hints.pdf>
Written in December 1973, but most of it could have been written
yesterday. Another wonderful and relevant quote:
I fear that most designers of extensible languages have spurned the
technical simplifications which make them feasible.
]
--
David Hopwood <david.nospam.hopwood@blueyonder.co.uk>
|
|
0
|
|
|
|
Reply
|
david.nospam.hopwood (121)
|
6/1/2005 9:29:50 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> |
> | > Joachim Durchholz <jo@durchholz.org> writes:
> | >
> | > | Gabriel Dos Reis wrote:
> | > | > But given the constraints, do you have a better solution?
> | > | > (Compiling to tuple of functions does not meet the constraints).
> | > | > We have listed what appear to us to be the most important constraints
> | > | > here:
> | > | > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
> | > |
> | > | Well, if being compatible with C++ is a constraint, then you pretty
> | > | much have to live with all the problems that C++ templates carry.
> | >
> | > Breaking C++ is not a luxury we have, that is a fundamental constraint.
> |
> | Which means, we are basically screwed...
>
> Only if you decide that you;re defeated the you're screwed :-).
Well, I am not defeated, but "not breaking C++" is not a constraint
that I live by. (Actually, C++ was already broken from the start.
Every couple of years I look at it again, and it has grown more hair,
has acquired more stuff designed to patch up or hide the sins of its
past.)
> Personally, I think there are lot of things that can be improved and
> we have done some of them.
Some things are just not worth repairing. The basic problem is that
you are not willing to "break C++" (see above). This precludes any
improvement. It is like giving the cancer patient a new haircut.
> | One day mankind (or at least the computer-literate part thereof) will
> | look back and shake its collective head at how much intellectual
> | resources were wasted on that horrible mistake called C++.
>
> I guess that would depend on how would they measure "waste" and "mistake".
No, this does not depend on anything. I was making a prediction of
what future generations will think of C++, and it contains an implied
prediction of what these generations will consider a "waste" and a
"mistake". My prediction will either come true or it won't. Only time
can tell, but I am confident that I am right.
> The functional programminng community has "owned" institutions for
> over three decades now, yet...
Yet what?
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/1/2005 10:00:32 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
> | I expect some FPL to be a grandiose improvement over C++ -
>
> I hope so too. The functional programming community has owned
> institutions and spent wonderful resources there for over three
> decades. It would be a terrible and unqualifiable waste if they could
> not have a grandiose improvement of C++.
A lot of the ideas from FPL could (and in my opinion should) be
transplanted to next-generation imperative programming languages. Even
if none of the FPL programming ever becomes mainstream the research has
not been a waste.
In fact this transplantation is already happening: Python has borrowed
quite a lot from functional languages (except, unfortunately, a type
system), and has become very popular. I don't know Ruby, but I get the
impression there the same is true. Guy Steele and others are designing a
new programming language Fortress that also borrows a lot.
Moreover, processor design has increasing difficulty in hiding
parallelism, so traditional imperative languages are in trouble anyway.
I doubt this trend will make an existing FPL mainstream, but at least
the FPLs show that there are alternatives, and they offer at least part
of the solution.
|
|
0
|
|
|
|
Reply
|
reeuwijk (3)
|
6/1/2005 10:39:50 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> Gabriel Dos Reis wrote:
>
> > Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
> > | You cannot expect to arrive at a good language when you don't
> > separate
> > | issues of semantics and implementation properly.
> > That is a matter of opinion instead of fact.
>
> No, it's hard fact.
>
> I have programmed both in Eiffel and C++. Both languages are good
> representatives for the static-typing OO view of the programming
> world. Eiffel was designed for clarity of concepts, C++ was designed for
> efficient compilation.
Well, I sort of agree. But C++ was designed to be compatible with C.
Many of the problems in C++ can be traced to that compatibility
requirement.
I agree with Andreas Rossberg's statement above, but I don't think that
should mean "ignore implementation issues".
>... This shows in many ways:
> * The default for Eiffel member functions is that they are
> virtual. Nonvirtual functions are a very rare exception. The additional
> dynamic dispatch isn't a real issue, 90% of dispatching calls can be
> made static - it's more difficult under separate compilation, and would
> probably require some kind of smart linking (in a separate step before
> linking with modules written in other languages), but it's all not quite
> rocket science, and can be made as efficient as one would care.
> * You can make virtual calls from within constructors. Actually
> constructor functions are completely normal functions, except that they
> can be called when an object is constructed initially. No fiddling with
> automatic initialisation. This is *far* simpler than the set of rules
> used in C++.
> * Eiffel requires garbage collection. Now that makes Eiffel unsuitable
> for HRT, but it makes it far more reliable - if a constructor throws an
> exception, created objects are orphaned and will be reclaimed. In other
> words, I don't have to worry about memory leaks - that's a *huge*
> simplification for programmers. Besides, I wouldn't want to use C++ for
> HRT either - and, no, "smart pointers" aren't a smart solution here,
> deallocating an object may trigger a chain of deallocations and makes
> deallocation less predictable (and queuing up the deallocations just
> means that memory isn't freed at the time it becomes available, so we're
> halfways back to the timing performance of traditional automatic GC, but
> with a horribly slow interface that requires permanent updates in
> reference counts). If I were to do HRT programming, I'd not use dynamic
> memory allocation anyway - so neither C++ nor Eiffel fit the bill :-)
I'm not sure why you say that. C++ can be used without dynamic
allocation pretty easily. I suppose Eiffel could, too, but it's perhaps
more painful (declare everything "expanded"?). For hard-real-time, I
prefer Ada.
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
6/1/2005 11:51:44 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> Gabriel Dos Reis wrote:
>
> > Joachim Durchholz <jo@durchholz.org> writes:
> > | However, the way Annex B does not make promises, and the list of
> > | things that are in it, that's all very bad for generated code. It's
> > | easy to have more than 256 nested parentheses in an expression, or to
> > | go beyond any of the other limits that a C++ compiler may have and be
> > | compliant.
> > I hope you realized that 256 is not a normative limit,
>
> Sure.
>
> I'm also well aware that that 256 number listed is just an example of
> such a limit - it could be 100, 20, 20,000, or "bounded only by memory".
>
> > and Annex B
> > started with reminding that implementations must document their limits
> > (that requirement is already formulated in the normative part �1.9)
>
> I don't object to the precision of Annex B - sometimes it's helpful to
> specifically state what things are explicitly *not* guaranteed.
>
> However, I would have found it far better if the language had specified
> that no such limits are allowed (except for the obvious "limited by
> available memory").
I agree with you that compilers should not have such arbitrary limits,
other than those based on "available memory". But I don't see how a
language standard can say so. How can you write a test case that
determines whether the compiler obeys such a rule? I mean, if the thing
crashes on the 257'th level of nesting, how do you know (formally)
whether it has an arbitrary limit of 256, or it just ran out of memory?
(You can guess...)
>... Right now, anybody who generates C++ programs will
> have to consider all these limitations, and provide workarounds for them
> - this *vastly* complicates code generation if done properly (so most
> code-generating programs probably punt on the issue and rely on the C++
> compiler to properly report if the table overflows).
Perhaps it would be better for a language standard to avoid mentioning
such limits at all. And for a conformance test suite to use lots of
nesting.
> > | I'm quite puzzled why C++ has such a long list of limited
> > | resources.
> > Maybe it is because you haven't seen that of C :-). See below.
> > (I hope they are not problem for functional programming language
> > implementations that generate C codes ;-))
>
> Contrary to popular belief, C is not a good portable assembler. The
> standard strategy for compiling FPLs nowadays seems to be machine code
> generation.
Well, C isn't *so* bad. Problems include: Lack of overflow detection.
No access to hardware operations like (single X single)-->double
integer multiply instructions. No portable and efficient way to
implement exception handling. Etc.
> > | In a modern system, it would be easy to lift all these
> > | restrictions (and replace them with the blanket "limited by available
> > | memory" statement).
> > one could, but the question: isn't that blanket statement already
> > part of the normative part? Seurely it is. The other thing is you
> > seem to believe that C++ must run only on "a modern system", something
> > that needs to be clarified. People involved in C++ standardization
> > felt that C++ should be able to run also on not so "modern systems".
> > I think we all agree that, if one sufficiently narrows its scope, one
> > could achieve nifty things. C++ has been trying not to narrow to much
> > its scope.
>
> Hold it. I'd say that at C++ *compiler* can be expected to run on a
> reasonably modern system. (Besides, I don't know of a C++ compiler that
> doesn't require several dozen megabytes, so that's reality already.)
Yes. All compilers (these days) should run on fast machines with lots
of memory. For embedded systems, cross compilers should be used.
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
6/2/2005 12:06:59 AM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
> Joachim Durchholz wrote:
> > Algol was a grandiose improvement over PL/I.
>
> Um, Algol predates PL/I by almost a decade.
Yes. And yet Algol is an improvement upon PL/I. ;-)
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
6/2/2005 12:16:55 AM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> [...]
>
> | > Personally, I think there are lot of things that can be improved and
> | > we have done some of them.
> |
> | Some things are just not worth repairing. The basic problem is that
> | you are not willing to "break C++" (see above). This precludes any
> | improvement.
>
> But that is your opinion. You actually have not tried. Have you?
No, I have not. Not everything needs to be tried first to know that
it is no use.
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/2/2005 2:26:13 AM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> reeuwijk@few.vu.nl (Kees van Reeuwijk) writes:
>
> | Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
> |
> | > Joachim Durchholz <jo@durchholz.org> writes:
> | >
> | > | I expect some FPL to be a grandiose improvement over C++ -
> | >
> | > I hope so too. The functional programming community has owned
> | > institutions and spent wonderful resources there for over three
> | > decades. It would be a terrible and unqualifiable waste if they could
> | > not have a grandiose improvement of C++.
> |
> | A lot of the ideas from FPL could (and in my opinion should) be
> | transplanted to next-generation imperative programming languages. Even
> | if none of the FPL programming ever becomes mainstream the research has
> | not been a waste.
>
> The point was not that ideas from functional programming languages
> could be borrowed and implanted elsewhere. The claim was that FPL
> could be a gandiose improvement over C++. I think it takes more than
> just borrowing.
A lot of FPLs (and a lot of other languages, too) are *already*
significant (to avoid saying "grandiose") improvements over C++.
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/2/2005 2:27:54 AM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> |
> | > Matthias Blume <find@my.address.elsewhere> writes:
> | >
> | > [...]
> | >
> | > | > Personally, I think there are lot of things that can be improved and
> | > | > we have done some of them.
> | > |
> | > | Some things are just not worth repairing. The basic problem is that
> | > | you are not willing to "break C++" (see above). This precludes any
> | > | improvement.
> | >
> | > But that is your opinion. You actually have not tried. Have you?
> |
> | No, I have not.
>
> Thanks for the confirmation, I was suspecting that possibility but I
> was not sure.
To avoid misunderstandings: I am *very* interested in well-designed
programming languages, their design in itself, their efficient
implementation, and their application. But that does not mean I have
to work on something in which I see absolutely no value just to be
able to judge it. C++ is so far from my idea of a good language, it
cannot possibly be "improved" to something I would like and use
voluntarily, especially not if there is a "constraint" that all the
existing badness needs to be preserved. Therefore, your suggestion
that I am somehow not in the position of judging wether C++ is good or
bad just because I have not personally tried to improve it is more
than misguided.
Matthias
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/2/2005 2:51:56 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
[...]
| > Personally, I think there are lot of things that can be improved and
| > we have done some of them.
|
| Some things are just not worth repairing. The basic problem is that
| you are not willing to "break C++" (see above). This precludes any
| improvement.
But that is your opinion. You actually have not tried. Have you?
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 2:54:37 AM
|
|
reeuwijk@few.vu.nl (Kees van Reeuwijk) writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
|
| > Joachim Durchholz <jo@durchholz.org> writes:
| >
| > | I expect some FPL to be a grandiose improvement over C++ -
| >
| > I hope so too. The functional programming community has owned
| > institutions and spent wonderful resources there for over three
| > decades. It would be a terrible and unqualifiable waste if they could
| > not have a grandiose improvement of C++.
|
| A lot of the ideas from FPL could (and in my opinion should) be
| transplanted to next-generation imperative programming languages. Even
| if none of the FPL programming ever becomes mainstream the research has
| not been a waste.
The point was not that ideas from functional programming languages
could be borrowed and implanted elsewhere. The claim was that FPL
could be a gandiose improvement over C++. I think it takes more than
just borrowing.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 2:57:45 AM
|
|
David Hopwood <david.nospam.hopwood@blueyonder.co.uk> writes:
| Joachim Durchholz wrote:
| > Gabriel Dos Reis wrote:
| >
| >> Breaking C++ is not a luxury we have, that is a fundamental constraint.
| > Well, let me utter a sacrilege... C++ is the PL/I of modern
| > days. It's trying to be everything to everyone, and adding too many
| > ways to do the same thing, failing to provide some key mechanisms
| > that could replace the existing ones (not that this failure is a
| > fault of its designers: they had to work with the insights that were
| > available at the time of design); with a baroque syntax and
| > semantics that (almost) nobody completely understands.
|
| Almost?
|
| Andreas Rossberg wrote:
| > Joachim Durchholz wrote:
| > > Algol was a grandiose improvement over PL/I.
| >
| > Um, Algol predates PL/I by almost a decade.
|
| Hence Tony Hoares's comment on Algol 60:
|
| Here is a language so far ahead of its time, that it was not only an
| improvement on its predecessors, but also on nearly all its successors.
|
I thought it was clear that, for most claims in this thread, facts are
obviously perversions that should be avoided. :-)
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 3:01:24 AM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> |
> | > reeuwijk@few.vu.nl (Kees van Reeuwijk) writes:
> | >
> | > | Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
> | > |
> | > | > Joachim Durchholz <jo@durchholz.org> writes:
> | > | >
> | > | > | I expect some FPL to be a grandiose improvement over C++ -
> | > | >
> | > | > I hope so too. The functional programming community has owned
> | > | > institutions and spent wonderful resources there for over three
> | > | > decades. It would be a terrible and unqualifiable waste if they could
> | > | > not have a grandiose improvement of C++.
> | > |
> | > | A lot of the ideas from FPL could (and in my opinion should) be
> | > | transplanted to next-generation imperative programming languages. Even
> | > | if none of the FPL programming ever becomes mainstream the research has
> | > | not been a waste.
> | >
> | > The point was not that ideas from functional programming languages
> | > could be borrowed and implanted elsewhere. The claim was that FPL
> | > could be a gandiose improvement over C++. I think it takes more than
> | > just borrowing.
> |
> | A lot of FPLs (and a lot of other languages, too) are *already*
> | significant (to avoid saying "grandiose") improvements over C++.
>
> That may be quite possible though I would prefer facts not just claims
> (there seem to be many of them in this thread that carefully avoid
> being tainted by reality) and evidence of why they are significant
> improvement over C++.
What "reality" are you talking about? The many deficits of C++ have
been listed over and over. I won't repeat them here.
As for me, I find programming in those FPL far more pleasant and
productive than trying to do the same in C++.
> No, I would not take your word for it, sorry :-)
I am not asking you to take my word for it. Just a shame that some
clearly capable people waste their talents on something which, as I
believe strongly, will ultimately be known as a grandiose mistake.
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/2/2005 3:03:09 AM
|
|
Robert A Duff <bobduff@shell01.TheWorld.com> writes:
| Joachim Durchholz <jo@durchholz.org> writes:
|
| > Gabriel Dos Reis wrote:
| >
| > > Joachim Durchholz <jo@durchholz.org> writes:
| > > | However, the way Annex B does not make promises, and the list of
| > > | things that are in it, that's all very bad for generated code. It's
| > > | easy to have more than 256 nested parentheses in an expression, or to
| > > | go beyond any of the other limits that a C++ compiler may have and be
| > > | compliant.
| > > I hope you realized that 256 is not a normative limit,
| >
| > Sure.
| >
| > I'm also well aware that that 256 number listed is just an example of
| > such a limit - it could be 100, 20, 20,000, or "bounded only by memory".
| >
| > > and Annex B
| > > started with reminding that implementations must document their limits
| > > (that requirement is already formulated in the normative part �1.9)
| >
| > I don't object to the precision of Annex B - sometimes it's helpful to
| > specifically state what things are explicitly *not* guaranteed.
| >
| > However, I would have found it far better if the language had specified
| > that no such limits are allowed (except for the obvious "limited by
| > available memory").
|
| I agree with you that compilers should not have such arbitrary limits,
| other than those based on "available memory". But I don't see how a
| language standard can say so. How can you write a test case that
| determines whether the compiler obeys such a rule? I mean, if the thing
| crashes on the 257'th level of nesting, how do you know (formally)
| whether it has an arbitrary limit of 256, or it just ran out of memory?
It is a point I've already made, pointing to the relevant part of the C++
definition; but that does not count it appears...
[...]
| Yes. All compilers (these days) should run on fast machines with lots
| of memory.
And for those that don't? They are still quite plenty of them, last
time I checked. As an implementer, I regularly get complain about the
compiler speed on not so modern but not so old machines,
| For embedded systems, cross compilers should be used.
Yes, but there is a wide spectrum between the two extremes.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 3:09:03 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Matthias Blume <find@my.address.elsewhere> writes:
| >
| > [...]
| >
| > | > Personally, I think there are lot of things that can be improved and
| > | > we have done some of them.
| > |
| > | Some things are just not worth repairing. The basic problem is that
| > | you are not willing to "break C++" (see above). This precludes any
| > | improvement.
| >
| > But that is your opinion. You actually have not tried. Have you?
|
| No, I have not.
Thanks for the confirmation, I was suspecting that possibility but I
was not sure.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 3:39:04 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > reeuwijk@few.vu.nl (Kees van Reeuwijk) writes:
| >
| > | Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
| > |
| > | > Joachim Durchholz <jo@durchholz.org> writes:
| > | >
| > | > | I expect some FPL to be a grandiose improvement over C++ -
| > | >
| > | > I hope so too. The functional programming community has owned
| > | > institutions and spent wonderful resources there for over three
| > | > decades. It would be a terrible and unqualifiable waste if they could
| > | > not have a grandiose improvement of C++.
| > |
| > | A lot of the ideas from FPL could (and in my opinion should) be
| > | transplanted to next-generation imperative programming languages. Even
| > | if none of the FPL programming ever becomes mainstream the research has
| > | not been a waste.
| >
| > The point was not that ideas from functional programming languages
| > could be borrowed and implanted elsewhere. The claim was that FPL
| > could be a gandiose improvement over C++. I think it takes more than
| > just borrowing.
|
| A lot of FPLs (and a lot of other languages, too) are *already*
| significant (to avoid saying "grandiose") improvements over C++.
That may be quite possible though I would prefer facts not just claims
(there seem to be many of them in this thread that carefully avoid
being tainted by reality) and evidence of why they are significant
improvement over C++.
No, I would not take your word for it, sorry :-)
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 3:46:17 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Matthias Blume <find@my.address.elsewhere> writes:
| >
| > | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
| > |
| > | > Matthias Blume <find@my.address.elsewhere> writes:
| > | >
| > | > [...]
| > | >
| > | > | > Personally, I think there are lot of things that can be improved and
| > | > | > we have done some of them.
| > | > |
| > | > | Some things are just not worth repairing. The basic problem is that
| > | > | you are not willing to "break C++" (see above). This precludes any
| > | > | improvement.
| > | >
| > | > But that is your opinion. You actually have not tried. Have you?
| > |
| > | No, I have not.
| >
| > Thanks for the confirmation, I was suspecting that possibility but I
| > was not sure.
|
| To avoid misunderstandings: I am *very* interested in well-designed
| programming languages, their design in itself, their efficient
| implementation, and their application. But that does not mean I have
| to work on something in which I see absolutely no value just to be
| able to judge it. C++ is so far from my idea of a good language, it
| cannot possibly be "improved" to something I would like and use
| voluntarily, especially not if there is a "constraint" that all the
| existing badness needs to be preserved. Therefore, your suggestion
| that I am somehow not in the position of judging wether C++ is good or
| bad just because I have not personally tried to improve it is more
| than misguided.
Well, the suggestion was not that you're not in position to make
judgement on something you have not tried but have strong opinions on
and are absolutely right that it cannot not be improved. It looks
like to you can draw just about any conclusion.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 6:31:50 AM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
>| A lot of the ideas from FPL could (and in my opinion should) be
>| transplanted to next-generation imperative programming languages. Even
>| if none of the FPL programming ever becomes mainstream the research has
>| not been a waste.
> The point was not that ideas from functional programming languages
> could be borrowed and implanted elsewhere.
The point of research and universities is mainly to produce ideas.
Products are to a large extent side effects, proofs of concept that
an idea works in practice. Expecting computer science departments to
compete with C++ is like expecting the literature department to
publish best seller novels.
> The claim was that FPL could be a gandiose improvement over C++. I
> think it takes more than just borrowing.
I used to have a job writing C++ code. I definitely believe I'm more
productive and write more robust code using a FPL, and I *know* that I
have a lot more fun doing it.
Which FPLs have you used, and in what ways do you think they are
inferior to C++?
-kzm
--
If I haven't seen further, it is by standing in the footprints of giants
|
|
0
|
|
|
|
Reply
|
news2 (145)
|
6/2/2005 6:37:35 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Matthias Blume <find@my.address.elsewhere> writes:
| >
| > | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
| > |
| > | > reeuwijk@few.vu.nl (Kees van Reeuwijk) writes:
| > | >
| > | > | Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
| > | > |
| > | > | > Joachim Durchholz <jo@durchholz.org> writes:
| > | > | >
| > | > | > | I expect some FPL to be a grandiose improvement over C++ -
| > | > | >
| > | > | > I hope so too. The functional programming community has owned
| > | > | > institutions and spent wonderful resources there for over three
| > | > | > decades. It would be a terrible and unqualifiable waste if they could
| > | > | > not have a grandiose improvement of C++.
| > | > |
| > | > | A lot of the ideas from FPL could (and in my opinion should) be
| > | > | transplanted to next-generation imperative programming languages. Even
| > | > | if none of the FPL programming ever becomes mainstream the research has
| > | > | not been a waste.
| > | >
| > | > The point was not that ideas from functional programming languages
| > | > could be borrowed and implanted elsewhere. The claim was that FPL
| > | > could be a gandiose improvement over C++. I think it takes more than
| > | > just borrowing.
| > |
| > | A lot of FPLs (and a lot of other languages, too) are *already*
| > | significant (to avoid saying "grandiose") improvements over C++.
| >
| > That may be quite possible though I would prefer facts not just claims
| > (there seem to be many of them in this thread that carefully avoid
| > being tainted by reality) and evidence of why they are significant
| > improvement over C++.
|
| What "reality" are you talking about? The many deficits of C++ have
| been listed over and over. I won't repeat them here.
Like this
<d7kcsl$2581l$4@hades.rz.uni-saarland.de>
?
Yes, please don't :-)
Furthermore, as has being pointed out, the "many deficits" of C++
listed here have been made based on misunderstanding of what they are
and where they came from. Someone insisted on syntax and "typename"
issue without quite understanding that it was a problem inherited from
C, as opposed to a problem introduced by templates.
In fact, I've found that working on C++ is more challenging than, say,
working on ML variants or Haskell -- not that those languages do not
provide opportunities for intellectual excitements. The primary
reason being that problems with C++ are really challenging for both
existing theories, design and implementation techniques. As you may
know, some have even decided not to look because they thought they
could not make any progress :-) And, it is quite gratifying to see
that progress can be made where others have resigned -- but I do
not expect to convince you of that.
| As for me, I find programming in those FPL far more pleasant and
| productive than trying to do the same in C++.
I do respect you opinion.
Personally, my FPLs are not that good as my C/C++ but I do have
extensive programming experience with FPLs (hard to do otherwise in
certain areas in the French system) and I've come to the conclusion
that despite those aspects I really dislike in C++, I've yet to see
most of claimed advances in modern FPLs match in expressivity and
scalability -- yes, I know that is a sufficient reason to be flamed
for on c.l.f. but I'm hope there are souls there less dogmatic (yes, I
know there are, I've met them on several occasions :-)). I don't have
to like it before solving the challenges it poses. I'd encourage
anyone who has not been there before to try it.
Now, what about others far more well-known who have actually
transgressed the cultural barriers and sub-community walls?
http://www.stepanovpapers.com/
But, I guess that does not count.
| > No, I would not take your word for it, sorry :-)
|
| I am not asking you to take my word for it. Just a shame that some
| clearly capable people waste their talents on something which, as I
| believe strongly, will ultimately be known as a grandiose mistake.
Yes, I guess if those people spent their talents on SML/NJ it would
not be waste.
In fact I tried for some time -- it is hard to evolve in the French
system without being exposed to hardcore FP, especially in certain
academic circles -- and decided my efforts are best spent somewhere
else. Clearly, the notion of what is "waste" is not universal. And I
understand you hold yours very firmly.
I'm just hoping that somedays, cultural barriers will be transgressed
more smoothly and we would be talking about semantics, programming,
systems building, instead of focusing on angle brackets, bananas,
curly-braces and dot-notations.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 7:28:58 AM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> | A lot of FPLs (and a lot of other languages, too) are *already*
> | significant (to avoid saying "grandiose") improvements over C++.
>
> That may be quite possible though I would prefer facts not just claims
> (there seem to be many of them in this thread that carefully avoid
> being tainted by reality) and evidence of why they are significant
> improvement over C++.
> No, I would not take your word for it, sorry :-)
I tried to offer what is at least anecdotal evidence from
an industrial setting of how we've used Erlang to gain a
quite significant edge in productivity and quality.
"Four-Fold Increase in Productivity and Quality"
http://www.erlang.se/publications/Ulf_Wiger.pdf
FEmSYS 2001, Munich.
The "four-fold increase in productivity" relates to the
observation that systems with similar feature sets tend
to have 4-10x more lines of source code when written in
C++ than in Erlang. We chose the more conservative
estimate of four. Measuring line-per-man hour productivity,
different projects seem to be fairly similar as well, but
obviously then, the more expressive language wins.
Similarly for quality, we've observed that fault
density measured in errors per KLOC seems to be roughly
the same. Given fewer lines of code per feature, total
quality by this measure should be higher.
Since the writing of that paper, the fault-density measured
in errors per 100 lines of code has decreased by a factor
3-4 in the product in question, at the same time as the
source code volume has doubled in size. We are now in the
process of building successors to that product, where we
have been able to rewrite and restructure more freely, and
I believe that the end result will be quite impressive.
There are some obvious problems: I cannot reveal all the
background data due to confidentiality constraints. It's
also quite difficult to produce scientific comparisons
of products written in different programming languages,
since we obviously never build the same product twice
using teams that are identical in experience and
competence, but with different implementation technologies
(and the size and complexity of the products, something
that obviously affects the comparison, makes it practically
impossible to perform such a study in an academic (or indeed
any) setting). Furthermore, the improvements made since 2001
also reflect the fact that we've had low personnel turnover,
and thus have many designers with several years of
experience working with this technology and using our
methodology. Especially for FPLs in a commercial environment,
this is something very unusual.
Some of my thoughts on using unconventional development
tools in industry were summarized in
http://www.erlang.se/workshop/2004/ulfwiger.pdf
/Uffe
--
Ulf Wiger, Senior Specialist,
/ / / Architecture & Design of Carrier-Class Software
/ / / Team Leader, Software Characteristics
/ / / Ericsson AB, IMS Gateways
|
|
0
|
|
|
|
Reply
|
ulf.wiger1 (107)
|
6/2/2005 9:00:25 AM
|
|
Andreas Rossberg wrote:
> Joachim Durchholz wrote:
>
>> Algol was a grandiose improvement over PL/I.
>
> Um, Algol predates PL/I by almost a decade.
Yes. It was a great improvement over many of its successors.
(This isn't my observation, I'm just quoting somebody (Dijkstra?) from
memory.)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/2/2005 12:08:01 PM
|
|
Gabriel Dos Reis wrote:
> Furthermore, as has being pointed out, the "many deficits" of C++
> listed here have been made based on misunderstanding of what they are
> and where they came from.
I agree that there may be misunderstandings about where C++ deficits
come from. However, what they are is well-known (ignoring Annex B for
the moment - compared to some other problems, this is really a secondary
point).
> Someone insisted on syntax and "typename"
> issue without quite understanding that it was a problem inherited from
> C, as opposed to a problem introduced by templates.
It's still a serious problem. Mimicking C++'s quirks in C so closely had
advantages for acceptability, but it make the language far, far worse.
However, I think Bjarne got a lot of the new things really, really wrong
(overloading, per-default nonvirtual functions, almost all aspects of
constructor semantics, redundant class specifications, just to name a
few). Most of these seem to be due to a (mistaken, IMNSHO) priorisation
of efficient compilation and run-time execution over a clean language
semantics.
> In fact, I've found that working on C++ is more challenging than, say,
> working on ML variants or Haskell -- not that those languages do not
> provide opportunities for intellectual excitements. The primary
> reason being that problems with C++ are really challenging for both
> existing theories, design and implementation techniques. As you may
> know, some have even decided not to look because they thought they
> could not make any progress :-) And, it is quite gratifying to see
> that progress can be made where others have resigned -- but I do
> not expect to convince you of that.
I don't think it's even remotely possible to turn C++ into a safe
language. This says everything that I need to know about whether
investing intellectual effort into it is worth it.
> | As for me, I find programming in those FPL far more pleasant and
> | productive than trying to do the same in C++.
>
> I do respect you opinion.
> Personally, my FPLs are not that good as my C/C++ but I do have
> extensive programming experience with FPLs (hard to do otherwise in
> certain areas in the French system) and I've come to the conclusion
> that despite those aspects I really dislike in C++, I've yet to see
> most of claimed advances in modern FPLs match in expressivity and
> scalability -- yes, I know that is a sufficient reason to be flamed
> for on c.l.f. but I'm hope there are souls there less dogmatic (yes, I
> know there are, I've met them on several occasions :-)). I don't have
> to like it before solving the challenges it poses. I'd encourage
> anyone who has not been there before to try it.
Um... where are the scalability problems?
Actually C++ offers its own set of scalability problems. There's often
cultural blindness involved - people get so used to the limitations of
the language that they use on a day-to-day basis that they think the
problems are of a general nature, instead of due to design mistakes in
the language.
> I'm just hoping that somedays, cultural barriers will be transgressed
> more smoothly and we would be talking about semantics, programming,
> systems building, instead of focusing on angle brackets, bananas,
> curly-braces and dot-notations.
I have been talking about semantics all the time. My conclusion has been
that C++ sucks, plain and simple. That's even common wisdom, as in "C
gives you enough rope to hang yourself, but C++ also provides you with a
gun and ammo to blow your feet off".
Not that I particularly like C++'s syntax. It's a nightmare. Template
syntax is just as bad; I'm amazed about the amount of i**ocy that makes
a language designer use << >> as template parameter delimiters and set
up the parsing rules so that you need symbol table information to see
whether that's two < < symbols in a row or a single << parameter.
In other words: while I agree that Bjarne had a tough job being
compatible enough with C to avoid outrage (a questionable but reasonable
decision), he added so much to the syntactic confusion that C
compatibility simply isn't a good excuse anymore. C++ is a piece of
language design teaching how *not* to do it. (This doesn't mean I could
do better. I just observe that there were a lot of people who are doing
better. It's a pity that nobody besides Bjarne tried a good
static-typing extension to C - or, if alternatives existed, they didn't
get the attention that Bjarne with his corporate backing got.)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/2/2005 12:31:50 PM
|
|
Robert A Duff wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>> * Eiffel requires garbage collection. [...] If I were to do HRT
>> programming, I'd not use dynamic memory allocation anyway - so
>> neither C++ nor Eiffel fit the bill :-)
>
> I'm not sure why you say that. C++ can be used without dynamic
> allocation pretty easily. I suppose Eiffel could, too, but it's
> perhaps more painful (declare everything "expanded"?).
Well, you could, but "expanded" means you don't have polymorphism. In
other words, all the OO stuff goes out of the window, and you could just
as well program in Ada or Modula or whatever.
I'd expect similar problems with C++ if dynamic memory allocation is
disallowed, but I'm not familiar enough with that scenario to tell for sure.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/2/2005 12:40:24 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> I'm amazed about the amount of i**ocy that makes a language designer
> use << >> as template parameter delimiters and set up the parsing
> rules so that you need symbol table information to see whether
> that's two < < symbols in a row or a single << parameter.
Delimiters are < >, not << >>, and >> never means > >, unlike Java
(and < < never occurs); actually this is what many people consider
a wart.
Symbol table information is required to distinguish between template
parameters and less-than operator though. Parsing C++ requires full
typechecking, including name resolution, overloading resolution,
template instantiation, and evaluation of constant expressions.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/2/2005 12:40:37 PM
|
|
Robert A Duff wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
>>However, I would have found it far better if the language had specified
>>that no such limits are allowed (except for the obvious "limited by
>>available memory").
>
> I agree with you that compilers should not have such arbitrary limits,
> other than those based on "available memory". But I don't see how a
> language standard can say so. How can you write a test case that
> determines whether the compiler obeys such a rule?
Simple enough. Write a test suite that doubles any limit in question.
Observe the compiler's memory footprint. If the memory footprint nears
available memory, without the compiler complaining, it passes.
Of course, a devious compiler writer could get away with arbitrary
limits, either by providing large-enough tables or by arbitrarily
allocating unneeded memory :-)
.... but then I don't think anybody would do that :-))
>>>> I'm quite puzzled why C++ has such a long list of limited
>>>> resources.
>>>Maybe it is because you haven't seen that of C :-). See below.
>>>(I hope they are not problem for functional programming language
>>>implementations that generate C codes ;-))
>>
>>Contrary to popular belief, C is not a good portable assembler. The
>>standard strategy for compiling FPLs nowadays seems to be machine code
>>generation.
>
> Well, C isn't *so* bad. Problems include: Lack of overflow detection.
> No access to hardware operations like (single X single)-->double
> integer multiply instructions. No portable and efficient way to
> implement exception handling. Etc.
No tail-call optimisation. This is the first barrier that FPL compiler
writers hit (exceptions and some issues with closure construction and
other exoticities come next, but many implementors have already given up
on C before reaching that point).
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/2/2005 12:46:02 PM
|
|
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
> Symbol table information is required to distinguish between template
> parameters and less-than operator though. Parsing C++ requires full
> typechecking, including name resolution, overloading resolution,
> template instantiation, and evaluation of constant expressions.
A pathologic example: whether <2> in the last line is template
parameter or less-then and greater-then operators depends on the
number of bits in an int.
template<unsigned N> struct C {static const int x = 1;};
template<> struct C<0> {template<int a> static void x(int b) {}};
int main() {C<0x100u * 0x100u>::x<2>(3);}
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/2/2005 12:49:22 PM
|
|
>>>>> Joachim Durchholz wrote (on Thu, 02 Jun 2005 at 13:08):
> Andreas Rossberg wrote:
>> Joachim Durchholz wrote:
>>
>>> Algol was a grandiose improvement over PL/I.
>> Um, Algol predates PL/I by almost a decade.
> Yes. It was a great improvement over many of its successors.
> (This isn't my observation, I'm just quoting somebody (Dijkstra?) from
> memory.)
Hoare. In "Hints on programming language design".
H
|
|
0
|
|
|
|
Reply
|
hancock (83)
|
6/2/2005 12:55:43 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Furthermore, as has being pointed out, the "many deficits" of C++
> listed here have been made based on misunderstanding of what they are
> and where they came from. Someone insisted on syntax and "typename"
> issue without quite understanding that it was a problem inherited from
> C, as opposed to a problem introduced by templates.
The fact that it is inherited from C *is* the problem. (I don't care
"where it came from". If it is bad, it is bad.)
You seem to suggest that something becomes better if we understand why
it came to be so bad. I reject that view.
> In fact, I've found that working on C++ is more challenging than, say,
> working on ML variants or Haskell -- not that those languages do not
> provide opportunities for intellectual excitements.
Teaching calculus to dogs is also far more challenging than teaching
it to humans. Should we enroll dogs in math courses, for the
challenge's sake?
By the way, what specifically have you done "working on ML variants or
Haskell"? (Just curious.)
> The primary reason being that problems with C++ are really
> challenging for both existing theories, design and implementation
> techniques.
Yes, but that is precisely the problem with C++. Basically, it is
way, way too complex -- withouth this complexity actually being paid
for by anything good.
> As you may know, some have even decided not to look because they
> thought they could not make any progress :-)
> And, it is quite gratifying to see that progress can be made where
> others have resigned -- but I do not expect to convince you of that.
I don't consider the development of C++ "progress" -- not its original
design, and not its subsequent development. So far, not having
accepted the "challenge" seems like it was the right thing to do.
> Yes, I guess if those people spent their talents on SML/NJ it would
> not be waste.
Spending one's efforts on one particular implementation (or even just
one particular language) only is probably going to be a waste unless
lessons can be learned that "survive". Lessons from ML will certainly
survive.
> Clearly, the notion of what is "waste" is not universal.
Granted. However, notice that my prediction (i.e., my belief) is that
C++ will *eventually* be viewed as a waste (almost) universally.
> I'm just hoping that somedays, cultural barriers will be transgressed
> more smoothly and we would be talking about semantics, programming,
> systems building, instead of focusing on angle brackets, bananas,
> curly-braces and dot-notations.
Did I say even one word about "angle brackets, bananas, curly-braces
and dot-notations"?
Matthias
PS: What are "bananas"?
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/2/2005 1:01:43 PM
|
|
Gabriel Dos Reis wrote:
>
> Furthermore, as has being pointed out, the "many deficits" of C++
> listed here have been made based on misunderstanding of what they are
> and where they came from. Someone insisted on syntax and "typename"
> issue without quite understanding that it was a problem inherited from
> C, as opposed to a problem introduced by templates.
Since I believe that you are referring to me I have to rebut that I
think it's you who still misunderstands. To repeat: I'm aware of the
constraints and their origins, I'm aware that it's hard to achieve
anything significantly better under these constraints. But since I'm not
bound to these constraints (I don't need C compatibility), I don't need
to consider them in my evaluation of the outcome.
And I simply can't believe that you do not see any deficits in the outcome.
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
6/2/2005 2:06:18 PM
|
|
Gabriel Dos Reis wrote:
>
> As before, I will try to inject, once again, a bit of facts in this
> discussion. D&E, page 68-69
>
> �3.3.2 Parsing C++
>
> In 1982 when I first planned Cfront, I wanted to use a recursive
> descent parser because I had experience writing and maintaining such
> a beast, because I liked such parsers' ability to produce good
> error messages, and because I liked the idea of having the full
> power of a general purpose programming language available when
> decisions had to be made in the parser. However, being a
> conscientious young computer scientist I asked the experts. Al Aho
> and Steve Johnson were in the Computer Science Research Center and
> they, primarily Steve, convinced me that writing a parser by hand
> was most old-fashioned, would be an inefficient use of my time,
> would almost certainly result in a hard-to-understand and
> hard-to maintain parser, and would be prone to unsystematic and
> therefore unreliable error recovery. The right way was to use an
> LALR(1) parser generator, so I used Al and Steve's YACC [Aho, 1986].
Come on, I don't have the book here, but I recall that in the next
paragraph he describes how he failed, how he judged that as a
consequence of using the wrong tool (instead of realizing that the
syntax design was broken) and abandoned it.
- Andreas
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
6/2/2005 2:15:52 PM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Furthermore, as has being pointed out, the "many deficits" of C++
| > listed here have been made based on misunderstanding of what they are
| > and where they came from. Someone insisted on syntax and "typename"
| > issue without quite understanding that it was a problem inherited from
| > C, as opposed to a problem introduced by templates.
|
| The fact that it is inherited from C *is* the problem. (I don't care
| "where it came from". If it is bad, it is bad.)
| You seem to suggest that something becomes better if we understand why
| it came to be so bad. I reject that view.
I did not suggest that, so you may reject view that and that is fine;
don't say I suggested it.
| > In fact, I've found that working on C++ is more challenging than, say,
| > working on ML variants or Haskell -- not that those languages do not
| > provide opportunities for intellectual excitements.
|
| Teaching calculus to dogs is also far more challenging than teaching
| it to humans.
That is an interesting observation.
| Should we enroll dogs in math courses, for the
| challenge's sake?
I think the idea may worth consideration, in particular if someone
like you were part of the class. The challengce might not necessarily
from come where one might think.
[...]
| > Yes, I guess if those people spent their talents on SML/NJ it would
| > not be waste.
|
| Spending one's efforts on one particular implementation (or even just
| one particular language) only is probably going to be a waste unless
| lessons can be learned that "survive". Lessons from ML will certainly
| survive.
And of course, lessons from ML will survive but not from C++; and this
is because you've looked enough into C++ problems to state that.
| > Clearly, the notion of what is "waste" is not universal.
|
| Granted. However, notice that my prediction (i.e., my belief) is that
| C++ will *eventually* be viewed as a waste (almost) universally.
|
| > I'm just hoping that somedays, cultural barriers will be transgressed
| > more smoothly and we would be talking about semantics, programming,
| > systems building, instead of focusing on angle brackets, bananas,
| > curly-braces and dot-notations.
|
| Did I say even one word about "angle brackets, bananas, curly-braces
| and dot-notations"?
those are my words for "syntax".
|
| Matthias
|
| PS: What are "bananas"?
a notation common in certain area of FP community.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 2:42:55 PM
|
|
Marcin 'Qrczak' Kowalczyk wrote:
>
> A pathologic example: whether <2> in the last line is template
> parameter or less-then and greater-then operators depends on the
> number of bits in an int.
>
> template<unsigned N> struct C {static const int x = 1;};
> template<> struct C<0> {template<int a> static void x(int b) {}};
> int main() {C<0x100u * 0x100u>::x<2>(3);}
Nice one! That pretty much says everything. Of course, there will be a
perfectly viable excuse for this behaviour...
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
6/2/2005 2:51:18 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
| Robert A Duff wrote:
|
| > Joachim Durchholz <jo@durchholz.org> writes:
| >
| >>However, I would have found it far better if the language had specified
| >>that no such limits are allowed (except for the obvious "limited by
| >>available memory").
| > I agree with you that compilers should not have such arbitrary
| > limits,
| > other than those based on "available memory". But I don't see how a
| > language standard can say so. How can you write a test case that
| > determines whether the compiler obeys such a rule?
|
| Simple enough. Write a test suite that doubles any limit in
| question.
Simple enough, but that does not cut it. Each time you run a compiler,
you run a possibly different instantiation of the abstract machine and
a process from the the host environment.
| Observe the compiler's memory footprint.
but how do you express that in a language standard?
| Of course, a devious compiler writer could get away with arbitrary
| limits, either by providing large-enough tables or by arbitrarily
| allocating unneeded memory :-)
| ... but then I don't think anybody would do that :-))
Notice that some compilers set internal characteristics, passes or
resource limits, depending on the avaliable memory.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 2:55:40 PM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
> Marcin 'Qrczak' Kowalczyk wrote:
>> A pathologic example: whether <2> in the last line is template
>> parameter or less-then and greater-then operators depends on the
>> number of bits in an int.
>> template<unsigned N> struct C {static const int x = 1;};
>> template<> struct C<0> {template<int a> static void x(int b) {}};
>> int main() {C<0x100u * 0x100u>::x<2>(3);}
>
> Nice one! That pretty much says everything. Of course, there will be a
> perfectly viable excuse for this behaviour...
I'm confident there is some paragraph somewhere, written by Bjarne
himself, telling the world how angry users forced him to leave things
this way, even though he know better...
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/2/2005 3:07:17 PM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
> Gabriel Dos Reis wrote:
>> As before, I will try to inject, once again, a bit of facts in this
>> discussion. D&E, page 68-69
>> therefore unreliable error recovery. The right way was to use an
>> LALR(1) parser generator, so I used Al and Steve's YACC [Aho, 1986].
> Come on, I don't have the book here, but I recall that in the next
> paragraph he describes how he failed, how he judged that as a
> consequence of using the wrong tool (instead of realizing that the
> syntax design was broken) and abandoned it.
Incidentally, I just discovered my copy when cleaning up a shelf.
Here's how it continues:
For most projects, it would have been the right choice. For almost
every project writing an experimental language from scratch, it
would have been the right choice. For most people, it would have
been the right choice. In retrospect, for me and C++ it was a bad
mistake. C++ was not a new experimental language, it was an almost
compatible superset of C. [difficulties of C parsing snipped] Worse,
it seems that some people have a natural affinity to some parser
strategies and others work much better with other strategies. My
bias towards top-down parsing has shown itself many times over the
years in the form of constructs that are hard to fit into a YACC
grammar. To this day, Cfront has a YACC parser supplemented by much
lexical trickery relying on recursive descent techniques. On the
other hand, it /is/ possible to write an efficient and reasonably
nice recursive descent parser for C++. Several modern C++ compilers
use recursive descent.
So, it is blamed on the sucky syntax of C, but also on his personal
preferences (preferring sucky syntax? :-).
-kzm
--
If I haven't seen further, it is by standing in the footprints of giants
|
|
0
|
|
|
|
Reply
|
news2 (145)
|
6/2/2005 5:58:14 PM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| Gabriel Dos Reis wrote:
| > As before, I will try to inject, once again, a bit of facts in this
| > discussion. D&E, page 68-69
| > �3.3.2 Parsing C++
| > In 1982 when I first planned Cfront, I wanted to use a recursive
| > descent parser because I had experience writing and maintaining such
| > a beast, because I liked such parsers' ability to produce good
| > error messages, and because I liked the idea of having the full
| > power of a general purpose programming language available when
| > decisions had to be made in the parser. However, being a
| > conscientious young computer scientist I asked the experts. Al Aho
| > and Steve Johnson were in the Computer Science Research Center and
| > they, primarily Steve, convinced me that writing a parser by hand
| > was most old-fashioned, would be an inefficient use of my time,
| > would almost certainly result in a hard-to-understand and
| > hard-to maintain parser, and would be prone to unsystematic and
| > therefore unreliable error recovery. The right way was to use an
| > LALR(1) parser generator, so I used Al and Steve's YACC [Aho, 1986].
|
| Come on,
Oh yeah, don't bother contrasting your previous claim with what
actually happened.
| I don't have the book here, but I recall that in the next
| paragraph he describes how he failed, how he judged that as a
| consequence of using the wrong tool (instead of realizing that the
| syntax design was broken)
I don't know how much of determined distorsion it takes to make
the above statement, when the author said (page 45):
Could I have "fixed" the most annoying deficiencies of the C syntax
and semantics at some point before C++ was made pubically
available? Could I have done so without removing useful features
(to C with Classes' users in their environments -- as opposed to an
idea world) or introducing incompatibilities that were unacceptable
to C programmers wanting to migrate to C with Classes? I think
not. In some cases, I tried, but I backed out my changes after
complaints from outraged users.
[...]
The part of the C syntax I disliked the most was the declaration
syntax. Having both prefix and postfix declarator operators is the
source of a fair amount of confusion. [...]
The negative reaction to changes in this area from users was very
strong. They considered the "terseness" allowed by C essential to
the point of refusing to use a "fascist" language that required
them to write redundant type specifiers. I backed out the
change. I don't think I had a choice. Allowing implicit int is the
source of many of the annoying problems with the C++ grammar
today. Note that the pressure came from users, not management or
arm-chair language experts. [...]
Similarly, I considered the possibility of introducing a linear
notation for declarators. The C trick of having the declaration of
a name mimic its use leads to declarations that are hard to read
and write, and maximizes the opportunity for humans and programs to
confuse declarations and expressions.
[...]
My eventual rationale for leaving things as they were was that any
new syntax would (temporarily at least) add complexity to a known
mess. Also, even though the old style is a boon to teachers of
trivia and to people who want to ridicule C, it is not a
significant problem for C programmers. I this case, I'm not sure
if I did the right thing, though. The agony to me and C++
implementers, documenters, and tool builders caused by the
perversities of syntax has been significant. Users can -- and do
-- of course insulate themselves from such problems by writing in a
small and easily understood subset of C/C++ declaration syntax.
Andreas, if you want to accuse and ridicule someone of atroce
ignorance, at least do it right, based on facts.
| and abandoned it.
Again, from facts, he did not abandon the YACC parser.
For most projects, it would have been the right choice, For almost
every project writing an experimental language from scratch, it
would have been the right choice. In retrospect, for me and C++ it
was a bad mistake. C++ was not a new experimental language, it was
an almost compatible superset of C -- and at the time nobody had
been able to write an LALR(1) grammar for C. The LALR(1) grammar
used by ANSI C was constructed by Tom Pennello about a year and half
later -- far too late to benefit me and C++. Even Steve Johnson's
PCC, which was the preeminent C compiler at the time, cheated at
details that were to prove troublesome to C++ parser writers. For
example, PCC didn't handle redundant parentheses correctly so that
int(x); wasn't accepted as a declaration as a declaration of x.
Worse, it seems hat some people have a natural affinity to some
parser strategies and work much better with other strategies. My
bias toward top-down parsing has shown itself many times other the
years in the form of constructs that are hard to fit into a YACC
grammar. To this day, Cfront has a YACC parser supplemented by much
lexical trickery relying on recursive descent techniques. On the
other hand, it /is/ possible to write an efficient and reasonably
nice recursive descent parser for C++. Several modern C++ compilers
use recursive descent.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 6:47:37 PM
|
|
Problems with C/C++ syntaxes result from choices which didn't cause
troubles when they were made, only later after the languages have been
extended in other aspects.
The original C syntax was context-free. When 'typedef' got added,
parsing of declarations and casts started to depend on which
identifiers name types. In C++ it got worse with classes
(whose members can be types or not) and templates.
The syntax of declarations didn't look as bad when the only modifiers
of a declarator were D[N] (array), D[] (pointer) and D() (function).
Then pointers got a syntax more distinct from arrays, function
parameters became a part of the function's type, function pointers
and method pointers got added, and we arrived at what we have now,
where the 'signal' function can be declared as
void (*signal(int signum, void (*handler)(int)))(int);
The syntax of casts was easy to parse when all types started with a
keyword. With the adition of 'typedef', function parameter types etc.
the '(T) E' syntax become nearly ambiguous, and old gcc versions
misparsed 'throw (C());' with apparently redundant parentheses as
a beginning of a cast of something to a function pointer type
(promoted from a function type).
The choice of <> as template brackets didn't cause parsing problems at
first (except the annoyance with >>), but then the ability to specify
function template parameters explicitly on a function call got added,
and they started to collide with relational operators.
Templates were originally expanded almost textually, and were only
minimally parsed at definition time. Later rules changed in order
to detect more errors at template definition time rather than
instantiation time, and the comittee had to add the 'typename'
keyword and a syntax like 'C<T>::template f<T>(x, x)' in order
to distinguish type names from other names, and template names
from other names, before seeing their definitions.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/2/2005 6:49:50 PM
|
|
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
| Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
|
| > Symbol table information is required to distinguish between template
| > parameters and less-than operator though. Parsing C++ requires full
| > typechecking, including name resolution, overloading resolution,
| > template instantiation, and evaluation of constant expressions.
Parsing C++ does not require template instantiation, nor overload
resolutions, nor full typechecking.
But, in this discussion facts don't count.
| A pathologic example: whether <2> in the last line is template
| parameter or less-then and greater-then operators depends on the
| number of bits in an int.
If you want to see pathology, why don't you do it right and ask people
in the trenches?
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1757.html
you may even get more pathological examples if that is what you're
after.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 6:59:48 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> | > Symbol table information is required to distinguish between template
> | > parameters and less-than operator though. Parsing C++ requires full
> | > typechecking, including name resolution, overloading resolution,
> | > template instantiation, and evaluation of constant expressions.
>
> Parsing C++ does not require template instantiation, nor overload
> resolutions, nor full typechecking.
C++ parser needs to know which names are types, and which names are
templates. For qualified names like C<T>::name this requires template
instantiation and matching template specializations.
Matching template specializations requires evaluating constant
expressions. Computing the value of a constant expression which
involves sizeof requires computing the type of an arbitrary
expression. Computing the type requires overload resolution.
From C++ draft:
6.8 Ambiguity resolution [stmt.ambig]
1 There is an ambiguity in the grammar involving expression-statements
and declarations: An expression-statement with a function-style
explicit type conversion (_expr.type.conv_) as its leftmost subexpres-
sion can be indistinguishable from a declaration where the first
declarator starts with a (. In those cases the statement is a decla-
ration. [Note: To disambiguate, the whole statement might have to be
examined to determine if it is an expression-statement or a declara-
tion. This disambiguates many examples. [Example: assuming T is a
simple-type-specifier (_dcl.type_),
T(a)->m = 7; // expression-statement
T(a)++; // expression-statement
T(a,5)<<c; // expression-statement
T(*d)(int); // declaration
T(e)[5]; // declaration
T(f) = { 1, 2 }; // declaration
T(*g)(double(3)); // declaration
In the last example above, g, which is a pointer to T, is initialized
to double(3). This is of course ill-formed for semantic reasons, but
that does not affect the syntactic analysis. --end example]
2 The remaining cases are declarations. [Example:
class T {
// ...
public:
T();
T(int);
T(int, int);
};
T(a); // declaration
T(*b)(); // declaration
T(c)=7; // declaration
T(d),e,f=3; // declaration
extern int h;
T(g)(h,2); // declaration
--end example] --end note]
3 The disambiguation is purely syntactic; that is, the meaning of the
names occurring in such a statement, beyond whether they are type-
names or not, is not generally used in or changed by the disambigua-
tion. Class templates are instantiated as necessary to determine if a
qualified name is a type-name. Disambiguation precedes parsing, and a
statement disambiguated as a declaration may be an ill-formed declara-
tion. If, during parsing, a name in a template parameter is bound
differently than it would be bound during a trial parse, the program
is ill-formed. No diagnostic is required. [Note: This can occur only
when the name is declared earlier in the declaration. ] [Example:
struct T1 {
T1 operator()(int x) { return T1(x); }
int operator=(int x) { return x; }
T1(int) { }
};
struct T2 { T2(int){ } };
int a, (*(*b)(T2))(int), c, d;
void f() {
// dismabiguation requires this to be parsed
// as a declaration
T1(a) = 3,
T2(4), // T2 will be declared as
(*(*b)(T2(c)))(int(d)); // a variable of type T1
// but this will not allow
// the last part of the
// declaration to parse
// properly since it depends
// on T2 being a type-name
}
--end example]
[...]
8.2 Ambiguity resolution [dcl.ambig.res]
1 The ambiguity arising from the similarity between a function-style
cast and a declaration mentioned in _stmt.ambig_ can also occur in the
context of a declaration. In that context, the choice is between a
function declaration with a redundant set of parentheses around a
parameter name and an object declaration with a function-style cast as
the initializer. Just as for the ambiguities mentioned in
_stmt.ambig_, the resolution is to consider any construct that could
possibly be a declaration a declaration. [Note: a declaration can be
explicitly disambiguated by a nonfunction-style cast, by a = to indi-
cate initialization or by removing the redundant parentheses around
the parameter name. ] [Example:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
--end example]
2 The ambiguity arising from the similarity between a function-style
cast and a type-id can occur in different contexts. The ambiguity
appears as a choice between a function-style cast expression and a
declaration of a type. The resolution is that any construct that
could possibly be a type-id in its syntactic context shall be consid-
ered a type-id.
3 [Example:
#include <cstddef>
char *p;
void *operator new(size_t, int);
void foo() {
const int x = 63;
new (int(*p)) int; // new-placement expression
new (int(*[x])); // new type-id
}
4 For another example,
template <class T>
struct S {
T *p;
};
S<int()> x; // type-id
S<int(1)> y; // expression (ill-formed)
5 For another example,
void foo()
{
sizeof(int(1)); // expression
sizeof(int()); // type-id (ill-formed)
}
6 For another example,
void foo()
{
(int(1)); // expression
(int())1; // type-id (ill-formed)
}
--end example]
7 Another ambiguity arises in a parameter-declaration-clause of a func-
tion declaration, or in a type-id that is the operand of a sizeof or
typeid operator, when a type-name is nested in parentheses. In this
case, the choice is between the declaration of a parameter of type
pointer to function and the declaration of a parameter with redundant
parentheses around the declarator-id. The resolution is to consider
the type-name as a simple-type-specifier rather than a declarator-id.
[Example:
class C { };
void f(int(C)) { } // void f(int (*fp)(C c)) { }
// not: void f(int C);
int g(C);
void foo() {
f(1); // error: cannot convert 1 to function ptr
f(g); // OK
}
For another example,
class C { };
void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
// not: void h(int *C[10]);
--end example]
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/2/2005 7:47:03 PM
|
|
We had a conversation on just this very topic on comp.compilers just
recently (lanugages that are hard to parse). In it I criticized
exactly one facet of the declaration syntax that I thought would have
been avoided by taking the conflict messages of yacc seriously.
However, Dr Stroustrup pointed out that at the time he was first
implementing C++, it was not known how to parse the current dialect of
C using LR techniques. Thus, the grammar he began with was simplified
to exclude the parsing problems that were then unsolved. Doing so
allowed him to introduce new conflicts (that were undetected in his
subset grammar) that are problems to this day, without his being
adequately warned by the tool in question.
Unfortunately, since C++ was broken with respect to LL/LR compilaton
from that early point, (The existence of hand-written recursive
descent compilers, does not imply the ability of the language to be
parsed LL, as hand-written compilers can be written "ad hack" and use
the full (Turing) power of the host programming language.) later
language extenders (i.e. those adding templates) have also falled into
similar traps. I think it would have been unlikely that a language
designer with a working lexer and LR (or LL) parser for C++
pre-templates, would have added templates in exactly the syntax
proposed. In particular, they would not have added in the >> problem
for closing templates.
However, this is just my own issue.
As to C++, it is most certainly the PL/I of our times. And, just like
PL/I there are many usable dialects within it.
|
|
0
|
|
|
|
Reply
|
cfc (231)
|
6/2/2005 8:04:15 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> |
> | > Furthermore, as has being pointed out, the "many deficits" of C++
> | > listed here have been made based on misunderstanding of what they are
> | > and where they came from. Someone insisted on syntax and "typename"
> | > issue without quite understanding that it was a problem inherited from
> | > C, as opposed to a problem introduced by templates.
> |
> | The fact that it is inherited from C *is* the problem. (I don't care
> | "where it came from". If it is bad, it is bad.)
> | You seem to suggest that something becomes better if we understand why
> | it came to be so bad. I reject that view.
>
> I did not suggest that, so you may reject view that and that is fine;
> don't say I suggested it.
Then what's the point in reviewing the history of how C++ came to be
the way it is? I don't care about the history. I see the result, and
I see that it is bad.
> | > In fact, I've found that working on C++ is more challenging than, say,
> | > working on ML variants or Haskell -- not that those languages do not
> | > provide opportunities for intellectual excitements.
> |
> | Teaching calculus to dogs is also far more challenging than teaching
> | it to humans.
>
> That is an interesting observation.
>
> | Should we enroll dogs in math courses, for the
> | challenge's sake?
>
> I think the idea may worth consideration, in particular if someone
> like you were part of the class. The challengce might not necessarily
> from come where one might think.
Thank you. Consider the compliment reciprocated.
> [...]
>
> | > Yes, I guess if those people spent their talents on SML/NJ it would
> | > not be waste.
> |
> | Spending one's efforts on one particular implementation (or even just
> | one particular language) only is probably going to be a waste unless
> | lessons can be learned that "survive". Lessons from ML will certainly
> | survive.
>
> And of course, lessons from ML will survive but not from C++; and this
> is because you've looked enough into C++ problems to state that.
Lessons from C++ will survive, mostly in the form of "don't make the
following mistake: ...".
> | Did I say even one word about "angle brackets, bananas, curly-braces
> | and dot-notations"?
>
> those are my words for "syntax".
I don't think I said anything about syntax either.
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/2/2005 8:17:44 PM
|
|
Chris F Clark <cfc@shell01.TheWorld.com> writes:
> We had a conversation on just this very topic on comp.compilers just
> recently (lanugages that are hard to parse).
Perl is probably even harder to parse than C++, considering its
lexical structure (the grammar is not that bad).
Some of its rules are not defined by documentation but by code which
looks like this (perl-5.8.5/toke.c):
/* S_intuit_more
* Returns TRUE if there's more to the expression (e.g., a subscript),
* FALSE otherwise.
*
* It deals with "$foo[3]" and /$foo[3]/ and /$foo[0123456789$]+/
*
* ->[ and ->{ return TRUE
* { and [ outside a pattern are always subscripts, so return TRUE
* if we're outside a pattern and it's not { or [, then return FALSE
* if we're in a pattern and the first char is a {
* {4,5} (any digits around the comma) returns FALSE
* if we're in a pattern and the first char is a [
* [] returns FALSE
* [SOMETHING] has a funky algorithm to decide whether it's a
* character class or not. It has to deal with things like
* /$foo[-3]/ and /$foo[$bar]/ as well as /$foo[$\d]+/
* anything else returns TRUE
*/
/* This is the one truly awful dwimmer necessary to conflate C and sed. */
STATIC int
S_intuit_more(pTHX_ register char *s)
{
if (PL_lex_brackets)
return TRUE;
if (*s == '-' && s[1] == '>' && (s[2] == '[' || s[2] == '{'))
return TRUE;
if (*s != '{' && *s != '[')
return FALSE;
if (!PL_lex_inpat)
return TRUE;
/* In a pattern, so maybe we have {n,m}. */
if (*s == '{') {
s++;
if (!isDIGIT(*s))
return TRUE;
while (isDIGIT(*s))
s++;
if (*s == ',')
s++;
while (isDIGIT(*s))
s++;
if (*s == '}')
return FALSE;
return TRUE;
}
/* On the other hand, maybe we have a character class */
s++;
if (*s == ']' || *s == '^')
return FALSE;
else {
/* this is terrifying, and it works */
int weight = 2; /* let's weigh the evidence */
char seen[256];
unsigned char un_char = 255, last_un_char;
char *send = strchr(s,']');
char tmpbuf[sizeof PL_tokenbuf * 4];
if (!send) /* has to be an expression */
return TRUE;
Zero(seen,256,char);
if (*s == '$')
weight -= 3;
else if (isDIGIT(*s)) {
if (s[1] != ']') {
if (isDIGIT(s[1]) && s[2] == ']')
weight -= 10;
}
else
weight -= 100;
}
for (; s < send; s++) {
last_un_char = un_char;
un_char = (unsigned char)*s;
switch (*s) {
case '@':
case '&':
case '$':
weight -= seen[un_char] * 10;
if (isALNUM_lazy_if(s+1,UTF)) {
scan_ident(s, send, tmpbuf, sizeof tmpbuf, FALSE);
if ((int)strlen(tmpbuf) > 1 && gv_fetchpv(tmpbuf,FALSE, SVt_PV))
weight -= 100;
else
weight -= 10;
}
else if (*s == '$' && s[1] &&
strchr("[#!%*<>()-=",s[1])) {
if (/*{*/ strchr("])} =",s[2]))
weight -= 10;
else
weight -= 1;
}
break;
case '\\':
un_char = 254;
if (s[1]) {
if (strchr("wds]",s[1]))
weight += 100;
else if (seen['\''] || seen['"'])
weight += 1;
else if (strchr("rnftbxcav",s[1]))
weight += 40;
else if (isDIGIT(s[1])) {
weight += 40;
while (s[1] && isDIGIT(s[1]))
s++;
}
}
else
weight += 100;
break;
case '-':
if (s[1] == '\\')
weight += 50;
if (strchr("aA01! ",last_un_char))
weight += 30;
if (strchr("zZ79~",s[1]))
weight += 30;
if (last_un_char == 255 && (isDIGIT(s[1]) || s[1] == '$'))
weight -= 5; /* cope with negative subscript */
break;
default:
if (!isALNUM(last_un_char) && !strchr("$@&",last_un_char) &&
isALPHA(*s) && s[1] && isALPHA(s[1])) {
char *d = tmpbuf;
while (isALPHA(*s))
*d++ = *s++;
*d = '\0';
if (keyword(tmpbuf, d - tmpbuf))
weight -= 150;
}
if (un_char == last_un_char + 1)
weight += 5;
weight -= seen[un_char];
break;
}
seen[un_char]++;
}
if (weight >= 0) /* probably a character class */
return FALSE;
}
return TRUE;
}
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/2/2005 9:08:33 PM
|
|
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > | > Symbol table information is required to distinguish between template
| > | > parameters and less-than operator though. Parsing C++ requires full
| > | > typechecking, including name resolution, overloading resolution,
| > | > template instantiation, and evaluation of constant expressions.
| >
| > Parsing C++ does not require template instantiation, nor overload
| > resolutions, nor full typechecking.
|
| C++ parser needs to know which names are types, and which names are
| templates. For qualified names like C<T>::name this requires template
| instantiation and matching template specializations.
The premisses are right, but the conclusion is Wrong. No template
instantiation is required in order to parse template definitions.
Consider the following:
template<class C> void f(C c)
{
typename C::template rebind<int>::other t;
}
It basically contains all the ingredients you did not understand.
[ snipping of passage not supporting the claim made ]
[...]
| template <class T>
| struct S {
| T *p;
| };
| S<int()> x; // type-id
| S<int(1)> y; // expression (ill-formed)
But, this does not require instantiation of template before parsing.
|
| 5 For another example,
| void foo()
| {
| sizeof(int(1)); // expression
| sizeof(int()); // type-id (ill-formed)
| }
This has nothing to do with your claim.
| 6 For another example,
| void foo()
| {
| (int(1)); // expression
| (int())1; // type-id (ill-formed)
| }
Neither this.
I appreciate that you went through the trouble of looking at a draft,
but it would been better if the quote actually supported the claim you
made. I gave an example above. Could you tell me, in your view, which
template should be instantiated before parsing the function definition?
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/2/2005 11:17:32 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> The premisses are right, but the conclusion is Wrong. No template
> instantiation is required in order to parse template definitions.
It's required to parse definitions even not occurring in templates, as
long as they don't depend on a template parameter of a template we are in.
From what you have snipped:
3 The disambiguation is purely syntactic; that is, the meaning of the
names occurring in such a statement, beyond whether they are type-
names or not, is not generally used in or changed by the disambigua-
tion. Class templates are instantiated as necessary to determine if a
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
qualified name is a type-name. Disambiguation precedes parsing, and a
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
statement disambiguated as a declaration may be an ill-formed declara-
tion. If, during parsing, a name in a template parameter is bound
differently than it would be bound during a trial parse, the program
is ill-formed. No diagnostic is required. [Note: This can occur only
when the name is declared earlier in the declaration. ]
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/3/2005 4:52:14 AM
|
|
Gabriel Dos Reis wrote:
>
> I don't know how much of determined distorsion it takes to make
> the above statement, when the author said (page 45):
>
> Could I have "fixed" the most annoying deficiencies of the C syntax
> and semantics at some point before C++ was made pubically
> available? Could I have done so without removing useful features
> (to C with Classes' users in their environments -- as opposed to an
> idea world) or introducing incompatibilities that were unacceptable
> to C programmers wanting to migrate to C with Classes? I think
> not. In some cases, I tried, but I backed out my changes after
> complaints from outraged users.
So? Since when are individual outraged users a suitable criterion for
judging good language design? Any bit of progress will always outrage
somebody. C++ probably would have many less "outraged" or annoyed users
today if he had chosen to wisely ignore such voices at the right times.
Even if he had no choice, as he claims: that he couldn't do better does
not imply that the result is a good language. You see, I find your line
of argument really strange. Somebody says "this is bad" and you
continuously reply "no, because it was designed under that constraint".
That's a non-sequitur.
> Again, from facts, he did not abandon the YACC parser.
Reread the paragraph, he did. Later ("to this day") he returned to it,
but only with "much lexical trickery relying on recursive descent
techniques". That's not good enough, and it was too late by then: some
of the posts and examples in this thread undoubtedly show that something
had gone terribly wrong already.
And it's no excuse that there was no working C parser at the time -
before I start throwing huge piles of extensions at something, I should
fix the core if that turns out to be necessary - everything else is not
design but hackery.
I better drop out of this thread now before it gets too heated-up...
- Andreas
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
6/3/2005 10:08:18 AM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| Gabriel Dos Reis wrote:
| > I don't know how much of determined distorsion it takes to make
| > the above statement, when the author said (page 45):
| > Could I have "fixed" the most annoying deficiencies of the C
| > syntax
| > and semantics at some point before C++ was made pubically
| > available? Could I have done so without removing useful features
| > (to C with Classes' users in their environments -- as opposed to an
| > idea world) or introducing incompatibilities that were unacceptable
| > to C programmers wanting to migrate to C with Classes? I think
| > not. In some cases, I tried, but I backed out my changes after
| > complaints from outraged users.
|
| So?
Just facts. But, you do not seem to like facts, especially those that
would expose the fiction in your claims. You claimed:
instead of realizing that the syntax design was broken
and I'm pointing out that, the author did know (at the time) and write
about it several times and explains the reason of why he could not
have done the cleanup he wanted, in the real world of the language
users (as opposed to an imaginary perfect world).
Your reasoning is quite singular. Each time you make claims that do
not match reality and you're put before facts and realized that, well,
you should really have checked reality before making the claims your made
you just turn to make another false claims. When you seem to have
exhausted the list of false claims you could make, it is now because
the people you're crediting of fictionary facts were just ignorant.
And this whole discussion started with a distorted report of yours,
and you went on worse and worse.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/3/2005 12:39:28 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
>
> | Gabriel Dos Reis wrote:
> | > I don't know how much of determined distorsion it takes to make
> | > the above statement, when the author said (page 45):
> | > Could I have "fixed" the most annoying deficiencies of the C
> | > syntax
> | > and semantics at some point before C++ was made pubically
> | > available? Could I have done so without removing useful features
> | > (to C with Classes' users in their environments -- as opposed to an
> | > idea world) or introducing incompatibilities that were unacceptable
> | > to C programmers wanting to migrate to C with Classes? I think
> | > not. In some cases, I tried, but I backed out my changes after
> | > complaints from outraged users.
> |
> | So?
>
> Just facts. But, you do not seem to like facts, especially those that
> would expose the fiction in your claims. You claimed:
>
> instead of realizing that the syntax design was broken
>
> and I'm pointing out that, the author did know (at the time) and write
> about it several times and explains the reason of why he could not
> have done the cleanup he wanted, in the real world of the language
> users (as opposed to an imaginary perfect world).
Actually, Stroustrup merely *claims* that he could not have done the
cleanup. He obviously could have -- at the expense of annoying some
users. As Andreas said, *any* language change *always* annoys
someone, and it was extremely unwise of Stroustrup to listen to those
particular voices. I know for a fact that there were other people
around him at the time who hated C++'s design from the beginning. Why
did he not listen to those people?
> Your reasoning is quite singular. Each time you make claims that do
> not match reality and you're put before facts and realized that, well,
> you should really have checked reality before making the claims your made
> you just turn to make another false claims.
The fact that he wrote so in his books does not prove that he really
knew the design was bad at the time he did it. Perfect hindsight can
be wonderful thing. But I don't know what he really knew at the time
either, and it isn't really the point anyway.
So let's suppose he _did_ know that his design was awful back
then... Isn't that even worse? Botching something because one does
not know better can at least be excused by ignorance. Again, those
"outraged users" are *not* an excuse.
> When you seem to have
> exhausted the list of false claims you could make, it is now because
> the people you're crediting of fictionary facts were just ignorant.
What "list"? The only claim of Andreas that you seem to be hung up on
is the claim of ignorance on Bjarne's part. What other "false claims"
did Andreas make according to you?
> And this whole discussion started with a distorted report of yours,
> and you went on worse and worse.
I just looked it up. The discussion did not start with anything
Andreas did, so here is a distorted fact for you. And, as far as I
can tell, the first contribution of Andreas to this (already ongoning
thread) was pretty accurate.
Matthias
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/3/2005 1:01:05 PM
|
|
Gabriel Dos Reis wrote:
>
> Just facts. But, you do not seem to like facts, especially those that
> would expose the fiction in your claims.
Sorry, but I think I have made sufficiently clear why most of the facts
you brought don't address any of the criticism. Also, I don't readily
take everything claimed in some book as "fact".
> You claimed:
>
> instead of realizing that the syntax design was broken
>
> and I'm pointing out that, the author did know (at the time) and write
> about it several times and explains the reason of why he could not
> have done the cleanup he wanted, in the real world of the language
> users (as opposed to an imaginary perfect world).
He realized that there was a problem. But obvious "fact" is, that he
either didn't realize the extent of it, or consciously decided to ignore
the well-established insight that a language designed with such problems
is doomed to break (which was my claim regarding syntax design). And
that C++ syntax broke horribly is also undeniable "fact".
I don't even blame anybody personally. I just conclude from this (and
all the other problems the language has) that the early C++ gurus'
expertise in language design was, at least back then, limited.
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
6/3/2005 1:13:39 PM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
[...]
| > And this whole discussion started with a distorted report of yours,
| > and you went on worse and worse.
|
| I just looked it up. The discussion did not start with anything
| Andreas did, so here is a distorted fact for you.
That lead to the addition of ad-hoc mechanisms for template
"export" and explicit instantiation (effectively moving it towards the
other model), but as of today, they still not solve these problems
satisfactory, as far as I am aware of it.
and see the answer in <m3br6yyz22.fsf@uniton.integrable-solutions.net>.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/3/2005 6:01:22 PM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
| Gabriel Dos Reis wrote:
| > Just facts. But, you do not seem to like facts, especially those that
| > would expose the fiction in your claims.
|
| Sorry, but I think I have made sufficiently clear why most of the
| facts you brought don't address any of the criticism.
You denied evidence, that for sure. You claimed he did not realize
that the syntax was broken -- but you decided to ignore the fact that
he recognized very early that the syntax he inherited from C was
aproblem and tried to fix it. You claimed that he ignored everybody's
else adive and abandon YACC -- while what he did was actually go and
ask the experts and took their advices and did not abandon YACC.
You claimed Algol was a grandiose improvment over PL/I -- which causes
a time travel problem.
The other claim, you constantly made was that you don't like C++. That
is a taste matter, and most certainly that is hardly argued with
with facts, and I did not do that.
| Also, I don't readily take everything claimed in some book as "fact".
I can understand that -- though it looks like, you don't hesitate to
argue with "recalling next paragraph" until it is produced and don't
support your claim.
It is not just "some book". Those involved in C and C++, and those
also hating C++, have had long to verify the report. That certainly
provide for far better evidence than the claims you've made so far.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/3/2005 6:30:30 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> You claimed Algol was a grandiose improvment over PL/I -- which causes
> a time travel problem.
So you're quibbling with Hoare here? After all, this is a fairly
famous quote!
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/3/2005 6:46:07 PM
|
|
Gabriel Dos Reis wrote:
> ...
> Just facts. But, you do not seem to like facts, especially those that
> would expose the fiction in your claims. You claimed:
>
> instead of realizing that the syntax design was broken
>
> and I'm pointing out that, the author did know (at the time) and write
> about it several times and explains the reason of why he could not
> have done the cleanup he wanted, in the real world of the language
> users (as opposed to an imaginary perfect world).
so if you start with something that is broken, realize it, but decide
you can't change the brokenness because of some constraints, the result
is not broken?
> ...
hs
|
|
0
|
|
|
|
Reply
|
hs60 (77)
|
6/3/2005 11:46:43 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Hartmann Schaffer <hs@hartmann.schaffernet> writes:
>
> | Gabriel Dos Reis wrote:
> | > ...
> | > Just facts. But, you do not seem to like facts, especially those that
> | > would expose the fiction in your claims. You claimed:
> | > instead of realizing that the syntax design was broken
> | > and I'm pointing out that, the author did know (at the time) and
> | > write
> | > about it several times and explains the reason of why he could not
> | > have done the cleanup he wanted, in the real world of the language
> | > users (as opposed to an imaginary perfect world).
> |
> | so if you start with something that is broken, realize it, but decide
> | you can't change the brokenness because of some constraints, the
> | result is not broken?
>
> I don't think "brokenness" is a universal, absolute notion.
I am not interested in any definition of "brokenness" (of programming
languages) according to which C++ is not broken.
The discussion here (especially the one you had with Marcin) was quite
telling. If even experts have a fight over deciding whether parsing
requires template instantiation (regardless of what the true answer to
this question might be -- I frankly don't care), then something is
very, very wrong. The excerpts from the draft hat Marcin posted are
absolutely mind-boggling! It reads like tax law, for crying out loud!
I thought I knew C++ was bad. But I was actually wrong about this.
The truth is that C++ is an absolute nightmare!
> What some people consider broken -- say Scheme, SML, Haskell, C++ --
> may be considered not broken by others.
All these languages are, indeed, "broken" to some degree. There are
excellent analyses available. One of the most thorough ones for the
case of SML was written by your dear friend Andreas Rossberg, btw.
So, now that we have this out of the way, what remains to be
considered is the degree of brokenness. And C++ stands out in this
regard.
> Furthermore, other people may consider "brokenness" in the context
> of how the thing was made and the constraints.
Some people clearly do that. However, this approach is, IMNSHO, to be
thoroughly rejected. If something is broken it is broken. Period.
> And I believe that for programming languages, the consideration of
> contexts offer better insights into getting a judgment.
> However, I also understand that some people prefer or
> decide to be ignorant of history and the facts.
Nobody should be ignorant of the facts. However, being ignorant of
certain some "facts" is not really a problem in those cases where
these "facts" have nothing to do with the judgment one is trying to
make. Nobody needs to know the history of C++ to understand that it
is a disaster.
Historical context is merely helpful in understanding, well, history:
how and why something became as bad as it is. It does /absolutely/
/nothing/ in terms of changing the verdict.
> To take your question at the other end, so if you start with something
> that is broken, realize it, but decide you can't change *all* the
> brokenness because of some constraints, can the result still be an
> improvement?
Maybe, it depends on the concrete situation. Anyway, it is not clear
that C++ even is one of the cases that fit the above scenario. It was
Stroustrup's personal opinion that he was bound by those constraints
that he keeps listing in his books. But there is no proof that that
these contraints existed objectively. We can't rewind history and see
what would have happened if he had ignored the voices of those who
readily equate PL design decisions with a philosophy that has resulted
in some of the worst crimes of humanity. (If someone calls a language
design "fascist", I stop listening to that person.)
Fixing the problems inherited from C early on might have resulted in a
language even more popular than the current C++. It is hard to tell.
Not hard to tell is that doing so wouldn't have resulted in a language
technically superior to the current C++.
Those so-called "improvements" that were made to C++ over the years,
btw., have only compounded the problems. Ultimately, C++'s problem is
its gratuitous complexity. And that cannot be cured without
simplifying. Yet, during the evolution of C++ nothing has been
simplified, and additional complexity has been added.
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/4/2005 2:25:15 AM
|
|
Hartmann Schaffer <hs@hartmann.schaffernet> writes:
| Gabriel Dos Reis wrote:
| > ...
| > Just facts. But, you do not seem to like facts, especially those that
| > would expose the fiction in your claims. You claimed:
| > instead of realizing that the syntax design was broken
| > and I'm pointing out that, the author did know (at the time) and
| > write
| > about it several times and explains the reason of why he could not
| > have done the cleanup he wanted, in the real world of the language
| > users (as opposed to an imaginary perfect world).
|
| so if you start with something that is broken, realize it, but decide
| you can't change the brokenness because of some constraints, the
| result is not broken?
I don't think "brokenness" is a universal, absolute notion. What
some people consider broken -- say Scheme, SML, Haskell, C++ -- may be
considered not broken by others. Furthermore, other people may
consider "brokenness" in the context of how the thing was made
and the constraints. And I believe that for programming languages,
the consideration of contexts offer better insights into getting a
judgment. However, I also understand that some people prefer or
decide to be ignorant of history and the facts.
To take your question at the other end, so if you start with something
that is broken, realize it, but decide you can't change *all* the
brokenness because of some constraints, can the result still be an
improvement?
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/4/2005 2:44:47 AM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> | > I don't think "brokenness" is a universal, absolute notion.
> |
> | I am not interested in any definition of "brokenness" (of programming
> | languages) according to which C++ is not broken.
>
> so, you want to take "C++ is broken" as an axiom. No matter what.
> It is more than religion.
No. Of course, I realize that you are in denial and don't want to
understand, but here it goes anyway:
The point is that I have a certain value system which I use to judge
whether a language design is broken or not. According to this system,
C++ is (badly) broken. That's not an axiom, it is an observation.
Now, I realize that other people have different value systems, so they
will make judgments differently. However, systems that are reasonably
"close" to each other would at least lead to similar conclusions.
Given how low C++ ranks in /my/ system, any /other/ system where it
ranks highly must be /very/ far from mine. In fact, so far that I
have a hard time conducting a meaningful exchange of opinions on
language design matters with anyone who uses such a radically
different system.
The two of us are currently demonstrating this phenomenon to the
world.
I confess that it is incomprehesible to me how anyone could possibly
think of C++ as a well-designed programming language.
> [...]
>
> | in some of the worst crimes of humanity. (If someone calls a language
> | design "fascist", I stop listening to that person.)
>
> And which language have you designed?
1. What does that have to do with anything?
2. A few, but certainly not something as "substantial" as C++.
One example is here:
http://www.ttic.org/blume/papers/tame-ixp.pdf
In a strange twist of fate, a substantial portion of this work was
carried out while I occupied Bjarne's old office at Bell Labs... :-)
Cheers,
Matthias
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/4/2005 4:35:38 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
> One example is here:
> http://www.ttic.org/blume/papers/tame-ixp.pdf
Oops, there is a hyphen missing. This should have been:
http://www.tti-c.org/blume/papers/tame-ixp.pdf
Matthias
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/4/2005 4:48:01 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Hartmann Schaffer <hs@hartmann.schaffernet> writes:
| >
| > | Gabriel Dos Reis wrote:
| > | > ...
| > | > Just facts. But, you do not seem to like facts, especially those that
| > | > would expose the fiction in your claims. You claimed:
| > | > instead of realizing that the syntax design was broken
| > | > and I'm pointing out that, the author did know (at the time) and
| > | > write
| > | > about it several times and explains the reason of why he could not
| > | > have done the cleanup he wanted, in the real world of the language
| > | > users (as opposed to an imaginary perfect world).
| > |
| > | so if you start with something that is broken, realize it, but decide
| > | you can't change the brokenness because of some constraints, the
| > | result is not broken?
| >
| > I don't think "brokenness" is a universal, absolute notion.
|
| I am not interested in any definition of "brokenness" (of programming
| languages) according to which C++ is not broken.
so, you want to take "C++ is broken" as an axiom. No matter what.
It is more than religion.
[...]
| in some of the worst crimes of humanity. (If someone calls a language
| design "fascist", I stop listening to that person.)
And which language have you designed?
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/4/2005 5:14:40 AM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> | Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> |
> | > | > I don't think "brokenness" is a universal, absolute notion.
> | > |
> | > | I am not interested in any definition of "brokenness" (of programming
> | > | languages) according to which C++ is not broken.
> | >
> | > so, you want to take "C++ is broken" as an axiom. No matter what.
> | > It is more than religion.
> |
> | No. Of course, I realize that you are in denial and don't want to
> | understand, but here it goes anyway:
>
> No, you got it wrong. I understand people can have strong opinions.
> In your case, it goes beyond that. You have taken something to be an
> axiom. That is not me being in denial.
If you say so... (How come you can read my mind?)
> [...]
>
> | In fact, so far that I
> | have a hard time conducting a meaningful exchange of opinions on
> | language design matters with anyone who uses such a radically
> | different system.
>
> You never pose and ask yourself whether your system is broken, if I
> may borrow words from you?
I do. Of course, my system is based on my experience. I have
programmed in many languages, I have implemented several languages, I
have designed some languages. I think this has given me some
background in judging language designs.
Of course, there is a small probability that I am totally off base,
and that C++ is the design to end all design. But this seems somewhat
unlikely. My views on what is good design has changed many times over
the years, but as far as C++ is concerned, the trend was a simple one:
the more experience I gained, the less I could stand it.
> [...]
>
> | > | in some of the worst crimes of humanity. (If someone calls a language
> | > | design "fascist", I stop listening to that person.)
> | >
> | > And which language have you designed?
> |
> | 1. What does that have to do with anything?
>
> When someone has such interesting opinions as you offer here about what a
> programming language, its design and relation to users should be, I say
> "woaw, that is interesting!
So you had never heard this before from others?!? Now it's upon me to
say "whoa!"
> Is this pure theology or is there any
> thing concrete I can look at to see how he does things himself and
> what they look like?". But, I was not expecting you to react that way
> (or more precisely I guessed, but I thought you were too smart to go
> that way).
Sorry, but you are being too cryptic for me here. What are you trying
to say?
> | One example is here:
> | http://www.ttic.org/blume/papers/tame-ixp.pdf
>
> Maybe, I should have mentioned I already knew about that one and
> others you published about.
Good. Then why did you ask?
> In case you're wondering, the question was not facetious. I thought
> you made something I missed, that obviously demonstrate how things
> should be in your system and I wanted to see what impact they have on
> the rest of computer science and the world. Those were genuine interests.
Why do /I/ have to make something that demonstrates how things should
be in my opinion? There are perfectly good language designs out there
which come close enough. In fact, few languages fare worse than C++
in "my system". (And no, that's not because "C++ is bad" is an axiom.)
> (And very recently, when someone from your "previous" team came to visit
> us, I naturally took news about your recent work :-))
Again, you are being too vague. Which recent work are you referring
to exactly? What "previous" team are you talking about?
> | In a strange twist of fate, a substantial portion of this work was
> | carried out while I occupied Bjarne's old office at Bell Labs... :-)
>
> As they say in French, � L'habit ne fait pas le moine. � (I hope
> someone will translate.)
Yeah, I was relying on this sort of wisdom when I trusted that nothing
would rub off. :-)
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/4/2005 5:35:54 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > | > I don't think "brokenness" is a universal, absolute notion.
| > |
| > | I am not interested in any definition of "brokenness" (of programming
| > | languages) according to which C++ is not broken.
| >
| > so, you want to take "C++ is broken" as an axiom. No matter what.
| > It is more than religion.
|
| No. Of course, I realize that you are in denial and don't want to
| understand, but here it goes anyway:
No, you got it wrong. I understand people can have strong opinions.
In your case, it goes beyond that. You have taken something to be an
axiom. That is not me being in denial.
[...]
| In fact, so far that I
| have a hard time conducting a meaningful exchange of opinions on
| language design matters with anyone who uses such a radically
| different system.
You never pose and ask yourself whether your system is broken, if I
may borrow words from you?
[...]
| > | in some of the worst crimes of humanity. (If someone calls a language
| > | design "fascist", I stop listening to that person.)
| >
| > And which language have you designed?
|
| 1. What does that have to do with anything?
When someone has such interesting opinions as you offer here about what a
programming language, its design and relation to users should be, I say
"woaw, that is interesting! Is this pure theology or is there any
thing concrete I can look at to see how he does things himself and
what they look like?". But, I was not expecting you to react that way
(or more precisely I guessed, but I thought you were too smart to go
that way).
| 2. A few, but certainly not something as "substantial" as C++.
Ah, I see.
| One example is here:
| http://www.ttic.org/blume/papers/tame-ixp.pdf
Maybe, I should have mentioned I already knew about that one and
others you published about.
In case you're wondering, the question was not facetious. I thought
you made something I missed, that obviously demonstrate how things
should be in your system and I wanted to see what impact they have on
the rest of computer science and the world. Those were genuine interests.
(And very recently, when someone from your "previous" team came to visit
us, I naturally took news about your recent work :-))
| In a strange twist of fate, a substantial portion of this work was
| carried out while I occupied Bjarne's old office at Bell Labs... :-)
As they say in French, � L'habit ne fait pas le moine. � (I hope
someone will translate.)
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/4/2005 6:13:50 AM
|
|
* Gabriel Dos Reis:
> The premisses are right, but the conclusion is Wrong. No template
> instantiation is required in order to parse template definitions.
>
> Consider the following:
>
> template<class C> void f(C c)
> {
> typename C::template rebind<int>::other t;
> }
>
> It basically contains all the ingredients you did not understand.
I think he isn't after template definitions, but non-template code
which instantiated templates. No typename/template annotations are
required in this case, so the compiler must in fact instantiate the
template before it can make a decision.
|
|
0
|
|
|
|
Reply
|
fw12 (435)
|
6/4/2005 8:37:20 AM
|
|
Florian Weimer <fw@deneb.enyo.de> writes:
> I think he isn't after template definitions, but non-template code
> which instantiated templates. No typename/template annotations are
> required in this case,
Actually they are forbidden outside templates.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/4/2005 9:33:16 AM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
[...]
| > | In fact, so far that I
| > | have a hard time conducting a meaningful exchange of opinions on
| > | language design matters with anyone who uses such a radically
| > | different system.
| >
| > You never pose and ask yourself whether your system is broken, if I
| > may borrow words from you?
|
| I do. Of course, my system is based on my experience. I have
| programmed in many languages, I have implemented several languages, I
| have designed some languages.
The point was not whether you designed some languages. But whether
you designed a language that had sufficient impact on computer science
and the world, and how your system worked out when confronted with the
reality of the word (as opposed to an abstract one). I'm merely
trying to differentiate claims from someone who would have designed toy
languages that have little impact, from someone who would actually
have done something substantial. Say differently, I'm trying to
differentiate arm-chair designers from real practitioners.
| I think this has given me some
| background in judging language designs.
|
| Of course, there is a small probability that I am totally off base,
| and that C++ is the design to end all design.
You missed the point, because that was not the claim.
[...]
| > | > | in some of the worst crimes of humanity. (If someone calls a language
| > | > | design "fascist", I stop listening to that person.)
| > | >
| > | > And which language have you designed?
| > |
| > | 1. What does that have to do with anything?
| >
| > When someone has such interesting opinions as you offer here about what a
| > programming language, its design and relation to users should be, I say
| > "woaw, that is interesting!
|
| So you had never heard this before from others?!?
Sure I did and do from time to time. But then, I always try to see
whether their authors are simply arrogant, or arm-chair designers, or
real practitioners.
| Now it's upon me to say "whoa!"
|
| > Is this pure theology or is there any
| > thing concrete I can look at to see how he does things himself and
| > what they look like?". But, I was not expecting you to react that way
| > (or more precisely I guessed, but I thought you were too smart to go
| > that way).
|
| Sorry, but you are being too cryptic for me here. What are you trying
| to say?
|
| > | One example is here:
| > | http://www.ttic.org/blume/papers/tame-ixp.pdf
| >
| > Maybe, I should have mentioned I already knew about that one and
| > others you published about.
|
| Good. Then why did you ask?
the answer was in the sentences that followed.
| > In case you're wondering, the question was not facetious. I thought
| > you made something I missed, that obviously demonstrate how things
| > should be in your system and I wanted to see what impact they have on
| > the rest of computer science and the world. Those were genuine interests.
|
| Why do /I/ have to make something that demonstrates how things should
| be in my opinion?
I was not asking you to make something that dmonstrates how things
should be in your opinion. I was asking whether you had something I
could look at that shows how things should be in your system. The
answer could have been "yes". That was fine. The answer could have
been "no". That was fine too. In either case, I'd have had a
material to answer my question "is this theology, or is this something
that got confrontation with the reality?" See?
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/4/2005 2:11:54 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
>
> [...]
>
> | > | In fact, so far that I
> | > | have a hard time conducting a meaningful exchange of opinions on
> | > | language design matters with anyone who uses such a radically
> | > | different system.
> | >
> | > You never pose and ask yourself whether your system is broken, if I
> | > may borrow words from you?
> |
> | I do. Of course, my system is based on my experience. I have
> | programmed in many languages, I have implemented several languages, I
> | have designed some languages.
>
> The point was not whether you designed some languages. But whether
> you designed a language that had sufficient impact on computer science
> and the world, and how your system worked out when confronted with the
> reality of the word (as opposed to an abstract one).
Obviously you knew the answer to this one. If I had, you would
certainly have heard of it, hadn't you? So don't try to sound sincere
when you are not, ok?
> I'm merely trying to differentiate claims from someone who would
> have designed toy languages that have little impact, from someone
> who would actually have done something substantial.
Well, at least I have not done substantial damage either. As I said,
one day people will look back and marvel at how much damage C++ has
caused the (computing) world.
> Say differently, I'm trying to differentiate arm-chair designers
> from real practitioners.
Well, guilty as charged. Now, let me ask you: What languages have
/you/ designed?
> Sure I did and do from time to time. But then, I always try to see
> whether their authors are simply arrogant, or arm-chair designers, or
> real practitioners.
But even when they are arrogant and/or armchair designers, they might
just be right. And "real practitioners" can be wrong, even while
temporarily looking successful. C++ impressively demonstrates this.
> I was not asking you to make something that dmonstrates how things
> should be in your opinion. I was asking whether you had something I
> could look at that shows how things should be in your system. The
> answer could have been "yes". That was fine. The answer could have
> been "no". That was fine too. In either case, I'd have had a
> material to answer my question "is this theology, or is this something
> that got confrontation with the reality?" See?
You can go around and call this "theology" or "axiom" or whatever. I
don't care. I have nothing at stake depends in any way on C++ one way
or the other. I don't use this language, I rarely think about it, I
don't have to work with it or on it, I don't have to prove that it is
bad, I don't have to try and improve it. To have an axiom
specifically naming C++, or to have a "theology" that talks about C++
would make no sense at all for me. It just so happens that my
experience with languages have shaped my value system, and as it so
happens, C++ does not look very good in this system.
Matthias
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/4/2005 3:38:36 PM
|
|
Gabriel Dos Reis wrote:
> Hartmann Schaffer <hs@hartmann.schaffernet> writes:
>
> | Gabriel Dos Reis wrote:
> | > ...
> | > Just facts. But, you do not seem to like facts, especially those that
> | > would expose the fiction in your claims. You claimed:
> | > instead of realizing that the syntax design was broken
> | > and I'm pointing out that, the author did know (at the time) and
> | > write
> | > about it several times and explains the reason of why he could not
> | > have done the cleanup he wanted, in the real world of the language
> | > users (as opposed to an imaginary perfect world).
> |
> | so if you start with something that is broken, realize it, but decide
> | you can't change the brokenness because of some constraints, the
> | result is not broken?
>
> I don't think "brokenness" is a universal, absolute notion. What
> some people consider broken -- say Scheme, SML, Haskell, C++ -- may be
> considered not broken by others.
That doesn't make either of them right.
Besides, C++ *is* broken.
It's broken in theory: parsing is a mess, its semantics is riddled with
exceptions and special cases. I already gave constructor issues in a
recent post, and that's just the start.
It's broken according to broad consensus. It's even a common saying that
"C++ gives you not enough rope to hang yourself, but a pistol to shoot
nice large holes through your foot".
It's broken according to personal experience. I have done similar
projects in C++ and in other languages, and C++ required me to write
down details that would be handled automatically in other languages
(hence more LoC, more time to write it, more bugs), it took me more time
to look up semantic details to get the code express what I wanted it to
express, it layed traps for me that cost me hours of debugging.
By all definitions, C++ is broken. That anybody can allude that C++ may
be considered nonbroken by some people makes me seriously doubt that
person's sanity.
> Furthermore, other people may
> consider "brokenness" in the context of how the thing was made
> and the constraints.
It may be that C++ was the least broken thing that could be done under
the circumstances. I seriously doubt that, but it's entirely possible.
Still, this doesn't make C++ non-broken.
> And I believe that for programming languages,
> the consideration of contexts offer better insights into getting a
> judgment.
Judgment on Bjarne Stroustrup's language design skills is what you've
been highlighting. I'm under the impression that most people here think
that that's largely irrelevant - what we think about is the merit of the
language itself (and C++ is quite unanimously considered breakage here,
else we'd be populating comp.lang.c++ instead of comp.lang.functional).
> However, I also understand that some people prefer or
> decide to be ignorant of history and the facts.
Please, allegations don't belong into a technical discussion.
> To take your question at the other end, so if you start with something
> that is broken, realize it, but decide you can't change *all* the
> brokenness because of some constraints, can the result still be an
> improvement?
It's certainly possible to improve something bad into something
not-quite-so-bad. The question is whether the end result is good enough.
The consensus here is that changing C++ into even a reasonable language
would require so deep alterations that the result wouldn't be C++
anymore, and would be rejected for that reason. It's like polishing a
blind corner of a broken mirror - the shard certainly has improved, but
there's no way that the mirror will ever become whole again, regardless
of the skill that went into the polish.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/4/2005 5:05:05 PM
|
|
* Joachim Durchholz:
> It's broken in theory: parsing is a mess, its semantics is riddled with
> exceptions and special cases. I already gave constructor issues in a
> recent post, and that's just the start.
I was bitten by that one, too, but if you think about it, it's a
direct consequence of having true constructors and destructors. If
you always invoke the member functions in the most derived class,
you'd have partially constructed or destructed flying around, which
would be a real nightmare.
There are a few features I consider truly broken. For example, it's
not quite clear if you can portably allocate an array whose size is
determined at run time. Some choices in the syntax department turned
out to be unfortunate, but this mostly concerns implementors and not
programmers.
> It's broken according to broad consensus. It's even a common saying that
> "C++ gives you not enough rope to hang yourself, but a pistol to shoot
> nice large holes through your foot".
By this definition, most (all?) successful technology is broken.
> It's broken according to personal experience. I have done similar
> projects in C++ and in other languages, and C++ required me to write
> down details that would be handled automatically in other languages
> (hence more LoC, more time to write it, more bugs), it took me more time
> to look up semantic details to get the code express what I wanted it to
> express, it layed traps for me that cost me hours of debugging.
Usually, you are less productive when you use tools which you hate.
> By all definitions, C++ is broken. That anybody can allude that C++ may
> be considered nonbroken by some people makes me seriously doubt that
> person's sanity.
At least C++ fits reasonably well with the traditional and current
UNIX development model (separate compilation, processes are often
short-lived). There's an unfortunate mismatch in the area of I/O, but
this is probably also a quality-of-implementation issue
(sorry Gaby 8->).
|
|
0
|
|
|
|
Reply
|
fw12 (435)
|
6/4/2005 5:46:14 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> Robert A Duff wrote:
>
> > Joachim Durchholz <jo@durchholz.org> writes:
> >> * Eiffel requires garbage collection. [...] If I were to do HRT
> >> programming, I'd not use dynamic memory allocation anyway - so
> >> neither C++ nor Eiffel fit the bill :-)
> > I'm not sure why you say that. C++ can be used without dynamic
> > allocation pretty easily. I suppose Eiffel could, too, but it's
> > perhaps more painful (declare everything "expanded"?).
>
> Well, you could, but "expanded" means you don't have polymorphism.
Yeah, that's what I meant by "painful". Eiffel really wants everything
to be in the heap; the rules for "expanded" seem kind of weird to me,
and appear to be tacked on after the fact (in fact, I believe "expanded"
was not in the original version of Eiffel). Eiffel is a pretty nice
language design, but it wouldn't be my first choice for hard real time.
>... In
> other words, all the OO stuff goes out of the window, and you could just
> as well program in Ada or Modula or whatever.
Ada is a fully OO language. It does not require heap usage in order to
get run-time polymorphism, although there are many OO-style applications
that will want to use the heap for various reasons. Ada *is* used for
HRT programs -- that's what it (Ada 83) was originally design for. Ada
95 added the OO features. Many HRT applications do not use heap at all,
and many do not use run-time polymorphism, either -- but you can have
one without the other.
> I'd expect similar problems with C++ if dynamic memory allocation is
> disallowed, but I'm not familiar enough with that scenario to tell for
> sure.
I believe C++ is similar to Ada in this regard.
Neither C++ nor Ada have garbage collection, by the way, although either
can be used with Boehm's conservative GC. Also, Ada implementations
targetting the JVM or .NET have GC, because the underlying platform
does.
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
6/4/2005 5:49:08 PM
|
|
Gabriel Dos Reis wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
> | Gabriel Dos Reis wrote:
> |
> | > Joachim Durchholz <jo@durchholz.org> writes:
> | > | Gabriel Dos Reis wrote:
> | > | > But given the constraints, do you have a better solution?
> | > | > (Compiling to tuple of functions does not meet the constraints).
> | > | > We have listed what appear to us to be the most important constraints
> | > | > here:
> | > | > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1522.pdf
> | > | | Well, if being compatible with C++ is a constraint, then you
> | > pretty
> | > | much have to live with all the problems that C++ templates carry.
> | > Breaking C++ is not a luxury we have, that is a fundamental
> | > constraint.
> |
> | Well, let me utter a sacrilege... C++ is the PL/I of modern days. It's
> | trying to be everything to everyone, and adding too many ways to do
>
> Having been involved in C++ design and implementation discussions for
> some time now, what I've figured out is that for many people it is
> not doing enough. For the next version of C++, the C++ standard
> Evolution Working Group had asked for "wishlist" for improvements from
> the community. The list we got is quite long and looking over it, it
> appears that clearly C++ was not providing enough for some people.
Oh. So C++ is going to be even more bloated.
I really wish somebody would start to take away things from C++. I know
that's impossible, but I wish it were. The current language is simply
far too large, with too many obscure interactions between language
features. Adding yet another set of features will most likely just
worsen the problem (and that's what I mean if I call a language "bloated").
> But I've also heard your rant some times. The reality is that, unless
> you've been close enough (either as implementors leasting to users) or
> designers (listening to users) trying to improve over things, it is
> hard to assess the complexity and the tension between the variety of
> interests.
Been there, done that. It was just a crummy 4GL, and I was more into
design of the accompagnying libraries than the language itself, but I
have seen the trade-off nightmares, the guesswork, and general insecurity.
> Furthermore, if the primary design aim has been to design a
> beautiful language, I'm confident that C++ designers would have done a
> better job.
I don't care too much about "beauty". I care about learning curves,
amount of surprise (aka "pitfalls"), compiler reliability, and similar
things. Languages that fare well in these areas tend to have a quality
that is often described as "elegance" or "beauty", but it's a
consequence, not an aim in itself.
> | the same thing, failing to provide some key mechanisms that could
> | replace the existing ones (not that this failure is a fault of its
> | designers: they had to work with the insights that were available at
> | the time of design); with a baroque syntax and semantics that (almost)
>
> There is an account of C++ design history that I think anybody who
> wants to make serious criticisms about quirks in C++ should read. In
> particular, it has many discussions about the syntax issues in several
> paragraphs (apart from the main section �2.8 Syntax Problems).
Well, I have read that part of Bjarne's musings three times now, so
there's no need to post it again.
That the syntax is baroque is largely a C legacy, and perhaps
unavoidable. Still, there is gratuitious baroqueness in C++'s syntax,
easily demonstrated through the observation that there are several
useful C parsers available now, but _not_a_single_C++_parser_.
However, the syntax problems were just a passing note. They are quite
bad, but they pale in comparison with C++'s semantic blunders. The
language implements all the mechanisms of an OO language, but it fails
to have the accompagnying semantic concepts, so every programmer has to
manually establish things like LSP, proper virtual function linkague
during construction, and similar things. (Oh, yeah, it does have a
semantics during construction: the object under construction starts as
that of the most basic class and undergoes a set of transformation until
it arrives at the designated target class. Unfortunately, this semantic
model is Wrong with a capital W.)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/4/2005 5:50:45 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> Robert A Duff wrote:
>
> > Joachim Durchholz <jo@durchholz.org> writes:
> >
> >>However, I would have found it far better if the language had specified
> >>that no such limits are allowed (except for the obvious "limited by
> >>available memory").
> > I agree with you that compilers should not have such arbitrary limits,
> > other than those based on "available memory". But I don't see how a
> > language standard can say so. How can you write a test case that
> > determines whether the compiler obeys such a rule?
>
> Simple enough. Write a test suite that doubles any limit in
> question. Observe the compiler's memory footprint. If the memory
> footprint nears available memory, without the compiler complaining, it
> passes.
>
> Of course, a devious compiler writer could get away with arbitrary
> limits, either by providing large-enough tables or by arbitrarily
> allocating unneeded memory :-)
> ... but then I don't think anybody would do that :-))
But now you're not talking about formal requirements in a language
standard, but practical matters. Looking at memory footprints is not a
fair test, in any formal sense.
> >>>> I'm quite puzzled why C++ has such a long list of limited
> >>>> resources.
> >>>Maybe it is because you haven't seen that of C :-). See below.
> >>>(I hope they are not problem for functional programming language
> >>>implementations that generate C codes ;-))
> >>
> >>Contrary to popular belief, C is not a good portable assembler. The
> >>standard strategy for compiling FPLs nowadays seems to be machine code
> >>generation.
> > Well, C isn't *so* bad. Problems include: Lack of overflow detection.
> > No access to hardware operations like (single X single)-->double
> > integer multiply instructions. No portable and efficient way to
> > implement exception handling. Etc.
>
> No tail-call optimisation.
Good point. This is indeed a bigger issue than the ones I mentioned.
>... This is the first barrier that FPL compiler
> writers hit (exceptions and some issues with closure construction and
> other exoticities come next, but many implementors have already given up
> on C before reaching that point).
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
6/4/2005 5:57:31 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Notice that some compilers set internal characteristics, passes or
> resource limits, depending on the avaliable memory.
I'd advise compiler writers not to do that. It can cause subtle bugs
that happen to the compiler users, but can't be reproduced by the
compiler writers, which is a nightmare.
If such feature is necessary, let the user control it with command-line
switches, rather than having the compiler query the OS ("how much memory
can I have right now?).
- Bob
|
|
0
|
|
|
|
Reply
|
bobduff (1531)
|
6/4/2005 6:00:23 PM
|
|
* Joachim Durchholz:
> (Oh, yeah, it does have a
> semantics during construction: the object under construction starts as
> that of the most basic class and undergoes a set of transformation until
> it arrives at the designated target class. Unfortunately, this semantic
> model is Wrong with a capital W.)
What do you propose as an alternative? Partially constructed objects?
|
|
0
|
|
|
|
Reply
|
fw12 (435)
|
6/4/2005 6:05:26 PM
|
|
* Robert A. Duff:
> Neither C++ nor Ada have garbage collection, by the way, although either
> can be used with Boehm's conservative GC. Also, Ada implementations
> targetting the JVM or .NET have GC, because the underlying platform
> does.
But not for objects with user-defined finalization, those are never
garbage-collected. (I'm not sure what JGNAT does, but after looking
at the GC-aware parts of GNAT, I think it doesn't implement the
language semantics properly.)
|
|
0
|
|
|
|
Reply
|
fw12 (435)
|
6/4/2005 6:10:41 PM
|
|
Florian Weimer wrote:
> * Joachim Durchholz:
>
>>It's broken in theory: parsing is a mess, its semantics is riddled with
>>exceptions and special cases. I already gave constructor issues in a
>>recent post, and that's just the start.
>
> I was bitten by that one, too, but if you think about it, it's a
> direct consequence of having true constructors and destructors. If
> you always invoke the member functions in the most derived class,
> you'd have partially constructed or destructed flying around, which
> would be a real nightmare.
No, not at all.
I'm speaking from my Eiffel experience here. Eiffel's policy is: a
function is always virtual (there are exceptions). Constructors are
otherwise normal functions, and they start with an object that's
initialized to all zeros. I have written dozens if not hundreds of
classes in Eiffel, and partially constructed objects have _not_once_
been an issue.
I don't know why exactly that's not a problem. One of the patterns that
I observed in an Eiffel program is that the more complex classes with
multiple constructors tend to have a protected "basic constructor" that
establishes the class invariant and little more, and the published
constructors first call that basic constructor, then do their thing to
honor their more specific parameters.
Anyway. It's not really a problem. Those complicated initialisation
rules for C++ are dealing with a problem that simply doesn't exist.
>>It's broken according to broad consensus. It's even a common saying that
>>"C++ gives you not enough rope to hang yourself, but a pistol to shoot
>>nice large holes through your foot".
>
> By this definition, most (all?) successful technology is broken.
(Let me restrict to "programming languages in the mainstream" -
"technology" is too general here, and "successful" is a somewhat
imprecise term.)
Lisp. Python.
Admittedly, that list is depressingly short :-(
Of course, all languages have warts, including Lisp and Python. C++ is
just infinitely worse...
>>It's broken according to personal experience. I have done similar
>>projects in C++ and in other languages, and C++ required me to write
>>down details that would be handled automatically in other languages
>>(hence more LoC, more time to write it, more bugs), it took me more time
>>to look up semantic details to get the code express what I wanted it to
>>express, it layed traps for me that cost me hours of debugging.
>
> Usually, you are less productive when you use tools which you hate.
True.
On the other hand, I didn't go into C++ development with an attitude of
hate. We had a project to do, and while none of us exactly liked C++, we
all assumed it would be good enough. Which it actually was, there's no
mistake about that - but it forced us into some extra twists that we
would liked to have avoided.
I hadn't had any practical Eiffel experience before that, so my hate
isn't the typical case of a disgruntled <insert your favorite language
here> programmer who was forced into C++ - in fact I welcomed the
opportunity to get hands-on experience with C++.
That experience strengthened my distaste for C++. I had an opportunity
to go into an Eiffel job and took it. My findings were:
- All those typical problems of C++ programming (memory leaks, exception
handling issues, diamond inheritance issues, syntactic and semantic
surprises) simply vanished.
- Despite Eiffel being in the verbose tradition of Pascal Ada, Eiffel
programs are far shorter than equivalent C++ programs. Part of it is
that Eiffel has automatic garbage collection (this takes off quite a lot
of lines of code, and often simplifies the design considerably), part of
it is that Eiffel generally makes the OO mechanisms "just work" where
C++ programmers need to write explicit specifications. Also, the Eiffel
compiler automatically extracts the information that C++ programmers
must redundantly write into header files.
- Eiffel has its own set of scary problems. However, you have to look
very carefully to find them, and there are few; contrast that with C++
with its blatant and numerous scary problems.
>>By all definitions, C++ is broken. That anybody can allude that C++ may
>>be considered nonbroken by some people makes me seriously doubt that
>>person's sanity.
>
> At least C++ fits reasonably well with the traditional and current
> UNIX development model (separate compilation, processes are often
> short-lived).
OK, Eiffel's compilation model doesn't match that. You can do separate
compilation, but only if you have a special linker (or are prepared to
face really bloated binaries).
On the other hand, C++ templates are more difficult to compile
separately than generic classes in Eiffel, so I don't see that C++ has
any real advantage here.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/4/2005 8:20:08 PM
|
|
Florian Weimer wrote:
> * Joachim Durchholz:
>
>
>> (Oh, yeah, it does have a semantics during construction: the object
>> under construction starts as that of the most basic class and
>> undergoes a set of transformation until it arrives at the
>> designated target class. Unfortunately, this semantic model is
>> Wrong with a capital W.)
>
> What do you propose as an alternative? Partially constructed
> objects?
Let the object be created as a member of its target class. The
constructor is obliged to fill it with data that fulfills the class's
invariant. In particular, it's obliged to fill in enough data before
calling functions that depend on that data - but that's normal with any
kind of step-by-step initialisation.
Besides, initialisation is rarely a serious problem. Objects tend to be
in a well-known state at that time, so there aren't many cases to code
and debug for.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/4/2005 8:28:36 PM
|
|
Robert A Duff wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
>>Robert A Duff wrote:
>>
>>>[...] C++ can be used without dynamic
>>>allocation pretty easily. I suppose Eiffel could, too, but it's
>>>perhaps more painful (declare everything "expanded"?).
>>
>>Well, you could, but "expanded" means you don't have polymorphism.
>
> Yeah, that's what I meant by "painful". Eiffel really wants everything
> to be in the heap; the rules for "expanded" seem kind of weird to me,
> and appear to be tacked on after the fact (in fact, I believe "expanded"
> was not in the original version of Eiffel).
That's indeed the case.
The semantics is also dodgy. Assinging from an expanded object will
always copy it (even if it's submission as a parameter to a subroutine).
The net effect is that expanded objects are virtually useless.
The motivation behind that move was to avoid having pointers that refer
to the innards of an object (this would have broken the garbage
collector of the language inventor's implementation), so here we have
another classical case of a language that acquired design problems
because of implementation consideration.
Note that the garbage collection problems could have been solved in an
instand by simply adopting the existing, open-source Boehm-Demers-Weiser
collector (that implementation compiled to C anyway, so it would have
been a perfect match).
> Eiffel is a pretty nice language design,
Um, well, Eiffel has some extremely good design decisions. It also has
some incredibly bad ones.
It would be easy to design a "better Eiffel". Just reverse some of the
more recent design decisions :-)
(Implementing it would be another story. I actually started work on such
a project, but found it would be more work than I liked, and I also
found that some problems in statically-typed OO were essentially
unsolvable anyway - that's why I'm here in comp.lang.functional.)
> but it wouldn't be my first choice for hard real time.
Nor mine :-)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/4/2005 8:46:17 PM
|
|
Matthias Blume <find@my.address.elsewhere> writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
|
| > Matthias Blume <find@my.address.elsewhere> writes:
| >
| > [...]
| >
| > | > | In fact, so far that I
| > | > | have a hard time conducting a meaningful exchange of opinions on
| > | > | language design matters with anyone who uses such a radically
| > | > | different system.
| > | >
| > | > You never pose and ask yourself whether your system is broken, if I
| > | > may borrow words from you?
| > |
| > | I do. Of course, my system is based on my experience. I have
| > | programmed in many languages, I have implemented several languages, I
| > | have designed some languages.
| >
| > The point was not whether you designed some languages. But whether
| > you designed a language that had sufficient impact on computer science
| > and the world, and how your system worked out when confronted with the
| > reality of the word (as opposed to an abstract one).
|
| Obviously you knew the answer to this one.
No, I did not. As I said, I thought I missed something you've done of
that scale. Which is why I asked. Whether you take it not sincere is
up to you.
[...]
| > Say differently, I'm trying to differentiate arm-chair designers
| > from real practitioners.
|
| Well, guilty as charged. Now, let me ask you: What languages have
| /you/ designed?
None. I'm just working on some those, trying to make improvements.
But then, I refrain from making the sorts of arrogants claims I've
seen here because the real world is just damned complex and theology
and lessons from arm-chair designers just do not cut it.
| > Sure I did and do from time to time. But then, I always try to see
| > whether their authors are simply arrogant, or arm-chair designers, or
| > real practitioners.
|
| But even when they are arrogant and/or armchair designers, they might
| just be right.
They might. Still, it takes evidence for that. And in your case, I'm
looking for that. But don't bother.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/4/2005 8:51:12 PM
|
|
Florian Weimer wrote:
> * Joachim Durchholz:
>
>>It's broken in theory: parsing is a mess, its semantics is riddled with
>>exceptions and special cases. I already gave constructor issues in a
>>recent post, and that's just the start.
>
> I was bitten by that one, too, but if you think about it, it's a
> direct consequence of having true constructors and destructors. If
> you always invoke the member functions in the most derived class,
> you'd have partially constructed or destructed flying around, which
> would be a real nightmare.
It would be quite possible for a language to statically reject programs
in which references to partially constructed objects could escape their
constructor. Partially destructed objects would not be an issue in a
language that used safe memory management (GC or region-based) and
post-mortem finalization.
--
David Hopwood <david.nospam.hopwood@blueyonder.co.uk>
|
|
0
|
|
|
|
Reply
|
david.nospam.hopwood (121)
|
6/4/2005 8:57:02 PM
|
|
Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
> Most people in this discussion seem to have posited axioms and are
> very firm on not examining things.
That seems to include yourself as one prime example. On the other
hand, I think I actually have examined quite a few things. Do you
really think that there is anything out there that
a) I have not yet examined, and
b) once I examine it, it would make me think of C++ highly?
> | > However, I also understand that some people prefer or
> | > decide to be ignorant of history and the facts.
> |
> | Please, allegations don't belong into a technical discussion.
>
> Well: that comes directly from one of Matthias' message.
No, it does not. I have explicitly said that one should /not/ be
ignorant of facts, although being ignorant of facts that have nothing
to do with the topic at hand will not harm the conversation on that
particular topic. I also said that history has nothing to do with the
topic of how C++ is broken. That does not mean that I prefer or
decide to be ignorant of it, but if I am, it won't harm my judgment.
History does not excuse bad design.
> | It's certainly possible to improve something bad into something
> | not-quite-so-bad. The question is whether the end result is good
> | enough.
>
> At least *you* seem to understand my question, as opposed to some
> people here.
Again those unfounded allegations. I said quite exlicitly that one
can make bad things better. I just happen to think that what is
/actually/ been done in an attempt to make C++ better actually makes
it worse.
To refresh your memory: I said that the main problem of C++ is its
complexity, and adding more complexity ("concepts" anyone?) does not
only not solve this problem, it makes the problem worse.
> | The consensus here is that changing C++ into even a reasonable
> | language would require so deep alterations that the result wouldn't be
> | C++ anymore, and would be rejected for that reason.
>
> I think there is something that has been missed here. There are at
> least two ways of making improvement: (1) radical changes, (2) extend
> the language with functionalities that provide for better
> alternatives, thus making making the broken part largely
> secondary.
See, and that is /precisely/ the error you are making. Adding stuff
to a language that suffers from having too much stuff already will
*never* make that problem go away. You seem to think that one can add
enough "goodness" to C++, thereby marginalizing the existing "badness"
so it won't matter anymore. But that is nothing more than wishful
thinking.
Matthias
|
|
0
|
|
|
|
Reply
|
find19 (1245)
|
6/4/2005 10:10:58 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
| Gabriel Dos Reis wrote:
|
| > Hartmann Schaffer <hs@hartmann.schaffernet> writes:
| > | Gabriel Dos Reis wrote:
| > | > ...
| > | > Just facts. But, you do not seem to like facts, especially those that
| > | > would expose the fiction in your claims. You claimed:
| > | > instead of realizing that the syntax design was broken
| > | > and I'm pointing out that, the author did know (at the time) and
| > | > write
| > | > about it several times and explains the reason of why he could not
| > | > have done the cleanup he wanted, in the real world of the language
| > | > users (as opposed to an imaginary perfect world).
| > | | so if you start with something that is broken, realize it, but
| > decide
| > | you can't change the brokenness because of some constraints, the
| > | result is not broken?
| > I don't think "brokenness" is a universal, absolute notion. What
| > some people consider broken -- say Scheme, SML, Haskell, C++ -- may be
| > considered not broken by others.
|
| That doesn't make either of them right.
But that wasn't the point.
| Besides, C++ *is* broken.
|
| It's broken in theory: parsing is a mess, its semantics is riddled
| with exceptions and special cases. I already gave constructor issues
| in a recent post, and that's just the start.
|
| It's broken according to broad consensus. It's even a common saying
| that "C++ gives you not enough rope to hang yourself, but a pistol to
| shoot nice large holes through your foot".
I think you can find something close to the origin of that "common
saying" here:
http://www.research.att.com/~bs/bs_faq.html#really-say-that
Did you really say that?
"C makes it easy to shoot yourself in the foot; C++ makes it harder,
but when you do it blows your whole leg off." Yes, I said something
like that. What people tend to miss, is that what I said there about
C++ is to a varying extent true for all powerful languages. As you
protect people from simple dangers, they get themselves into new and
less obvious problems. Someone who avoids the simple problems may
simply be heading for a not-so-simple one. One problem with very
supporting and protective environments is that the hard problems may
be discovered too late or be too hard to remedy once discovered. Also,
a rare problem is harder to find than a frequent one because you don't
suspect it.
"Within C++, there is a much smaller and cleaner language struggling
to get out." Yes, that quote can be found on page 207 of The Design
and Evolution of C++. And no, that smaller and cleaner language is not
Java or C#. The quote occurs in a section entitled "Beyond Files and
Syntax". I was pointing out that the C++ semantics is much cleaner
than its syntax. I was thinking of programming styles, libraries and
programming environments that emphasized the cleaner and more
effective practices over archaic uses focussed on the low-level
aspects of C.
"I have always wished for my computer to be as easy to use as my
telephone; my wish has come true because I can no longer figure out
how to use my telephone" I said that after a frustrating attempt to
use a "feature-rich" telephone sometime around 1990. I'm sure the
sentiment wasn't original, and probably not even the overall phrasing;
someone must have thought of that before me.
"There are only two kinds of languages: the ones people complain about
and the ones nobody uses". Again, I very much doubt that the sentiment
is original. Of course, all "there are only two" quotes have to be
taken with a grain o salt.
"Proof by analogy is fraud". Page 692 of TC++PL. A good analogy is an
excellent way of illustrating an idea, but far too often such
analogies are not accompanied by solid reasoning, data, etc.
| It's broken according to personal experience. I have done similar
| projects in C++ and in other languages, and C++ required me to write
| down details that would be handled automatically in other languages
| (hence more LoC, more time to write it, more bugs), it took me more
| time to look up semantic details to get the code express what I wanted
| it to express, it layed traps for me that cost me hours of debugging.
|
| By all definitions, C++ is broken. That anybody can allude that C++
| may be considered nonbroken by some people makes me seriously doubt
| that person's sanity.
|
| > Furthermore, other people may
| > consider "brokenness" in the context of how the thing was made and
| > the constraints.
|
| It may be that C++ was the least broken thing that could be done under
| the circumstances. I seriously doubt that, but it's entirely possible.
|
| Still, this doesn't make C++ non-broken.
|
| > And I believe that for programming languages,
| > the consideration of contexts offer better insights into getting a
| > judgment.
|
| Judgment on Bjarne Stroustrup's language design skills is what you've
| been highlighting.
Then you missed the whole point. I've been trying to see how
| I'm under the impression that most people here
| think that that's largely irrelevant
Most people in this discussion seem to have posited axioms and are
very firm on not examining things.
| - what we think about is the
| merit of the language itself (and C++ is quite unanimously considered
| breakage here, else we'd be populating comp.lang.c++ instead of
| comp.lang.functional).
I don't read comp.lang.c++, but by no means not just because you're
not populating it means it is broken. That does not mean I'm claiming
"C++ it nos broken")
| > However, I also understand that some people prefer or
| > decide to be ignorant of history and the facts.
|
| Please, allegations don't belong into a technical discussion.
Well: that comes directly from one of Matthias' message. Are you
suggesting that despite appearance he does not want technical discussion?
| > To take your question at the other end, so if you start with something
| > that is broken, realize it, but decide you can't change *all* the
| > brokenness because of some constraints, can the result still be an
| > improvement?
|
| It's certainly possible to improve something bad into something
| not-quite-so-bad. The question is whether the end result is good
| enough.
At least *you* seem to understand my question, as opposed to some
people here. Although I disagree with with your conclusion, partly
because I doubt one could reach meaningful conclusions without
actually looked in and understood the problems. And conclusions based on
refusal to go beyond "common saying" don't belong into technical
discussion, if I may borrow from you :-)
| The consensus here is that changing C++ into even a reasonable
| language would require so deep alterations that the result wouldn't be
| C++ anymore, and would be rejected for that reason.
I think there is something that has been missed here. There are at
least two ways of making improvement: (1) radical changes, (2) extend
the language with functionalities that provide for better
alternatives, thus making making the broken part largely
secondary.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/4/2005 10:36:14 PM
|
|
Gabriel Dos Reis wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
> | Gabriel Dos Reis wrote:
> |
> | > Hartmann Schaffer <hs@hartmann.schaffernet> writes:
> | > | Gabriel Dos Reis wrote:
> | > | > ...
> | > | > Just facts. But, you do not seem to like facts, especially those that
> | > | > would expose the fiction in your claims. You claimed:
> | > | > instead of realizing that the syntax design was broken
> | > | > and I'm pointing out that, the author did know (at the time) and
> | > | > write
> | > | > about it several times and explains the reason of why he could not
> | > | > have done the cleanup he wanted, in the real world of the language
> | > | > users (as opposed to an imaginary perfect world).
> | > | | so if you start with something that is broken, realize it, but
> | > decide
> | > | you can't change the brokenness because of some constraints, the
> | > | result is not broken?
> | > I don't think "brokenness" is a universal, absolute notion. What
> | > some people consider broken -- say Scheme, SML, Haskell, C++ -- may be
> | > considered not broken by others.
> |
> | That doesn't make either of them right.
>
> But that wasn't the point.
I was a bit too terse here: I meant to say "That doesn't make either
peoples' definition of brokenness right."
In other words: wether people disagree about the degree of brokenness in
a language, this doesn't make either of them right. The kind of
brokenness I'm interested in is a rather objective (though very hard to
measure) one: how many pitfalls it offers for developers in general, how
efficient one can program in it, how secure the resulting code is in
relation to the effort invested in making it so.
> | Besides, C++ *is* broken.
> |
> | It's broken in theory: parsing is a mess, its semantics is riddled
> | with exceptions and special cases. I already gave constructor issues
> | in a recent post, and that's just the start.
No objections here. Fine.
> | It's broken according to broad consensus. It's even a common saying
> | that "C++ gives you not enough rope to hang yourself, but a pistol to
> | shoot nice large holes through your foot".
>
> I think you can find something close to the origin of that "common
> saying" here:
>
> http://www.research.att.com/~bs/bs_faq.html#really-say-that
>
> "C makes it easy to shoot yourself in the foot; C++ makes it harder,
> but when you do it blows your whole leg off."
That's the other common saying about C++.
I think it doesn't reflect general consensus though. Whenever I have
seen quotes on the relative (un)security of either language, it was more
the ropes and holes-in-the-foot variant.
(C++ does make a few things safer. It just doesn't address the real
problems.)
> Yes, I said something like that.
Actually I didn't quote you, I reported an observation about how C++ is
perceived. (Probably that perception is more prevalent outside the C++
community itself, so we may be at odds about which view is the less
controversial one.)
> What people tend to miss, is that what I said there about
> C++ is to a varying extent true for all powerful languages.
That variation is so broad that this statement is almost meaningless.
For example, Haskell is powerful and makes it very, very difficult to
shoot yourself into the foot (you need to call aptly-named
UnsafePerformIO function).
> As you
> protect people from simple dangers, they get themselves into new and
> less obvious problems. Someone who avoids the simple problems may
> simply be heading for a not-so-simple one.
Only because he keeps so much time debugging the simple problems that he
doesn't even notice the not-so-simple ones. That's only an argument if
you take peoples' perceptions for reality.
> One problem with very
> supporting and protective environments is that the hard problems may
> be discovered too late or be too hard to remedy once discovered.
That's a real problem in language design.
On the other hand, there's a wide margin between "overly protective" and
"outright dangerous". I think C++ errs on the "outright dangerous" side.
I also think that C++ takes that argument as an excuse for not properly
thinking about the consequences of design decisions before unleashing
them on an unsuspecting world. (I'm not talking about consequences for
compiler writers. I'm talking about consequences for the language
semantics, the guarantees that the language gives a programmer. C++
gives very few guarantees.)
> Also,
> a rare problem is harder to find than a frequent one because you don't
> suspect it.
That argument cuts both sides. If you're preoccupied with frequent
problems, the rare problems never even appear on your radar. You get
into a false sense of security once you have fixed all those simple
frequent problems.
Let me give a supporting experience.
In my C++ days, I spent 10% of my time designing and 90% coding and
debugging.
In my Eiffel days, I spent 30-50% of my time designing and the rest with
coding/debugging. Not because design is so complicated if you use
Eiffel, but because coding and debugging were so much easier that we
could affort more time thinking about design. The gap between design and
implementation was far narrower than with C++, so we could toss around
design changes and implement them just to see whether they's work better.
> "Within C++, there is a much smaller and cleaner language struggling
> to get out." Yes, that quote can be found on page 207 of The Design
> and Evolution of C++. And no, that smaller and cleaner language is not
> Java or C#.
Fully agreed with that.
> The quote occurs in a section entitled "Beyond Files and
> Syntax". I was pointing out that the C++ semantics is much cleaner
> than its syntax.
I could agree with that, but only from the perspective that a semantics
could be both clean (cleanly defined, fully formalised) but still
utterly broken (i.e. the clean definition still produces obscure bugs).
And C++'s semantics is indeed utterly broken. I haven't even begun to
enumerate all the problems with its semantics, and I haven't seen you
disagreeing with the examples that I gave, so I'm somewhat surprised
that you still seem to think that it has good merit.
> | Judgment on Bjarne Stroustrup's language design skills is what you've
> | been highlighting.
>
> Then you missed the whole point. I've been trying to see how
how what?
> | I'm under the impression that most people here
> | think that that's largely irrelevant
>
> Most people in this discussion seem to have posited axioms and are
> very firm on not examining things.
I think that argument cuts both sides.
Actually I'm tired of this kind of allegation, regardless of whom it's
directed against.
> | - what we think about is the
> | merit of the language itself (and C++ is quite unanimously considered
> | breakage here, else we'd be populating comp.lang.c++ instead of
> | comp.lang.functional).
>
> I don't read comp.lang.c++, but by no means not just because you're
> not populating it means it is broken.
Not, but it does mean that you have a self-selected group of people who
don't like C++.
> That does not mean I'm claiming "C++ it nos broken")
Yup, I noticed a conspicuous absence of such claims.
I'm still wondering what your point actually *is*. Or why you're
entertaining this discussion.
> | > To take your question at the other end, so if you start with something
> | > that is broken, realize it, but decide you can't change *all* the
> | > brokenness because of some constraints, can the result still be an
> | > improvement?
> |
> | It's certainly possible to improve something bad into something
> | not-quite-so-bad. The question is whether the end result is good
> | enough.
>
> At least *you* seem to understand my question, as opposed to some
> people here.
Thanks.
Actually I'm pretty sure most people understand your position a lot
better than you realise, there's just a lot of mutual missing the topic
at work here. I.e. most here assume that C++ is broken beyond repair (a
view that I share), and you seem to counter that argument with tales of
how C++ originated and the constraints that it was designed under (which
are probably correct but don't address the main objection).
> Although I disagree with with your conclusion, partly
> because
Now I'd be interested what else are the reasons why you disagree.
> I doubt one could reach meaningful conclusions without
> actually looked in and understood the problems.
Well, I have learned enough C++ to know it's an unsafe language, with
many, many surprising twists in its semantics. Maybe a correct
categorisation of C++ is "that it makes it more difficult to make simple
errors, while making it d**n easy to make subtle errors" - an
improvement that I don't really care for.
I know (partly from close observation, partly from direct participation)
that designing a better language is difficult. Designing a good
statically-typed OO language is very difficult. Designing such a
language that's also largely compatible with C++ is impossible ("good"
and "compatible with C" are almost diametrally opposing design goals).
However, I don't think that the realisation that the C++ design goals
were a mission impossible saves the language in any way. It would have
been better if somebody had designed an OO language that's syntactically
similar enough to C that C programmers feel largely at home, and that
can easily interface with C libraries so that existing software can be
leveraged. (Of course, there's also the problem that knowledge about OO
type systems wasn't as good as it is today. Multiple inheritance wasn't
well-understood at that time - actually most language designers don't
understand it today, and simply implement a mechanism that "resolves
conflicts" in some arbitary fashion.)
> | The consensus here is that changing C++ into even a reasonable
> | language would require so deep alterations that the result wouldn't be
> | C++ anymore, and would be rejected for that reason.
>
> I think there is something that has been missed here. There are at
> least two ways of making improvement: (1) radical changes, (2) extend
> the language with functionalities that provide for better
> alternatives, thus making making the broken part largely
> secondary.
Well, sure. The problem is that the broken parts of a language remain in
use, so it doesn't really fix the problem.
Besides, adding to a language makes it even more complex, offering
additional ways for fine semantic points to creep in - and every fine
point in semantics is a source of subtle bugs.
C++ simply has grown into a too complex beast. The only way to fix it
would be radical change - which, for various reasons, isn't feasible
today. I think that C++ will go the same route as PL/I: existing
projects will continue to use it, but its use in new projects will
gradually decline until it's generally considered a dinosaur.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/4/2005 10:42:48 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
[...]
| That the syntax is baroque is largely a C legacy, and perhaps
| unavoidable. Still, there is gratuitious baroqueness in C++'s syntax,
| easily demonstrated through the observation that there are several
| useful C parsers available now, but _not_a_single_C++_parser_.
Facts:
http://gcc.gnu.org/
http://www.edg.com/
and many others.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/4/2005 10:43:30 PM
|
|
Gabriel Dos Reis wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
> [...]
>
> | That the syntax is baroque is largely a C legacy, and perhaps
> | unavoidable. Still, there is gratuitious baroqueness in C++'s syntax,
> | easily demonstrated through the observation that there are several
> | useful C parsers available now, but _not_a_single_C++_parser_.
>
> Facts:
>
> http://gcc.gnu.org/
> http://www.edg.com/
I stand corrected.
Mainly because I was typing faster than thinking: I meant free (in both
senses of the word) parsers.
GCC almost cuts it, but extracting the parser from the compiler is an
almost impossible task.
edg seems to be a commercial product.
Why that emphasis on free parsers? Because they tend to be done by small
teams or single persons. C++ is too complicated to be tackled if
manpower is limited. In fact gcc strenthens that point: the only free
software that handles C++ is gcc, a multi-person-century project; there
are no lean-and-hungry C++ parsers around, but there are several for C
(two usable ones listed on the comp.compilers archives, I think).
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/4/2005 10:48:12 PM
|
|
* David Hopwood:
> It would be quite possible for a language to statically reject programs
> in which references to partially constructed objects could escape their
> constructor.
Yes, but with virtual functions, you need whole-program analysis and
linker support. This doesn't play nice with DSOs.
> Partially destructed objects would not be an issue in a
> language that used safe memory management (GC or region-based) and
> post-mortem finalization.
I think the key issue is the way destructors are combined. If you
don't want a default combination, other solutions are fine. But in my
experience, destructors were the only virtual members I had to
override in a non-trivial way (in all the other cases I remember, I
overrode the function completely, either a no-op function or an
abstract one). That's why some special treatment might make sense.
|
|
0
|
|
|
|
Reply
|
fw12 (435)
|
6/4/2005 10:51:54 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
[...]
| Anyway. It's not really a problem. Those complicated initialisation
| rules for C++ are dealing with a problem that simply doesn't exist.
Again, having work sufficiently enough with C++, I'm interested in the
data upon which you base that claim.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/4/2005 11:09:35 PM
|
|
* Joachim Durchholz:
> Why that emphasis on free parsers? Because they tend to be done by small
> teams or single persons. C++ is too complicated to be tackled if
> manpower is limited. In fact gcc strenthens that point: the only free
> software that handles C++ is gcc, a multi-person-century project;
The current C++ parser was written by Mark Mitchell. AFAIK, it took
him much less than two person-years to write it. Gaby might have
better figures.
|
|
0
|
|
|
|
Reply
|
fw12 (435)
|
6/4/2005 11:27:54 PM
|
|
* Joachim Durchholz:
> I'm speaking from my Eiffel experience here. Eiffel's policy is: a
> function is always virtual (there are exceptions). Constructors are
> otherwise normal functions, and they start with an object that's
> initialized to all zeros.
This is only possible if all objects have a meaningful default value.
C++ references don't.
> Anyway. It's not really a problem. Those complicated initialisation
> rules for C++ are dealing with a problem that simply doesn't exist.
I disagree, initialization of interacting subsystems (and a class
hierarchy is just that) is a difficult problem, and language support
is more than welcome.
For example, Ada's elaboration semantics make life so much easier in
many cases (half of the singleton pattern becomes trivial).
>>> It's broken according to broad consensus. It's even a common saying
>>> that "C++ gives you not enough rope to hang yourself, but a pistol
>>> to shoot nice large holes through your foot".
>> By this definition, most (all?) successful technology is broken.
>
> (Let me restrict to "programming languages in the mainstream" -
> "technology" is too general here, and "successful" is a somewhat
> imprecise term.)
I meant "successful" in the sense of "success in acquiring developer
mindshare" or something like that, so proximity to mainstream is
equivalent.
> Lisp. Python.
Lisp is not successful and widely believed to be broken (parentheses,
garbage collection, dynamic type checking). Some of the C++ criticism
in this thread certainly is at the parentheses level, and most at GC,
some at dynamic checking.
Python is only non-broken if you don't care for efficiency. It's
very, very hard to create an optimizing Python compiler, much harder
than for Lisp, and you are tied to reference counting and can't use a
modern garbage collector. Applying double standards, we could call
this a reasonable tradeoff, though.
> That experience strengthened my distaste for C++. I had an opportunity
> to go into an Eiffel job and took it. My findings were:
> - All those typical problems of C++ programming (memory leaks, exception
> handling issues, diamond inheritance issues, syntactic and semantic
> surprises) simply vanished.
> - Despite Eiffel being in the verbose tradition of Pascal Ada, Eiffel
> programs are far shorter than equivalent C++ programs. Part of it is
> that Eiffel has automatic garbage collection (this takes off quite a lot
> of lines of code, and often simplifies the design considerably),
You used the wrong C++ libraries, it seems. Even garbage collection
is available for C++. Maybe it's not part of the language standard,
but the Boehm-Demers-Weiser collector is probably as portable as your
average Eiffel implementation. 8-)
> Also, the Eiffel compiler automatically extracts the information
> that C++ programmers must redundantly write into header files.
This is purely a matter of taste. I'm strongly in favor of a real
module system which separates declarations and definitions. (This is
no argument in favor of C++, of course.)
> On the other hand, C++ templates are more difficult to compile
> separately than generic classes in Eiffel, so I don't see that C++ has
> any real advantage here.
You pay the costs caused by templates only when you use them.
|
|
0
|
|
|
|
Reply
|
fw12 (435)
|
6/4/2005 11:29:30 PM
|
|
* Joachim Durchholz:
>> What do you propose as an alternative? Partially constructed
>> objects?
>
> Let the object be created as a member of its target class. The
> constructor is obliged to fill it with data that fulfills the class's
> invariant. In particular, it's obliged to fill in enough data before
> calling functions that depend on that data - but that's normal with any
> kind of step-by-step initialisation.
So you'd like to disallow calling virtual member functions from the
constructor altogether? This doesn't sound too bad, but based on your
previous postings, I concluded you wanted something more flexible.
> Besides, initialisation is rarely a serious problem.
Tell that to someone who had to fight with circular dependencies among
singletons.
|
|
0
|
|
|
|
Reply
|
fw12 (435)
|
6/4/2005 11:34:22 PM
|
|
Gabriel Dos Reis wrote:
> ...
> To take your question at the other end, so if you start with something
> that is broken, realize it, but decide you can't change *all* the
> brokenness because of some constraints, can the result still be an
> improvement?
to not quite as badly broken? would still be called broken
hs
|
|
0
|
|
|
|
Reply
|
hs60 (77)
|
6/5/2005 12:00:47 AM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
[...]
| > | Besides, C++ *is* broken.
| > | | It's broken in theory: parsing is a mess, its semantics is
| > riddled
| > | with exceptions and special cases. I already gave constructor issues
| > | in a recent post, and that's just the start.
|
| No objections here. Fine.
Oh no: Absence of reply does not mean agreement or disagreement.
I just haven't read your constructor issues. From your other
conversion with Florian, I guess it would have to do with calling
virtual functions in a constructor. Is that right?
[...]
| > Yes, I said something like that.
|
| Actually I didn't quote you,
I think you're (mis)attributing the quote from the website to me :-)
[...]
| > One problem with very
| > supporting and protective environments is that the hard problems may
| > be discovered too late or be too hard to remedy once discovered.
|
| That's a real problem in language design.
|
| On the other hand, there's a wide margin between "overly protective"
| and "outright dangerous". I think C++ errs on the "outright dangerous"
| side.
|
| I also think that C++ takes that argument as an excuse for not
| properly thinking about the consequences of design decisions before
| unleashing them on an unsuspecting world.
Well, I've been in the trenches for some time to know from experience
and from those who have been there long before me that your claim is
largely unfounded. For almost all problems I know of, I don't think
C++ designers did not properly think about design decision consequences.
[...]
| Let me give a supporting experience.
|
| In my C++ days, I spent 10% of my time designing and 90% coding and
| debugging.
Then, let me give you counter supportive exprience: I spend 90% of my
time designing and 10% coding. It is largely known (at least in the
C++ community, but I would have thought it isn't that language
specific) that the far vast majority of time spent on project (nearly
90%) is on design not code. This is the case for collegues I have
high (technical) estime for. That certainly is the case of (all?)
successful C++ project I know of.
Those which required more than 10% coding were problematic if not
failure.
[...]
| And C++'s semantics is indeed utterly broken. I haven't even begun to
| enumerate all the problems with its semantics,
Please do :-) As I said elsewhere, I thought I would be discussing
semantics intead of angle brackets, curly braces and bananas.
| and I haven't seen you
| disagreeing with the examples that I gave, so I'm somewhat surprised
| that you still seem to think that it has good merit.
Which examples? If you're refering to "constructors", I haven't seen
see them.
[...]
| > | - what we think about is the
| > | merit of the language itself (and C++ is quite unanimously considered
| > | breakage here, else we'd be populating comp.lang.c++ instead of
| > | comp.lang.functional).
| > I don't read comp.lang.c++, but by no means not just because you're
| > not populating it means it is broken.
|
| Not, but it does mean that you have a self-selected group of people
| who don't like C++.
You mean like some people on comp.lang.functional? ;-)
The only reason why I do not read comp.lang.c++ is that the traffic is
just too high for me to handle AND to read claims on
comp.lang.functional or comp.lang.ml etc :-)
| > That does not mean I'm claiming "C++ it nos broken")
|
| Yup, I noticed a conspicuous absence of such claims.
|
| I'm still wondering what your point actually *is*.
That in the face of the real world, confrontation with reality, the
notion of "brokenness" is not as clear cut as some theologies are
putting it. I don't believe it is a 0 or 1 thing. Furthermore, I
think considerations of the constraints, goals and understanding of the
problems are essential for making that judgment as objective
as possible. I just don't make it an axiom :-)
[...]
| > | The consensus here is that changing C++ into even a reasonable
| > | language would require so deep alterations that the result wouldn't be
| > | C++ anymore, and would be rejected for that reason.
| > I think there is something that has been missed here. There are at
| > least two ways of making improvement: (1) radical changes, (2) extend
| > the language with functionalities that provide for better
| > alternatives, thus making making the broken part largely
| > secondary.
|
| Well, sure. The problem is that the broken parts of a language remain
| in use, so it doesn't really fix the problem.
At that point, a question is why they are in use. If there are needs
that those parts address then, better address those needs than simply
removing the broken parts -- taking analogy from a previous message,
the broken mirror is not fixed just because it is thrown away.
If there are in use because of insufficient support from environement
(better libraries, education, etc.) then it is not a problem of not
retiring the broken parts. Rather offer better libraiies, education,
etc.
The report that a language X programmer would spend 90% of its time
coding and 10% designing is effectivelly worrisome, but that is barely
the language fault. I think it is more a problem of experience or
"education" (please, this is *no* insult) than an inherent brokenness
of the language.
I know from experience (writing programs and implementing translator)
that there are subsets of C++ that are safe, and they are subsets that
are unsafe. The unsafe parts is largely superseded by the safe
parts. And they are cases where the unsafe parts are needed (that is
the case for all major programming languages that support system
programming I know of). But the unsafe part can be isolated. And
that is a point that some people have trouble with. C++ is
successfully used on daily basis in high critical missions where
safety is a major issue. That is done by isolating the sae part form
the unsafe part. And not, they don't spend 90% of time coding and
debugging ;-)
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/5/2005 1:43:25 AM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
[...]
| Why that emphasis on free parsers? Because they tend to be done by
| small teams or single persons. C++ is too complicated to be tackled if
| manpower is limited. In fact gcc strenthens that point: the only free
| software that handles C++ is gcc, a multi-person-century project;
The new GCC/g++ parser was written by a single person: Mark Mitchell
of CodeSourcery.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/5/2005 1:46:01 AM
|
|
Florian Weimer <fw@deneb.enyo.de> writes:
| * Joachim Durchholz:
|
| > Why that emphasis on free parsers? Because they tend to be done by small
| > teams or single persons. C++ is too complicated to be tackled if
| > manpower is limited. In fact gcc strenthens that point: the only free
| > software that handles C++ is gcc, a multi-person-century project;
|
| The current C++ parser was written by Mark Mitchell. AFAIK, it took
| him much less than two person-years to write it. Gaby might have
| better figures.
Yours are correct.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/5/2005 1:46:55 AM
|
|
Hartmann Schaffer <hs@hartmann.schaffernet> writes:
| Gabriel Dos Reis wrote:
| > ...
| > To take your question at the other end, so if you start with something
| > that is broken, realize it, but decide you can't change *all* the
| > brokenness because of some constraints, can the result still be an
| > improvement?
|
| to not quite as badly broken? would still be called broken
The point is that the notion of "brokenness" is not a 0 or 1 thingy.
Matthias even seems to agree :-)
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/5/2005 1:49:13 AM
|
|
Just to fan the flames a bit more... I'm wonder what people think about
"D" http://www.digitalmars.com/d/
It seems a very serious attempted to "fix" C++ by starting from scratch.
It seems to lack a multi-million dollar marketing buget.. but beyond
that.. it seems quite mature...
|
|
0
|
|
|
|
Reply
|
danwang74 (206)
|
6/5/2005 2:13:32 AM
|
|
Gabriel Dos Reis wrote:
> "Daniel C. Wang" <danwang74@gmail.com> writes:
>
> | Just to fan the flames a bit more... I'm wonder what people think
> | about "D" http://www.digitalmars.com/d/
> | It seems a very serious attempted to "fix" C++ by starting from scratch.
>
> Google for discussions about D and C++ on C++ newsgroups ;-)
>
> | It seems to lack a multi-million dollar marketing buget..
>
> AT&T did not put $$$ marketing budget behind C++.
>
> -- Gaby
Defensive aren't we.. :) note I wasn't making any specific accusation,
in fact I was thinking of C# and Java more than C++ .
|
|
0
|
|
|
|
Reply
|
danwang74 (206)
|
6/5/2005 2:55:15 AM
|
|
"Daniel C. Wang" wrote:
>
> Just to fan the flames a bit more... I'm wonder what people think about
> "D" http://www.digitalmars.com/d/
> It seems a very serious attempted to "fix" C++ by starting from scratch.
> It seems to lack a multi-million dollar marketing buget.. but beyond
> that.. it seems quite mature...
D is influenced by C, C++ and Java. I cannot see any influence
of Python let alone the functional programming languges. In
paricular, D is missing builtin lists, ML style variant types
and ML style pattern matching. Its biggest problem is that its
whole thinking is locked into a Java/C++ style of Object
Orientated Design Pattern madness.
D attempts to fix a few of the more obvious flaws in C++ without
fixing the non-obvious flaws. Like C, C++ and Java, D allows
unsafe casts and unsafe conversion between types. D's template
system is a slight improvement over C++ but doesn't go anywhere
near far enough.
Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo nospam@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
"There is no reason why anyone would want a computer in their home"
Ken Olson, DEC, 1977
|
|
0
|
|
|
|
Reply
|
nospam140 (349)
|
6/5/2005 3:07:34 AM
|
|
Erik de Castro Lopo wrote:
{stuff deleted}
> D attempts to fix a few of the more obvious flaws in C++ without
> fixing the non-obvious flaws. Like C, C++ and Java, D allows
> unsafe casts and unsafe conversion between types. D's template
> system is a slight improvement over C++ but doesn't go anywhere
> near far enough.
So is it worth redesiging D's template system to "get it right" or would
people consider that a waste of effort?
Or to say it more generically, if one wanted to actually improve the
state of programming languages for your every day hacker today, where
should a language designer put their effort?
C++,
D,
Java,
C#
Note that C# and Java both recently picked up generics in a relatively
principled way. Given that C# and Java both have large multi-billion
dollar companies behind them with vested interests and C++ seems
unpalatable to many is D a good platform for language designers?
I haven't mentioned any functional languages, because I'm becoming
skeptical that they will have an real *direct* impact on programming for
your average joe/jane programmer. I suspect they'll have a much bigger
indirect impact in the long run.
|
|
0
|
|
|
|
Reply
|
danwang74 (206)
|
6/5/2005 3:42:58 AM
|
|
"Daniel C. Wang" <danwang74@gmail.com> writes:
| Just to fan the flames a bit more... I'm wonder what people think
| about "D" http://www.digitalmars.com/d/
| It seems a very serious attempted to "fix" C++ by starting from scratch.
Google for discussions about D and C++ on C++ newsgroups ;-)
| It seems to lack a multi-million dollar marketing buget..
AT&T did not put $$$ marketing budget behind C++.
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/5/2005 3:53:06 AM
|
|
"Daniel C. Wang" <danwang74@gmail.com> writes:
| Gabriel Dos Reis wrote:
| > "Daniel C. Wang" <danwang74@gmail.com> writes:
| > | Just to fan the flames a bit more... I'm wonder what people think
| > | about "D" http://www.digitalmars.com/d/
| > | It seems a very serious attempted to "fix" C++ by starting from scratch.
| > Google for discussions about D and C++ on C++ newsgroups ;-)
| > | It seems to lack a multi-million dollar marketing buget.. AT&T did
| > not put $$$ marketing budget behind C++. -- Gaby
|
| Defensive aren't we.. :)
No no no.
| note I wasn't making any specific accusation,
| in fact I was thinking of C# and Java more than C++ .
I was merely pointing out that as in the case of D you're reporting,
AT&T did not put $$$ marketing budget behind C++.
Is that being defensive?
-- Gaby
|
|
0
|
|
|
|
Reply
|
gdr (104)
|
6/5/2005 4:23:01 AM
|
|
"Daniel C. Wang" wrote:
>
> Erik de Castro Lopo wrote:
> {stuff deleted}
> > D attempts to fix a few of the more obvious flaws in C++ without
> > fixing the non-obvious flaws. Like C, C++ and Java, D allows
> > unsafe casts and unsafe conversion between types. D's template
> > system is a slight improvement over C++ but doesn't go anywhere
> > near far enough.
>
> So is it worth redesiging D's template system to "get it right" or would
> people consider that a waste of effort?
Because of all the other flaws, I believe D is a wasted effort
regardless of whether its template system is good or bad.
> Or to say it more generically, if one wanted to actually improve the
> state of programming languages for your every day hacker today, where
> should a language designer put their effort?
>
> C++,
> D,
> Java,
> C#
None of the above.
I've only looked at it a little, but Nemerle
http://www.nemerle.org/
seems to be the only attempt I know of that tries to bridge the
gap between C/C++/Java and the functional languages.
> I haven't mentioned any functional languages, because I'm becoming
> skeptical that they will have an real *direct* impact on programming for
> your average joe/jane programmer. I suspect they'll have a much bigger
> indirect impact in the long run.
IMHO, any language that allows unsafe casts and automatic
type conversions is unusable for large and/or complicated
projects. Any language which is designed for tackling these
big problems must also have built in lists, bounds checked
arrays and safe string handling as part of the language core
rather than as a grafted on extra like with C++ and to a lesser
extend Java and D. ML style variant types and pattern matching
are also a must have for my idea language.
You'll notice that none of the features above are strictly
functional language features. I'm not married to functional
programming, but for some tasks the functional approach
does work better than the imperative approach and vice versa.
It would therefore be nice to have functional and imperative
features on an equal footing unlike Ocaml where the constructs
for imperative programming seem like like second class features.
Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo nospam@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
Spammer: Any of you guys looking for a permanent position in Scotland?
Kaz Kylheku: No, I'm looking for a thug in Scotland who might be interested
in beating up off-topic Usenet spammers, on a pro bono basis.
|
|
0
|
|
|
|
Reply
|
nospam140 (349)
|
6/5/2005 5:01:31 AM
|
|
Quoth Erik de Castro Lopo <nospam@mega-nerd.com>:
....
| I've only looked at it a little, but Nemerle
|
| http://www.nemerle.org/
|
| seems to be the only attempt I know of that tries to bridge the
| gap between C/C++/Java and the functional languages.
I think Felix sounds more like that than you probably meant -
http://felix.sourceforge.net/
Donn Cave, donn@drizzle.com
|
|
0
|
|
|
|
Reply
|
donn (251)
|
6/5/2005 5:31:10 AM
|
|
Donn Cave wrote:
>
> Quoth Erik de Castro Lopo <nospam@mega-nerd.com>:
> ...
> | I've only looked at it a little, but Nemerle
> |
> | http://www.nemerle.org/
> |
> | seems to be the only attempt I know of that tries to bridge the
> | gap between C/C++/Java and the functional languages.
>
> I think Felix sounds more like that than you probably meant -
> http://felix.sourceforge.net/
I am aware of Felix. I even lurk on the mailing list ;-).
However, the vast majority of the problems I am interested
in are computationally expensive and I really don't think
that any language that runs on top of a VM (like Felix)
will ever match code that compiles to native binaries.
Despite John Skaller's success in to make Felix run as
fast as the native ocaml and C compiled binaries for
trivial test programs, I think that for real world cases
he has a long way to go.
Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo nospam@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
"A subversive is anyone who can out-argue their government"
|
|
0
|
|
|
|
Reply
|
nospam140 (349)
|
6/5/2005 5:42:07 AM
|
|
Erik de Castro Lopo wrote:
> "Daniel C. Wang" wrote:
{stuff deleted}
>>Or to say it more generically, if one wanted to actually improve the
>>state of programming languages for your every day hacker today, where
>>should a language designer put their effort?
>>
{stuff deleted}
>
> IMHO, any language that allows unsafe casts and automatic
> type conversions is unusable for large and/or complicated
> projects. Any language which is designed for tackling these
> big problems must also have built in lists, bounds checked
> arrays and safe string handling as part of the language core
> rather than as a grafted on extra like with C++ and to a lesser
> extend Java and D. ML style variant types and pattern matching
> are also a must have for my idea language.
{stuff deleted}
Hmm.. my question was not what would be the best language that you would
enjoy programming in, but where can one have a big impact on the design
of a language that for whatever reason has mindshare of a large group of
every day programmers.
After, reflecting on how generics made their way into Java and C#, I'm
very skeptical about the value of everyone designing new languages from
scratch and trying to build a user base around them. Desiging a new
language is an interesting exercise, but I think that it is highly
unlikely that most new languages will have any real *direct* impact in
the long run. However, there are real problmatic issues in exsiting
languages with existing user bases for which language designers can have
a tangible *direct* impact on.
BTW using the visitor pattern and "inner classes/closures" really isn't
so bad. Most OO languages have the moral equivlant of variants. The
lack of pattern matching is extremly annoying, but when it gets too
annoying one can always write a pre-processor.
|
|
0
|
|
|
|
Reply
|
danwang74 (206)
|
6/5/2005 6:49:25 AM
|
|
On 2005-06-05, Erik de Castro Lopo <nospam@mega-nerd.com> wrote:
> Donn Cave wrote:
>>
>> Quoth Erik de Castro Lopo <nospam@mega-nerd.com>:
>> ...
>> | I've only looked at it a little, but Nemerle
>> |
>> | http://www.nemerle.org/
>> |
>> | seems to be the only attempt I know of that tries to bridge the
>> | gap between C/C++/Java and the functional languages.
>>
>> I think Felix sounds more like that than you probably meant -
>> http://felix.sourceforge.net/
>
> I am aware of Felix. I even lurk on the mailing list ;-).
>
> However, the vast majority of the problems I am interested
> in are computationally expensive and I really don't think
> that any language that runs on top of a VM (like Felix)
> will ever match code that compiles to native binaries.
Felix does not run on a VM. Felix generates C++ code, which is then
compiled by the C++ compiler. From the Felix page:
The Felix compiler is written in Objective Caml, and generates ISO C++
which should compile on any platform.
The running time is quite similar to code written for C++ or ocamlopt
http://felix.sourceforge.net/current/speed/en_flx_perf.html
Disclaimer: I never coded in Felix.
Regards.
--
Basile STARYNKEVITCH http://starynkevitch.net/Basile/
email: basile(at)starynkevitch(dot)net
8, rue de la Fa�encerie, 92340 Bourg La Reine, France
|
|
0
|
|
|
|
Reply
|
basile-news (46)
|
6/5/2005 8:12:41 AM
|
|
Florian Weimer <fw@deneb.enyo.de> writes:
> By this definition, most (all?) successful technology is broken.
So what? Most commercially successful technology *is* broken - most of
the time beyond all repair.
'Andreas
--
Wherever I lay my .emacs, there's my $HOME.
|
|
0
|
|
|
|
Reply
|
Andreas_Eder1 (8)
|
6/5/2005 8:38:28 AM
|
|
"Basile Starynkevitch [news]" wrote:
>
> Felix does not run on a VM. Felix generates C++ code, which is then
> compiled by the C++ compiler. From the Felix page:
I'm sorry, you are correct.
Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo nospam@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
Linux, the UNIX defragmentation tool.
|
|
0
|
|
|
|
Reply
|
nospam140 (349)
|
6/5/2005 8:50:59 AM
|
|
"Daniel C. Wang" wrote:
>
> Hmm.. my question was not what would be the best language that you would
> enjoy programming in, but where can one have a big impact on the design
> of a language that for whatever reason has mindshare of a large group of
> every day programmers.
Unfortunately, this is the attitude that has landed us
with C++ and Java. Both languages build on an existing
language without doing anything that fixes the failings
of the language they build on.
C++ and Java are both supposed to be high level languages
but both still have potentially unsafe casts. This is still
the case with Java which was based on C++ where I thought
the lesson should have already been learned.
> After, reflecting on how generics made their way into Java and C#,
I know very little about C#. With regards to Java, I know
that maniupulating lists in Java is significantly more
painful that doing the same in say Ocaml. The reason is
that Ocaml has lists manipulation built into the language.
Java with generics still falls far short of Ocaml (or say
Python) with respect to list handling. The Visitor pattern
is simply not a adequate substitute.
> I'm
> very skeptical about the value of everyone designing new languages from
> scratch and trying to build a user base around them.
That may well be the case, but I believe that Java and
C++ (and probably C#) are unfixable with repsect to
sane list handling (to name one very common programming
task).
> Desiging a new
> language is an interesting exercise, but I think that it is highly
> unlikely that most new languages will have any real *direct* impact in
> the long run. However, there are real problmatic issues in exsiting
> languages with existing user bases for which language designers can have
> a tangible *direct* impact on.
Adding sane Ocaml/ML style list handling to mainstream
Java is significantly more difficult than writing a new
language :-).
> BTW using the visitor pattern and "inner classes/closures" really isn't
> so bad.
I've seen it done and it works OK for trivial examples,
but is a royal PITA for large real world examples.
> Most OO languages have the moral equivlant of variants.
Its hackery at best. If you work on a large project with
many sub-teams and two teams independantly decide that they
need variant types, you will end up with two incompatible
implementations. If variants are built into the language
people just use the builtin version instead of hacking
their own.
> The
> lack of pattern matching is extremly annoying, but when it gets too
> annoying one can always write a pre-processor.
Yet more hackery. The same arguments apply.
Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo nospam@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
Microsoft is finally bringing all of its Windows operating system families
under one roof. It will combine all of the features of CE, stability and
support of ME and the speed of NT.
It will be called Windows CEMENT...
|
|
0
|
|
|
|
Reply
|
nospam140 (349)
|
6/5/2005 9:05:45 AM
|
|
Florian Weimer wrote:
> * Joachim Durchholz:
>
>>I'm speaking from my Eiffel experience here. Eiffel's policy is: a
>>function is always virtual (there are exceptions). Constructors are
>>otherwise normal functions, and they start with an object that's
>>initialized to all zeros.
>
> This is only possible if all objects have a meaningful default value.
> C++ references don't.
I'm not far enough into references to comment on that. All I can say is
that I never missed them in other languages, and that's a strong
indicator that they solve a problem that isn't one in other languages.
>>Anyway. It's not really a problem. Those complicated initialisation
>>rules for C++ are dealing with a problem that simply doesn't exist.
>
> I disagree, initialization of interacting subsystems (and a class
> hierarchy is just that) is a difficult problem, and language support
> is more than welcome.
>
> For example, Ada's elaboration semantics make life so much easier in
> many cases (half of the singleton pattern becomes trivial).
OK, I'll take your word for that.
Then my stance on C++ constructor semantics becomes that it belongs to
the problem set, not the solution set.
>>>>It's broken according to broad consensus. It's even a common saying
>>>>that "C++ gives you not enough rope to hang yourself, but a pistol
>>>>to shoot nice large holes through your foot".
>>>
>>>By this definition, most (all?) successful technology is broken.
>>
>>Lisp. Python.
>
> Lisp is not successful and widely believed to be broken (parentheses,
> garbage collection, dynamic type checking). Some of the C++ criticism
> in this thread certainly is at the parentheses level, and most at GC,
> some at dynamic checking.
Lisp in itself isn't broken. Lisp has some drawbacks (parenthese
madness), and current-day lisps have broken macro and library stuff, but
the language itself is actually quite sane.
GC actually is the opposite of brokenness: it makes the language safer
and easier to program in. (It also restricts its usefulness for HRT, but
being unsuitable for a specific niche doesn't make a language broken.)
Dynamic typing is something that I myself don't particularly like, but
there are people who are successfully working with dynamically-typed
languages, so this in itself isn't breakage, too.
So, while Lisp certainly isn't for everybody's taste or every
application area, it isn't broken per se.
> Python is only non-broken if you don't care for efficiency. It's
> very, very hard to create an optimizing Python compiler, much harder
> than for Lisp, and you are tied to reference counting and can't use a
> modern garbage collector. Applying double standards, we could call
> this a reasonable tradeoff, though.
OK, reference counting is indeed brokenness.
Let me take back a bit of my statements above. A certain amount of
brokenness seems to be inevitable; it's just that C++ is broken in so
many ways that it's one of the worst languages that I have seen. (It's
not the worst though. RPG IV is worse: not as much breakage as in C++,
but that's only because it's so ridiculously inexpressive that the
language simply didn't have as many murky corners to hide brokenness in.)
>>That experience strengthened my distaste for C++. I had an opportunity
>>to go into an Eiffel job and took it. My findings were:
>>- All those typical problems of C++ programming (memory leaks, exception
>>handling issues, diamond inheritance issues, syntactic and semantic
>>surprises) simply vanished.
>>- Despite Eiffel being in the verbose tradition of Pascal Ada, Eiffel
>>programs are far shorter than equivalent C++ programs. Part of it is
>>that Eiffel has automatic garbage collection (this takes off quite a lot
>>of lines of code, and often simplifies the design considerably),
>
> You used the wrong C++ libraries, it seems.
Libraries don't help if you have to write your own algorithms.
We had to write a series of simple tests, and finding and learning a
library would have been more effort than simply programming it by
ourselves. (That's even true in hindsight. The test framework that I set
up took me two weeks to write, and the test programmer said it worked
smoothly for him. Finding and learning a test library would have taken
more than two person-weeks.)
> Even garbage collection
> is available for C++. Maybe it's not part of the language standard,
> but the Boehm-Demers-Weiser collector is probably as portable as your
> average Eiffel implementation. 8-)
Actually BDW GC is an option or mandatory for all Eiffel implementations
IIRC.
>>Also, the Eiffel compiler automatically extracts the information
>>that C++ programmers must redundantly write into header files.
>
> This is purely a matter of taste. I'm strongly in favor of a real
> module system which separates declarations and definitions. (This is
> no argument in favor of C++, of course.)
Declarations are automatically inferrable from definitions, so that
should be done. Having to keep the two consistent is a major time sink.
I'm speaking from having been on both sides of the fence: Turbo Pascal,
Modula-3, and C++ require explicit module interfaces, Eiffel doesn't
(and Eiffel compilers will generate human-readable interfaces on request).
My experience was: having the interfaces is excellent, but having to
maintain them redundantly with the code simply isn't worth it - an
eyeball code review will find more errors. Eiffel offered the best of
both worlds, because I didn't have to wade through tons of source code
to see the interface. (BTW Eiffel interfaces are even better than C++
ones: on request, the compiler will reproduce the full interface,
including members that were inherited from superclasses. You don't need
that too often, but it's indispensable when you're inspecting whether a
class has all the members that you expect it to have, and to diagnose
inheritance conflicts.)
>>On the other hand, C++ templates are more difficult to compile
>>separately than generic classes in Eiffel, so I don't see that C++ has
>>any real advantage here.
>
> You pay the costs caused by templates only when you use them.
Same with Eiffel's generic classes, so what?
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 9:36:09 AM
|
|
Erik de Castro Lopo wrote:
> "Daniel C. Wang" wrote:
>
>>Hmm.. my question was not what would be the best language that you would
>>enjoy programming in, but where can one have a big impact on the design
>>of a language that for whatever reason has mindshare of a large group of
>>every day programmers.
>
>
> Unfortunately, this is the attitude that has landed us
> with C++ and Java. Both languages build on an existing
> language without doing anything that fixes the failings
> of the language they build on.
huh? I don't understand why you lump Java and C++ in the same bucket.
From a language design Java isn't as horribly broken as C++. Java fixed
several problems with C++.
> C++ and Java are both supposed to be high level languages
> but both still have potentially unsafe casts. This is still
> the case with Java which was based on C++ where I thought
> the lesson should have already been learned.
Java has casts none of them are unsafe/unchecked. If you look into the
history of Java you'll discover that Java has much more in common with
LISP than C++. It has C like syntax mainly because there's really no
point in being different for no good reason.
|
|
0
|
|
|
|
Reply
|
danwang74 (206)
|
6/5/2005 10:10:53 AM
|
|
Gabriel Dos Reis wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
> [...]
>
> | > | Besides, C++ *is* broken.
> | > | | It's broken in theory: parsing is a mess, its semantics is
> | > riddled
> | > | with exceptions and special cases. I already gave constructor issues
> | > | in a recent post, and that's just the start.
> |
> | No objections here. Fine.
>
> Oh no: Absence of reply does not mean agreement or disagreement.
Well, it *would* have helped if you had answered then.
> I just haven't read your constructor issues. From your other
> conversion with Florian, I guess it would have to do with calling
> virtual functions in a constructor. Is that right?
Indeed.
> | > Yes, I said something like that.
> |
> | Actually I didn't quote you,
>
> I think you're (mis)attributing the quote from the website to me :-)
Nope, I'm quoting from your answers.
> | > One problem with very
> | > supporting and protective environments is that the hard problems may
> | > be discovered too late or be too hard to remedy once discovered.
> |
> | That's a real problem in language design.
> |
> | [...]
> | I also think that C++ takes that argument as an excuse for not
> | properly thinking about the consequences of design decisions before
> | unleashing them on an unsuspecting world.
>
> Well, I've been in the trenches for some time to know from experience
> and from those who have been there long before me that your claim is
> largely unfounded. For almost all problems I know of, I don't think
> C++ designers did not properly think about design decision consequences.
I'll readily agree that they spent a great deal of thinking about
consequences. They simply messed up priorities, and took the above
argument as an excuse for not getting it right.
> | Let me give a supporting experience.
> |
> | In my C++ days, I spent 10% of my time designing and 90% coding and
> | debugging.
>
> Then, let me give you counter supportive exprience: I spend 90% of my
> time designing and 10% coding. It is largely known (at least in the
> C++ community, but I would have thought it isn't that language
> specific) that the far vast majority of time spent on project (nearly
> 90%) is on design not code. This is the case for collegues I have
> high (technical) estime for. That certainly is the case of (all?)
> successful C++ project I know of.
Seems like a self-selected sample then - most projects are failures. If
you restrict yourself to projects where people are getting it right, you
automatically exclude those where the language prevented them from being
successful.
> | And C++'s semantics is indeed utterly broken. I haven't even begun to
> | enumerate all the problems with its semantics,
>
> Please do :-) As I said elsewhere, I thought I would be discussing
> semantics intead of angle brackets, curly braces and bananas.
I did, but you didn't pick that up.
Anyway, I didn't want to enter into a detailed discussion of C++'s
problems. If you disagree about the semantic problems, that's fine by me.
You might take interest in Ian Joyner's C++ Critique (accessible in
several places via Google). He's going overboard nitpicking in many
cases, but discounting that you still have an impressive list of
misfeatures.
> | > That does not mean I'm claiming "C++ it nos broken")
> |
> | Yup, I noticed a conspicuous absence of such claims.
> |
> | I'm still wondering what your point actually *is*.
>
> That in the face of the real world, confrontation with reality, the
> notion of "brokenness" is not as clear cut as some theologies are
> putting it.
OK, here's my personal definition:
A language is "broken" wherever it causes or promotes unsafe
programming. This includes things like violations of the principle of
least surprise, encouragement of unsafe practices, or the absence of
safety nets (and making it difficult to install reliable safety nets in
the form of library code).
> I don't believe it is a 0 or 1 thing.
Of course not. Languages can be more or less broken. A certain amount of
breakage seems to be unavoidable - not because a non-broken language is
impossible but because of the way that languages are designed and evolve.
On the other hand, I think that by the above definition, a reasonably
precise estimate of a language's brokenness is possible. For me, on a
scale between 0 and 1, C++'s brokenness ranges somewhere around 0.8, and
that's pretty bad. (RPG IV is 0.97 or something. Pascal would be 0.4,
Eiffel 0.3. Eiffel could be brought to, say, 0.2 - there are principal
limits to what one can to with an imperative dynamic-dispatching
language. C++ has far more room for improvement, but I fear that any
changes for the better would require too much incompatibility.)
> Furthermore, I
> think considerations of the constraints, goals and understanding of the
> problems are essential for making that judgment as objective
> as possible. I just don't make it an axiom :-)
Again: the goals and constraints are secondary for my definition of
brokenness.
Besides, I strongly disagree about the constraints and goals that Bjarne
chose. Not that they were unreasonable - but there was a conspicuous
absense of goals like "regular semantics", "flat learning curve for
programmers-to-be", "pitfall plugging". The result shows it.
> | > | The consensus here is that changing C++ into even a reasonable
> | > | language would require so deep alterations that the result wouldn't be
> | > | C++ anymore, and would be rejected for that reason.
> | > I think there is something that has been missed here. There are at
> | > least two ways of making improvement: (1) radical changes, (2) extend
> | > the language with functionalities that provide for better
> | > alternatives, thus making making the broken part largely
> | > secondary.
> |
> | Well, sure. The problem is that the broken parts of a language remain
> | in use, so it doesn't really fix the problem.
>
> At that point, a question is why they are in use. If there are needs
> that those parts address then, better address those needs than simply
> removing the broken parts -- taking analogy from a previous message,
> the broken mirror is not fixed just because it is thrown away.
<grin> but there is nothing but throwing away that you can do with a
broken mirror.
I'm well aware that every analogy breaks at some point. In particular,
improving C++ isn't an entirely fruitless exercise: it will remain with
us until the next hype washes it away, in a decade or two, and improving
C++ for that period of time can be of help. Just don't expect these
improvement to make computing history.
> If there are in use because of insufficient support from environement
> (better libraries, education, etc.) then it is not a problem of not
> retiring the broken parts. Rather offer better libraiies, education,
> etc.
Programmers will learn only under extreme pressure.
Better libraries are of limited use if the language is broken.
> The report that a language X programmer would spend 90% of its time
> coding and 10% designing is effectivelly worrisome, but that is barely
> the language fault. I think it is more a problem of experience or
> "education" (please, this is *no* insult) than an inherent brokenness
> of the language.
If a language requires 5+ years for getting to that point, it's an
economic disaster.
For a comparison, in Eiffel, I started with 50% design and 50% coding;
after half a year, I was at 65% and 35%, arriving at the 70/30 ratio I
alluded to in the end.
(A 90/10 ratio was unattainable for the kind of stuff we were doing: it
was a GUI library that tried to regularize the Windows controls' APIs.)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 10:23:49 AM
|
|
"Daniel C. Wang" <danwang74@gmail.com> writes:
> Java has casts none of them are unsafe/unchecked. If you look into the
> history of Java you'll discover that Java has much more in common with
> LISP than C++. It has C like syntax mainly because there's really no
> point in being different for no good reason.
Java indeed doesn't have operations which lead to undefined behavior,
but it too doesn't detect some obvious errors in the name of efficiency:
arithmetic overflow.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/5/2005 10:28:10 AM
|
|
Daniel C. Wang wrote:
> Just to fan the flames a bit more... I'm wonder what people think about
> "D" http://www.digitalmars.com/d/
> It seems a very serious attempted to "fix" C++ by starting from scratch.
> It seems to lack a multi-million dollar marketing buget.. but beyond
> that.. it seems quite mature...
Not powerful enough: no multiple inheritance.
Not flexible enough: no dynamic class loading. (That's a hard problem
though.)
Nit to pick: yet another string concatenation operator. (Ah, you can't
use & or . in a C-style language.)
Good: contracts. Seems like solid basic support, though one could add
all sorts of fancy things.
In all, it seems a reasonable point on the engineering trade-off spectrum.
Just a first impression. The devil is often in the details (well, for
C++, it was also in the grand picture.)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 10:42:15 AM
|
|
Daniel C. Wang wrote:
> Or to say it more generically, if one wanted to actually improve the
> state of programming languages for your every day hacker today, where
> should a language designer put their effort?
>
> C++,
> D,
> Java,
> C#
>
> Note that C# and Java both recently picked up generics in a relatively
> principled way. Given that C# and Java both have large multi-billion
> dollar companies behind them with vested interests and C++ seems
> unpalatable to many is D a good platform for language designers?
I think that D, Java, and C# are roughly equivalent: solid enough for
useful work.
Politically, Java is probably the best platform. It's well-supported and
here to stay.
Working with C++ requires a whole lot of arcane knowledge and black
magic. You'd probably end up spending so much thought space on C++ that
your mind isn't open for real improvements anymore.
> I haven't mentioned any functional languages, because I'm becoming
> skeptical that they will have an real *direct* impact on programming for
> your average joe/jane programmer. I suspect they'll have a much bigger
> indirect impact in the long run.
I like to think (read: hope) that they will be the next big hype.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 11:01:49 AM
|
|
Florian Weimer wrote:
> * Joachim Durchholz:
>
>>> What do you propose as an alternative? Partially constructed
>>> objects?
>>
>> Let the object be created as a member of its target class. The
>> constructor is obliged to fill it with data that fulfills the
>> class's invariant. In particular, it's obliged to fill in enough
>> data before calling functions that depend on that data - but that's
>> normal with any kind of step-by-step initialisation.
>
> So you'd like to disallow calling virtual member functions from the
> constructor altogether?
No, that's a decision for the programmer to make. He shouldn't do
virtual calls until the preconditions for those calls are met.
(This isn't too bad. Been there, done that.)
>> Besides, initialisation is rarely a serious problem.
>
> Tell that to someone who had to fight with circular dependencies
> among singletons.
That's initialisation of large global data structures. I don't think
that the way constructors work have any influence on that problem - it's
a hard problem by nature.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 11:07:52 AM
|
|
Florian Weimer wrote:
> * Joachim Durchholz:
>
>>Why that emphasis on free parsers? Because they tend to be done by small
>>teams or single persons. C++ is too complicated to be tackled if
>>manpower is limited. In fact gcc strenthens that point: the only free
>>software that handles C++ is gcc, a multi-person-century project;
>
> The current C++ parser was written by Mark Mitchell. AFAIK, it took
> him much less than two person-years to write it. Gaby might have
> better figures.
Ah, then things have changed. It's been a while since I frequented
comp.compilers.
Two man-years is still an impressive figure though... parsers for
languages like SML or Eiffel are more like man-weeks. And I can't
convince myself that several orders of magnitude of increased difficulty
are really worth the results.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 11:10:15 AM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
>>> Besides, initialisation is rarely a serious problem.
>> Tell that to someone who had to fight with circular dependencies
>> among singletons.
>
> That's initialisation of large global data structures. I don't think
> that the way constructors work have any influence on that problem -
> it's a hard problem by nature.
I'm not sure it's such a hard problem by nature. Could you give an
example where it's hard conceptually, yet possible at all? I want to
see how my language would solve that.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/5/2005 11:38:11 AM
|
|
Marcin 'Qrczak' Kowalczyk wrote:
> Joachim Durchholz <jo@durchholz.org> writes:
>
>>>>Besides, initialisation is rarely a serious problem.
>>>
>>>Tell that to someone who had to fight with circular dependencies
>>>among singletons.
>>
>>That's initialisation of large global data structures. I don't think
>>that the way constructors work have any influence on that problem -
>>it's a hard problem by nature.
>
> I'm not sure it's such a hard problem by nature. Could you give an
> example where it's hard conceptually, yet possible at all? I want to
> see how my language would solve that.
Not off the top of my head. I had similar problems only with large programs.
I think it's a problem with circularly dependent globals being
initialised. Programmers assume that globals are always available, and
that assumption clearly breaks during initialisation, so that's an
intrinsically hard problem.
OTOH circular dependencies are an indicator that the module structure is
wrong: most of the time, it's not the modules in their entirety but just
some specific parts of them that are circularly dependent. Those
entities should go into a common base module so that the circular
dependency becomes local and tractable.
Another way to circumvent the problem is by ad-hoc initialisation: the
module fully initialises itself only on first call, and only to the
extent needed for a given task. If that still remains a circular
dependency, you actually have a cross-module endless recursion, which is
a conceptual error anyway :-)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 11:48:33 AM
|
|
Florian Weimer wrote:
> Python is only non-broken if you don't care for efficiency. It's
> very, very hard to create an optimizing Python compiler, much harder
> than for Lisp, and you are tied to reference counting and can't use a
> modern garbage collector.
Nothing in the Python language specification requires reference counting.
Don't confuse the CPython implementation with the language. Jython has
full GC.
--
David Hopwood <david.nospam.hopwood@blueyonder.co.uk>
|
|
0
|
|
|
|
Reply
|
david.nospam.hopwood (121)
|
6/5/2005 2:15:18 PM
|
|
Joachim Durchholz wrote:
> OTOH circular dependencies are an indicator that the module structure is
> wrong: most of the time, it's not the modules in their entirety but just
> some specific parts of them that are circularly dependent. Those
> entities should go into a common base module so that the circular
> dependency becomes local and tractable.
Why? I've seen this opinion expressed from time to time but never seen
a convincing justification. Mutual recursion between modules (or some
of the entities defined in those modules) is perfectly reasonable,
natural and useful.
IMNSHO this is merely folklore promulgated by language designers
and/or implementors that can't be bothered to fix their compilers to
handle mutual recursion properly :-)
Regards
--
Adrian Hey
|
|
0
|
|
|
|
Reply
|
ahey (217)
|
6/5/2005 2:38:22 PM
|
|
Adrian Hey wrote:
> Joachim Durchholz wrote:
>
>>OTOH circular dependencies are an indicator that the module structure is
>>wrong: most of the time, it's not the modules in their entirety but just
>>some specific parts of them that are circularly dependent. Those
>>entities should go into a common base module so that the circular
>>dependency becomes local and tractable.
>
> Why? I've seen this opinion expressed from time to time but never seen
> a convincing justification. Mutual recursion between modules (or some
> of the entities defined in those modules) is perfectly reasonable,
> natural and useful.
I agree that mutual recursion between modules can be useful.
However, the kind of recursion that creates initialisation agonies is
typically caused by wrong modularisation.
> IMNSHO this is merely folklore promulgated by language designers
> and/or implementors that can't be bothered to fix their compilers to
> handle mutual recursion properly :-)
Well, initialisation is an issue only with global variables, so I
suspect the real problem is indeed not in recursion but in globals. But
then we were dealing with practical languages, warts and all...
Regards,
jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 2:51:13 PM
|
|
Gabriel Dos Reis wrote:
> "Daniel C. Wang" <danwang74@gmail.com> writes:
>
> | Just to fan the flames a bit more... I'm wonder what people think
> | about "D" http://www.digitalmars.com/d/
> | It seems a very serious attempted to "fix" C++ by starting from scratch.
>
> Google for discussions about D and C++ on C++ newsgroups ;-)
<http://groups.google.co.uk/groups?as_q=D+language&num=100&as_ugroup=comp.lang.c%2B%2B.*>
As might be expected, that search gets you mostly noise. OTOH, the first thread
seems to be quite positive about D. What was your point?
--
David Hopwood <david.nospam.hopwood@blueyonder.co.uk>
|
|
0
|
|
|
|
Reply
|
david.nospam.hopwood (121)
|
6/5/2005 3:29:28 PM
|
|
Erik de Castro Lopo wrote:
> "Daniel C. Wang" wrote:
>
>>Hmm.. my question was not what would be the best language that you would
>>enjoy programming in, but where can one have a big impact on the design
>>of a language that for whatever reason has mindshare of a large group of
>>every day programmers.
>
> Unfortunately, this is the attitude that has landed us
> with C++ and Java. Both languages build on an existing
> language without doing anything that fixes the failings
> of the language they build on.
>
> C++ and Java are both supposed to be high level languages
> but both still have potentially unsafe casts. This is still
> the case with Java which was based on C++ where I thought
> the lesson should have already been learned.
What precisely do you mean by unsafe here? Java, unlike C++, is
strongly typed:
- all constructs have well-defined behaviour,
- the run-time type of the content of any variable is always
consistent with its declared type,
- type errors can only occur in constructs where they are documented
to occur (e.g. casts, array stores, etc.), and in that case they
result in an exception.
Note that I'm not particularly defending the overall design of Java's
type system, just wondering why you call it unsafe.
--
David Hopwood <david.nospam.hopwood@blueyonder.co.uk>
|
|
0
|
|
|
|
Reply
|
david.nospam.hopwood (121)
|
6/5/2005 4:03:12 PM
|
|
Marcin 'Qrczak' Kowalczyk wrote:
{stuff deleted}
>
> Java indeed doesn't have operations which lead to undefined behavior,
> but it too doesn't detect some obvious errors in the name of efficiency:
> arithmetic overflow.
Java had bignums and even BCD based bignums for those who care. I think,
SML is the only language I know of which requires trapping arithmitic on
the native int type. heck, if I'm not mistaken even OCaml doesn't trap!
Anyway, the overflow issue hardly makes the language broken.
|
|
0
|
|
|
|
Reply
|
danwang74 (206)
|
6/5/2005 5:04:44 PM
|
|
Joachim Durchholz wrote:
{stuff deleted}
> Not powerful enough: no multiple inheritance.
It has interfaces ala Java. I consider the lack of multiple inheritance
a feature. (Guess, you can't make everyone happy..)
> Not flexible enough: no dynamic class loading. (That's a hard problem
> though.)
A practial problem, but it can load libraries dyanmically as much as a C
and C++ program can.
> Nit to pick: yet another string concatenation operator. (Ah, you can't
> use & or . in a C-style language.)
> Good: contracts. Seems like solid basic support, though one could add
> all sorts of fancy things.
>
> In all, it seems a reasonable point on the engineering trade-off spectrum.
My impression too.. which was why I brought it up. Compared to C++ it
does not seem so horribly broke, and it is amining at a similar niche as
C++.
> Just a first impression. The devil is often in the details (well, for
> C++, it was also in the grand picture.)
|
|
0
|
|
|
|
Reply
|
danwang74 (206)
|
6/5/2005 5:09:36 PM
|
|
"Daniel C. Wang" <danwang74@gmail.com> writes:
> Java had bignums and even BCD based bignums for those who care.
> I think, SML is the only language I know of which requires trapping
> arithmitic on the native int type.
In C# and Turbo Pascal checking is switchable. I don't know Delphi,
but perhaps it's like in Turbo Pascal.
In many languages bignums are produced automatically when fixnums
overflow: Lisp, Scheme, Erlang, Python (used to be an exception),
Ruby, Smalltalk.
Java bignums are awkward to use because arithmetic and comparisons
must look as method calls. They are also less efficient than a
combination of fixnums and bignums because they must all be allocated
dynamically.
It seems that dynamic typing promotes arithmetic safety. Most
dynamically typed languages don't have integers constrained to machine
word size, while most statically typed ones make wrapping-around or
at most exception-throwing limited ints the default.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/5/2005 6:09:21 PM
|
|
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
> It seems that dynamic typing promotes arithmetic safety. Most
> dynamically typed languages don't have integers constrained to machine
> word size, while most statically typed ones make wrapping-around or
> at most exception-throwing limited ints the default.
I'm not going to argue about "most" languages, but isn't statically
typed languages using arbitrary precision integers fairly equivalent
to dynamically typed ones?
-kzm
--
If I haven't seen further, it is by standing in the footprints of giants
|
|
0
|
|
|
|
Reply
|
news2 (145)
|
6/5/2005 6:15:31 PM
|
|
Marcin 'Qrczak' Kowalczyk wrote:
{stuff deleted}
> It seems that dynamic typing promotes arithmetic safety. Most
> dynamically typed languages don't have integers constrained to machine
> word size, while most statically typed ones make wrapping-around or
> at most exception-throwing limited ints the default.
Arithmetic safety is not needed for type-safety. For applications that
require the performance hit needed for arithmetic safety they should
have a way out. However, using an infinite precision rep by default
seems to be wrong headed with respect to performance. In general most
dynamic programming language trade off conveince for performance.
Sometimes this is not the right tradeoof and performance should be
considered. In anycase Java seems to have a resonable solution to the
issue.
|
|
0
|
|
|
|
Reply
|
danwang74 (206)
|
6/5/2005 6:39:40 PM
|
|
Ketil Malde <ketil+news@ii.uib.no> writes:
>> It seems that dynamic typing promotes arithmetic safety. Most
>> dynamically typed languages don't have integers constrained to machine
>> word size, while most statically typed ones make wrapping-around or
>> at most exception-throwing limited ints the default.
>
> I'm not going to argue about "most" languages, but isn't statically
> typed languages using arbitrary precision integers fairly equivalent
> to dynamically typed ones?
Yes, in theory. But in practice in most of them arbitrary precision
integers look much more awkward than machine word integers (C, Java,
SML, OCaml), or while in theory they could integrate well, the
standard language doesn't provide them at all (C++, Clean).
The only statically typed language I know where arbitrary precision
integers are as convenient as machine word integers is Haskell.
I don't know about C#, Eiffel and Mercury. They all should be able to
suppor them well, but I don't know whether they actually do (and I'm
too lazy to check now).
Also, they are usually less efficient than in dynamically typed
languages, because in latter ones it's very common to represent small
integers unboxed, tagged in some bits, and only large integers as
pointers. Yes, it's a special case in the runtime, but it's common
enough to be worth the effort.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/5/2005 7:23:39 PM
|
|
Marcin 'Qrczak' Kowalczyk wrote:
> "Daniel C. Wang" <danwang74@gmail.com> writes:
>
>
>>Java had bignums and even BCD based bignums for those who care.
>>I think, SML is the only language I know of which requires trapping
>>arithmitic on the native int type.
>
> In C# and Turbo Pascal checking is switchable. I don't know Delphi,
> but perhaps it's like in Turbo Pascal.
It's switchable in Delphi IIRC.
> It seems that dynamic typing promotes arithmetic safety. Most
> dynamically typed languages don't have integers constrained to machine
> word size, while most statically typed ones make wrapping-around or
> at most exception-throwing limited ints the default.
That's probably a consequence of having incurred some representational
overhead already, so overflowing into bignums isn't a big incremental
overhead anymore.
Regards,
Jo
would like static typing and arithmetic safety combined
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 10:06:07 PM
|
|
Marcin 'Qrczak' Kowalczyk wrote:
> I don't know about C#, Eiffel and Mercury. They all should be able to
> suppor them well, but I don't know whether they actually do (and I'm
> too lazy to check now).
Eiffel doesn't. It was compiling to C, and simply inherited C's
arithmetic properties.
Large integer types do exist as library classes, but they aren't
integrated into the standard integer type in any way.
Some Eiffel implementations offer various machine integer types,
together with some ad-hoc transformation rules.
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/5/2005 10:08:56 PM
|
|
Marcin 'Qrczak' Kowalczyk wrote:
> It seems that dynamic typing promotes arithmetic safety. Most
> dynamically typed languages don't have integers constrained to machine
> word size, while most statically typed ones make wrapping-around or
> at most exception-throwing limited ints the default.
This is a correlation between preferences of language designers; it
doesn't indicate any necessary dependence between the language features.
--
David Hopwood <david.nospam.hopwood@blueyonder.co.uk>
|
|
0
|
|
|
|
Reply
|
david.nospam.hopwood (121)
|
6/5/2005 11:03:51 PM
|
|
"Gabriel Dos Reis" <gdr@integrable-solutions.net> wrote in message
news:m3mzq51mu5.fsf@uniton.integrable-solutions.net...
> "Daniel C. Wang" <danwang74@gmail.com> writes:
>
> | Just to fan the flames a bit more... I'm wonder what people think
> | about "D" http://www.digitalmars.com/d/
> | It seems a very serious attempted to "fix" C++ by starting from scratch.
>
> Google for discussions about D and C++ on C++ newsgroups ;-)
There are also tens of thousands of messages on the D newsgroups at
news.digitalmars.com. Google refuses to index it, but that's for the good,
as it flies below the radar of the spammers <g>.
> | It seems to lack a multi-million dollar marketing buget..
True. The D marketing budget is $0. The progress D is making is entirely due
to the volunteer efforts of the D community.
|
|
0
|
|
|
|
Reply
|
walter22 (98)
|
6/6/2005 7:15:44 AM
|
|
"Gabriel Dos Reis" <gdr@integrable-solutions.net> wrote in message
news:m31x7hsa8q.fsf@uniton.integrable-solutions.net...
> I was merely pointing out that as in the case of D you're reporting,
> AT&T did not put $$$ marketing budget behind C++.
AT&T did the best, most effective kind of marketing - they paid the salaries
of brilliant engineers like Andrew Koenig and Bjarne Stroustrup as they
worked on and evangelized C++. I read their papers and attended their
presentations in C++'s early days, and they were very, very effective.
|
|
0
|
|
|
|
Reply
|
walter22 (98)
|
6/6/2005 7:22:22 AM
|
|
"Joachim Durchholz" <jo@durchholz.org> wrote in message
news:d7uku7$c0a$1@online.de...
> Not powerful enough: no multiple inheritance.
It'll do multiple inheritance of interfaces. Yes, this isn't full multiple
inheritance as practiced by C++.
> Nit to pick: yet another string concatenation operator. (Ah, you can't
> use & or . in a C-style language.)
A lot of people are at first put off by using ~ as an array concatenation
operator, and ~= as array append. The fun thing is, though, is once you
write a bit of code with it, it's the other operators like & and + for
concatenation that seem wrong.
After all, array concatenation is conceptually nothing like "and" or "add".
If you had a vector of floats, and you used '+' on two of them, would you
get a concatenation or an element-wise add? I submit that the latter is what
one would expect. Overloading '+' to mean "add" in some contexts, and
"concatenate" in others is needless confusion.
-Walter
www.digitalmars.com/d/ the D Programming Language
|
|
0
|
|
|
|
Reply
|
walter22 (98)
|
6/6/2005 7:30:26 AM
|
|
Walter wrote:
> "Joachim Durchholz" <jo@durchholz.org> wrote in message
> news:d7uku7$c0a$1@online.de...
>
>> Not powerful enough: no multiple inheritance.
>
> It'll do multiple inheritance of interfaces. Yes, this isn't full multiple
> inheritance as practiced by C++.
Exactly. Interfaces are the poor designer's excuse. "Sorry, we don't
understand MI properly, please roll your own."
>>Nit to pick: yet another string concatenation operator. (Ah, you can't
>>use & or . in a C-style language.)
>
> A lot of people are at first put off by using ~ as an array concatenation
> operator, and ~= as array append. The fun thing is, though, is once you
> write a bit of code with it, it's the other operators like & and + for
> concatenation that seem wrong.
That's normal: those operators that you don't use on a day-to-day basis
first start to look strange, then wrong.
> After all, array concatenation is conceptually nothing like "and" or "add".
Well, yes, if you think that & is bitwise and. I recall & being used as
concatenation operator, and * for set intersection (which is the proper
semantics of bitwise and, and indeed has analogies with multiplication).
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/6/2005 8:51:14 PM
|
|
"Joachim Durchholz" <jo@durchholz.org> wrote in message
news:d82d03$pq1$1@online.de...
> Walter wrote:
> > "Joachim Durchholz" <jo@durchholz.org> wrote in message
> > news:d7uku7$c0a$1@online.de...
> >
> >> Not powerful enough: no multiple inheritance.
> > It'll do multiple inheritance of interfaces. Yes, this isn't full
multiple
> > inheritance as practiced by C++.
> Exactly. Interfaces are the poor designer's excuse. "Sorry, we don't
> understand MI properly, please roll your own."
Since I've written a C++ compiler that does MI, and I know exactly how it
works, I'm afraid you'll need another reason <g>.
> > After all, array concatenation is conceptually nothing like "and" or
"add".
> Well, yes, if you think that & is bitwise and.
Even if you think of & as a logical and, it still doesn't imply
concatenation.
> I recall & being used as
> concatenation operator, and * for set intersection (which is the proper
> semantics of bitwise and, and indeed has analogies with multiplication).
None of the existing C or C++ operators makes any logical sense for
concatenation. That's why D uses a new one.
-Walter
www.digitalmars.com C, C++, D compilers
|
|
0
|
|
|
|
Reply
|
walter22 (98)
|
6/6/2005 9:28:36 PM
|
|
Joachim Durchholz wrote:
> Walter wrote:
>
>> "Joachim Durchholz" <jo@durchholz.org> wrote in message
>> news:d7uku7$c0a$1@online.de...
>>
>>> Not powerful enough: no multiple inheritance.
>>
>>
>> It'll do multiple inheritance of interfaces. Yes, this isn't full
>> multiple
>> inheritance as practiced by C++.
>
>
> Exactly. Interfaces are the poor designer's excuse. "Sorry, we don't
> understand MI properly, please roll your own."
I know zip about D, but I should say that it's been maybe a decade since
I've used multiple inheritance in C++. In some strange sense that I have
yet to be able to articulate, templates have made multiple inheritance
unnecessary. Inheritance plus virtual functions is purely about
type-safe dynamic dispatch. Inheritance in and of itself, I have become
convinced, is a distraction.
[...]
-thant
--
We have now sunk to a depth at which restatement of the obvious is the
first duty of intelligent men. -- George Orwell (attributed)
|
|
0
|
|
|
|
Reply
|
thant (330)
|
6/6/2005 9:31:44 PM
|
|
Walter wrote:
> "Joachim Durchholz" <jo@durchholz.org> wrote in message
> news:d82d03$pq1$1@online.de...
>
>> Walter wrote:
>>
>>> "Joachim Durchholz" <jo@durchholz.org> wrote in message
>>> news:d7uku7$c0a$1@online.de...
>>>
>>>
>>>> Not powerful enough: no multiple inheritance.
>>>
>>> It'll do multiple inheritance of interfaces. Yes, this isn't full
>>>
>
> multiple
>
>>> inheritance as practiced by C++.
>>
>> Exactly. Interfaces are the poor designer's excuse. "Sorry, we
>> don't understand MI properly, please roll your own."
>
> Since I've written a C++ compiler that does MI, and I know exactly
> how it works, I'm afraid you'll need another reason <g>.
C++ doesn't get it right anyway.
Eiffel comes close but doesn't handle it correctly, too. See
http://durchholz.org/jo/eiffel-critique/replicated-inheritance.html for
a discussion of the issues involved.
Note that that page originally was a part of an Eiffel critique that I
never finished. This is partly a liability (because it spends a good
deal of discussion and critique of Eiffel specifics), and partly a boon
(it uses assertions and DbC as a kind of Occam's razor to infer
relatively rigidly what MI really should do). There's also a formatting
foul-up that I'm just too lazy to fix right now ;-)
>>> After all, array concatenation is conceptually nothing like "and"
>>> or "add".
>>
>> Well, yes, if you think that & is bitwise and.
>
> Even if you think of & as a logical and, it still doesn't imply
> concatenation.
No, I've been thinking of it as concatenation :-)
>> I recall & being used as concatenation operator, and * for set
>> intersection (which is the proper semantics of bitwise and, and
>> indeed has analogies with multiplication).
>
> None of the existing C or C++ operators makes any logical sense for
> concatenation. That's why D uses a new one.
Indeed. I just wanted to say that & would be a good choice since it's
used for concatenation in other languages, except that & already has a
different meaning in C-style languages (and the same goes for ".").
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/6/2005 9:42:42 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
>The
>standard strategy for compiling FPLs nowadays seems to be machine code
>generation.
That depends on what you intend "nowadays" to mean. I see plenty of systems
using both approaches.
>Contrary to popular belief, C is not a good portable assembler.
It is clear that C is not a perfect portable assembler, and equally clear
that it is at least an adequate portable assembler for many purposes.
However, that is not the actual question. The actual question is: is it
better to generate C than to generate assembler?
The advantages of generating assembler:
speed
possibly size
direct access to all hardware features (not usually very important)
control over low level details; e.g. can generate map from function
names to locations for a specialized debugger
The advantages of generating C:
portability (significant even today, as the lack of x86-64 code
generators for languages that target assembler demonstrates;
may not be very significant in a few years)
don't have to write the parts of the compiler that are very close
to the metal (instruction selection, exploiting pipelining,
register allocation etc); important since the "metal" (the
chip microarchitectures) are constantly changing
don't have to write the parts of the compiler that work with the linker
(don't have to even know what the object file format is)
can exploit existing infrastructure for debugging generated code
when debugging the compiler
even easier to create interoperability with C code
Which you choose depends on your objectives and limitations.
How great the speed of advantage of assembler is depends on how much effort
you put into the code generator that generates assembler. If you do a minimum
job, it is very likely that generating C will yield faster code. The lack
of tail call optimization in C need not be a problem. It is easy to compile
tail recursion into while loops, only slightly harder to compiler mutual tail
recursion into while loops, and one can avoid mapping calls in the source
language into calls in C by using GNU C extensions (taking the addresses
of labels).
Zoltan Somogyi <zs@cs.mu.OZ.AU> http://www.cs.mu.oz.au/~zs/
Department of Computer Science and Software Engineering, Univ. of Melbourne
|
|
0
|
|
|
|
Reply
|
zs22 (13)
|
6/8/2005 8:46:38 AM
|
|
Zoltan Somogyi wrote:
>
> direct access to all hardware features (not usually very important)
Such access can be important e.g. for implementing overflow checks
efficiently etc., or in the same vein, optimised representations for
infinite precision integers, as we have been discussing.
> The lack
> of tail call optimization in C need not be a problem. It is easy to compile
> tail recursion into while loops, only slightly harder to compiler mutual tail
> recursion into while loops, and one can avoid mapping calls in the source
> language into calls in C by using GNU C extensions (taking the addresses
> of labels).
Right, but this still means that general tail calls cannot be
implemented in Standard C. Moreover, the GCC label trick requires coding
up your own parameter passing, stack management and register allocation,
effectively giving up the most important advantages of using an
intermediate compiler. It is also likely to be less efficient (and
tuning it will again be highly platform-specific). And how good does it
scale to separate compilation?
But of course, there is C--, which addresses all these deficiencies.
Cheers,
- Andreas
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
|
|
0
|
|
|
|
Reply
|
rossberg (600)
|
6/8/2005 11:21:50 AM
|
|
"Zoltan Somogyi" <zs@students.cs.mu.OZ.AU> wrote in message
news:42a6b06b$1@news.unimelb.edu.au...
> The advantages of generating assembler:
>
> speed
> possibly size
> direct access to all hardware features (not usually very important)
> control over low level details; e.g. can generate map from function
> names to locations for a specialized debugger
You forgot a few
1) Proper tail recursion, and some langauges require this.
2) Compatability with the garbage collection system. Some garbage collection
systems require particular stack layouts and particular use of registers.
3) Maintanence of other invariants that are needed for the runtime system.
(e.g. exception handling). I know of at least one system where they manage
to maintain these invaraints using C, but only when all compiler
optimazations (and I mean ALL) are turned off.
4) Handling of optional parameters, keyword parameters, and other types of
parameters that C doesn't have.
Some stuff I don't know about, but I guess are tricky in C.
Full closures, though I guess with enough pointers you can get around this.
Coroutines (longjump? How do you maintain the multiple stacks? Does PORTABLE
C support this?)
Rene.
|
|
0
|
|
|
|
Reply
|
Rene_de_Visser (48)
|
6/8/2005 11:26:31 AM
|
|
Zoltan Somogyi <zs@students.cs.mu.OZ.AU> writes:
> The lack of tail call optimization in C need not be a problem.
> It is easy to compile tail recursion into while loops, only slightly
> harder to compiler mutual tail recursion into while loops, and one
> can avoid mapping calls in the source language into calls in C by
> using GNU C extensions (taking the addresses of labels).
I wouldn't know how to do separate compilation and indirect jumps
using addresses of labels.
Here is what my compiler is doing (the design is based on GHC):
The portable version uses the well known trampoline trick, where each
function returns a function pointer which it wishes to jump to, and a
central interpreter loop repeatedly calls a function, then its result
etc. until exited by longjmp.
Then on selected platforms (x86 and x86_64) a Perl script translates
the assembler output of the C compiler, and converts returning a
function pointer into a direct jump (this is not always trivial,
e.g. jumps into a common epilogue are replaced with duplicated code).
Such jumps are marked by a comment in inline asm so the Perl script
can distinguish them from other function returns.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/8/2005 11:36:37 AM
|
|
"Rene de Visser" <Rene_de_Visser@hotmail.de> writes:
> 1) Proper tail recursion, and some langauges require this.
> 2) Compatability with the garbage collection system. Some garbage collection
> systems require particular stack layouts and particular use of registers.
> 3) Maintanence of other invariants that are needed for the runtime system.
> (e.g. exception handling). I know of at least one system where they manage
> to maintain these invaraints using C, but only when all compiler
> optimazations (and I mean ALL) are turned off.
> 4) Handling of optional parameters, keyword parameters, and other types of
> parameters that C doesn't have.
This can all be implemented portably in C; I've done this. C can be
used as an assembler.
> Some stuff I don't know about, but I guess are tricky in C. Full
> closures, though I guess with enough pointers you can get around
> this. Coroutines (longjump? How do you maintain the multiple stacks?
> Does PORTABLE C support this?)
Managing our own stack solves many problems at once: finding pointers
for GC, exception handling, threads, stack reallocation on overflow.
It includes a constant cost (e.g. the stack pointer is in a global
variable instead of a physical register), but it's worth the effort
if we want a language which does things C cannot do well directly,
like the above.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/8/2005 12:50:02 PM
|
|
Marcin 'Qrczak' Kowalczyk wrote:
> "Rene de Visser" <Rene_de_Visser@hotmail.de> writes:
>
>
>>1) Proper tail recursion, and some langauges require this.
>>2) Compatability with the garbage collection system. Some garbage collection
>>systems require particular stack layouts and particular use of registers.
>>3) Maintanence of other invariants that are needed for the runtime system.
>>(e.g. exception handling). I know of at least one system where they manage
>>to maintain these invaraints using C, but only when all compiler
>>optimazations (and I mean ALL) are turned off.
>>4) Handling of optional parameters, keyword parameters, and other types of
>>parameters that C doesn't have.
>
> This can all be implemented portably in C; I've done this. C can be
> used as an assembler.
You have my unlimited adoration :-)
However, having to live with C's restrictions imposes design constraints
on an already (usually) over-constrained system. Having too many goals
usually ends up with achieving none in a satisfactory fashion.
>>Some stuff I don't know about, but I guess are tricky in C. Full
>>closures, though I guess with enough pointers you can get around
>>this. Coroutines (longjump? How do you maintain the multiple stacks?
>>Does PORTABLE C support this?)
>
> Managing our own stack solves many problems at once: finding pointers
> for GC, exception handling, threads, stack reallocation on overflow.
> It includes a constant cost (e.g. the stack pointer is in a global
> variable instead of a physical register), but it's worth the effort
> if we want a language which does things C cannot do well directly,
> like the above.
Yup. Not relying on C's stack seems to solve most problems. At the
expense of some additional overhead.
However, what I had in mind were other things, most notably C's overflow
behavior. There's no way to efficiently check for integer overflow in C,
and it's indispensable if you want reliability of any kind.
Of course, instead of compiling to machine code, it may be easier to
simply require an assembly-language integer package that's linked to the
C code.
.... oops, I should write while thinking. I'm not sure whether C
compilers can inline assembly modules. Probably they can't, in which
case the function call overhead is rather prohibitive. (OTOH one could
do everything with GMP and ignore the overhead. We're not after speed
when compiling to C...)
Regards,
Jo
|
|
0
|
|
|
|
Reply
|
jo427 (1164)
|
6/8/2005 8:16:18 PM
|
|
Joachim Durchholz <jo@durchholz.org> writes:
> However, what I had in mind were other things, most notably C's
> overflow behavior. There's no way to efficiently check for integer
> overflow in C, and it's indispensable if you want reliability of any
> kind.
This doesn't generate optimal code but I don't know any better
portable way (it assumes two's complement arithmetic and should better
be compiled with -fwrapv on new gcc):
small = x + y;
return (~(x ^ y) & (small ^ x)) >= 0) ? small : add_to_bignum(x, y);
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/8/2005 8:53:58 PM
|
|
Andreas Rossberg <rossberg@ps.uni-sb.de> writes:
>Zoltan Somogyi wrote:
>> direct access to all hardware features (not usually very important)
>Such access can be important e.g. for implementing overflow checks
>efficiently etc., or in the same vein, optimised representations for
>infinite precision integers, as we have been discussing.
Which is why I wrote "not usually very important" instead of "not important".
>Moreover, the GCC label trick requires coding
>up your own parameter passing, stack management and register allocation,
>effectively giving up the most important advantages of using an
>intermediate compiler.
It gives up some of the advantages. I have found the remaining advantages
to be sufficient to still choose to generate C.
> It is also likely to be less efficient (and
>tuning it will again be highly platform-specific).
I conceded up front that assembler is likely to be somewhat faster in raw
speed. However, the time you save not having to write a pipeline scheduler
can be used to implement higher level optimizations.
Only a small fraction of all the optimizations in the Mercury compiler
do stuff that the C compiler would also do. Short circuiting jumps and
peephole optimization are the main ones, and they mostly work at a higher
level than C could. There is only one optimization that is at all platform
specific: it generates code that runs faster on machines with delayed jumps,
such as SPARC. The module that implements it is a whopping 81 lines in length,
including comments.
It has been a long time since I have looked at the assembly code generated
by the C compiler for code that was originally Mercury. The reason for that
is that when I did, I didn't see any room for speeding it up by more than
about 10%-15% in the general case, and that only by essentially implementing
the back end of a conventional compiler. (There was one big exception to this:
code that handles floating point. However, that has never been very important
to us.) Now that we use mostly x86s, which are register starved, the possible
gains would be significantly higher, but unfortunately so would the costs :-(
>And how good does it
>scale to separate compilation?
In the case of Mercury, perfectly. The Mercury compiler has about 300 modules,
so it better :-)
>But of course, there is C--, which addresses all these deficiencies.
It didn't exist for many years after we started working on Mercury.
Zoltan Somogyi <zs@cs.mu.OZ.AU> http://www.cs.mu.oz.au/~zs/
Department of Computer Science and Software Engineering, Univ. of Melbourne
|
|
0
|
|
|
|
Reply
|
zs22 (13)
|
6/9/2005 5:22:25 AM
|
|
"Rene de Visser" <Rene_de_Visser@hotmail.de> writes:
>> The advantages of generating assembler:
>>
>> speed
>> possibly size
>> direct access to all hardware features (not usually very important)
>> control over low level details; e.g. can generate map from function
>> names to locations for a specialized debugger
>You forgot a few
>1) Proper tail recursion, and some langauges require this.
Not an advantage of assembler, since you can also provide the same guarantees
if you generate C. You may have to work a bit harder.
>2) Compatability with the garbage collection system. Some garbage collection
>systems require particular stack layouts and particular use of registers.
>3) Maintanence of other invariants that are needed for the runtime system.
>(e.g. exception handling). I know of at least one system where they manage
>to maintain these invaraints using C, but only when all compiler
>optimazations (and I mean ALL) are turned off.
These are the kinds of things I meant by "control over low level detail".
>4) Handling of optional parameters, keyword parameters, and other types of
>parameters that C doesn't have.
If you don't map calls in the source language to calls in C this is not
a problem. Remember, you don't have to generate idiomatic C; you can generate
assembler in C syntax.
Zoltan Somogyi <zs@cs.mu.OZ.AU> http://www.cs.mu.oz.au/~zs/
Department of Computer Science and Software Engineering, Univ. of Melbourne
|
|
0
|
|
|
|
Reply
|
zs22 (13)
|
6/9/2005 5:25:41 AM
|
|
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
>> The lack of tail call optimization in C need not be a problem.
>> It is easy to compile tail recursion into while loops, only slightly
>> harder to compiler mutual tail recursion into while loops, and one
>> can avoid mapping calls in the source language into calls in C by
>> using GNU C extensions (taking the addresses of labels).
>I wouldn't know how to do separate compilation and indirect jumps
>using addresses of labels.
We have been doing it for ten years. You generate assembler code in labeled
blocks, and don't worry too much about which labels go in which function.
(It doesn't matter, except for C compilation speed, since you also generate
code that never accesses any variables local to the C function it is in.)
Next to every local label, you add a piece of assembly code that takes the
label name, creates a global variant of the name (we do it by sticking
something like "_entry_mercury" at the front) and provides a .globl
pseudo-op for that label. This allows code in other modules to refer
to the label as long as they follow the same algorithm for computing
its global name.
There is a significant amount of trickery that you have to have with this,
whose main aim is to make sure that the C compiler doesn't believe it can
optimize away any of the functions that are never called or any of the code
inside functions that don't have local gotos jumping to them.
If you can't generate .globl pseudo-ops, you can associate a global variable
with each label, and have an initialization pass that invokes a function in
each module, which assigns the addresses of the labels in that module to the
corresponding variables.
There is a layer of macros in the Mercury runtime that hides the choice
between three techniques for implementing gotos: these two, and the
"return to a driver function" model you mention below. Its implementation
takes maybe 500 lines. The rest of the system doesn't need to know which
method is being used; it works only at or above the level of the macros.
(The one exception I recall is the foreign language interface.)
For more information, see "Compiling logic programs to C using GNU C as a
portable assembler", available from the URL
www.cs.mu.oz.au/research/mercury/information/papers.html
Its first author, Fergus Henderson, implemented most of this ten years ago.
It has been very stable. The only time I remember touching these macros
in the last five years was when gcc 3.4 came out. It was a bit more agressive
about deleting apparently unreachable functions than 3.3, so I had to make
their actual reachability apparent to gcc. It took only a couple of hours.
>Here is what my compiler is doing (the design is based on GHC):
>The portable version uses the well known trampoline trick, where each
>function returns a function pointer which it wishes to jump to, and a
>central interpreter loop repeatedly calls a function, then its result
>etc. until exited by longjmp.
Mercury can do that too, on machines that don't have compilers that
support gcc extensions to C. This technique (without the edited assembler
trick) loses a factor of 2 in speed compared to the faster method described
above.
>Then on selected platforms (x86 and x86_64) a Perl script translates
>the assembler output of the C compiler, and converts returning a
>function pointer into a direct jump (this is not always trivial,
>e.g. jumps into a common epilogue are replaced with duplicated code).
>Such jumps are marked by a comment in inline asm so the Perl script
>can distinguish them from other function returns.
This technique predates Haskell. The NU-Prolog system used it in 1986,
and I bet it wasn't new then.
Zoltan.
|
|
0
|
|
|
|
Reply
|
zs22 (13)
|
6/9/2005 5:55:43 AM
|
|
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
>It includes a constant cost (e.g. the stack pointer is in a global
>variable instead of a physical register),
With GNU C extensions, a few global variables can BE in physical registers.
Even on the x86, on which the Mercury implementation stores only two abstract
machine registers in real machine registers (to leave the rest to the C
compiler), the stack pointer is one of them.
Zoltan.
|
|
0
|
|
|
|
Reply
|
zs22 (13)
|
6/9/2005 5:59:08 AM
|
|
Zoltan Somogyi <zs@students.cs.mu.OZ.AU> writes:
>>I wouldn't know how to do separate compilation and indirect jumps
>>using addresses of labels.
>
> We have been doing it for ten years. You generate assembler code in labeled
> blocks, and don't worry too much about which labels go in which function.
What if different functions need different stack frame sizes? What if
some of them save callee-saved registers on the stack and others don't?
> With GNU C extensions, a few global variables can BE in physical registers.
I tried that, but:
- there are too many interesting virtual registers and too few
physical registers on x86 (I pass up to 5 arguments in virtual
registers, the return address is another)
- different libraries which use this approach can't be used together
- if many physical registers are taken out, gcc sometimes is unable to
compile code
- performance savings were quite small (about 10% if I remember)
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
|
|
0
|
|
|
|
Reply
|
qrczak (1265)
|
6/9/2005 12:02:38 PM
|
|
I wrote:
>> We have been doing it for ten years. You generate assembler code in labeled
>> blocks, and don't worry too much about which labels go in which function.
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
>What if different functions need different stack frame sizes? What if
>some of them save callee-saved registers on the stack and others don't?
The stack that the code inside these functions store their information on
is not the C stack; it is a stack under our control, which is a C array
pointed to by a global variable. None of the functions ever store anything
on the C stack, except in two circumstances. First, the C compiler may
decide that some local expression is so complex it needs to spill some
registers. Second, in a few cases the generated C code refers to local
variables declared in small scopes. These are intended to be variables
for the C compiler to map to registers, but some of these may also be
spilled. (Their lifetime never goes beyond the next nonlocal goto.)
Accommodating these spills imposes a few requirements on the C function
that starts the Mercury abstract machine, and whose stack frame is
therefore shared by all these pieces of code. It does not expect any
of its local variables to survive having its frame being shared, and
the local variables include an array that forces the size of the stack frame
to be quite big (1 Kb if I remember). Since the size of the expression
that needs N bytes of spill is exponential in N, any invocation of the C
compiler that finds an expression that requires 1 Kb of spilled registers
will probably take days to execute and/or run out of swap space. Just
to be sure, we have a sanity check that tests whether an integer beyond
this array has been clobbered; I don't remember it ever having been
triggered after the initial debugging of this part of the Mercury
runtime system.
>> With GNU C extensions, a few global variables can BE in physical registers.
>I tried that, but:
>- there are too many interesting virtual registers and too few
> physical registers on x86 (I pass up to 5 arguments in virtual
> registers, the return address is another)
We started this work on SPARC and MIPS CPUs, on which we could use about
eight real machine registers. The payoff was of course higher. However,
when we instrumented every reference to an abstract machine register with a
counter, we found that the two most frequently used abstract machine
registers, the stack pointer and the return address register, account for
44% of all abstract machine register references. So we get close to half
the available benefit even with two real machine registers. Your mileage
of course will vary.
>- different libraries which use this approach can't be used together
Different libraries generated by the same language implementation can
of course be used together. If you are talking about two different language
implementations both claiming the same real register, it can still
be handled with appropriate code at the interface between them. Save the
registers to one language's backing store (some global variables), restore
the registers from the backing store of the other. Do the reverse when
returning.
>- if many physical registers are taken out, gcc sometimes is unable to
> compile code
Gcc has indeed had some bugs along these lines. Sometimes it wants to use
hand-written (by the gcc folks) assembler code for some primitive operations
such as strcpy, sometimes these primitives want to use registers we have
reserved for global variables, and sometimes gcc doesn't notice the conflict
until too late. We have reported some such bugs; they have either been fixed
or we developed workarounds.
>- performance savings were quite small (about 10% if I remember)
The benchmark results on the SPARC and MIPS machines we did about
a decade ago showed that using 8 or so machines registers to store
abstract machine registers gave a speed improvement of about a factor of 2.
Adding nonlocal gotos as well raised this to a factor of 3.
Definitely worthwhile.
Zoltan Somogyi <zs@cs.mu.OZ.AU> http://www.cs.mu.oz.au/~zs/
Department of Computer Science and Software Engineering, Univ. of Melbourne
|
|
0
|
|
|
|
Reply
|
zs22 (13)
|
6/10/2005 7:52:53 AM
|
|
|
217 Replies
65 Views
(page loaded in 1.252 seconds)
Similiar Articles: New APL2 Programming Language forum - comp.lang.aplIn any case, we have created a new APL2 Programming Language forum in IBM's ... Functional programming - comp.graphics.api.opengl New APL2 Programming Language forum ... Magic square : Help with my homework - comp.lang.prologWe've been asked to make a generic magic squares ... in 1..N]) #=3D 3, Earlang and most functional languages have ... Then (some time ago) higher order programming was ... define-generic-mode: how to control tab indentation? - comp.emacs ...I defined a simple generic for editing my programming language Foo in Emacs. The generic mode highlights some keywords. Now, how can I control the i... OOPS in matlab - comp.soft-sys.matlabMatlab has some support for functional programming, FP. FP is better than OOP for some ... dynamic and most texts on Design Patterns (e.g GOF) target compiled languages. Misuses of RTTI - comp.lang.c++.moderatedMost importantly, other language mechanisms such as polymorphism and templates ... That kind of facility is only useful in generic programming. Maybe > neither of these ... comp.arch.fpga - page 12ANN: Confluence 0.6 0 4 (8/11/2003 3:11:06 PM) Confluence is a functional programming language for digital logic design (FPGA/ASIC), real-time embedded software ... writing robust software? - comp.lang.c++.moderatedSome array out of bounds errors could be avoided with functional programming styles. ... with this you are probably left to a very minor subset of programming languages. Why no std::back_insert_iterator::value_type? - comp.lang.c++ ...> PS: once we have decltype in the language, we could ... convert bits to higher level constructs. | Generic programming ... >From "5.2.3 Explicit type conversion (functional ... Implementing a mangling tool - comp.lang.c++.moderated... at templates... sure they were cool, but they didn't take off, until generic programming ... This way, you could (at least in theory) even mix languages. Code in Fortran or ... Procedural modelling - comp.graphics.api.openglC to VHDL - comp.lang.vhdl Actually even any procedural > language to VHDL ... Functional programming - comp.graphics.api.opengl Functional programming - HaskellWiki ... google home page comes up in Russian!! - comp.sys.mac.apps ...So, did you try setting your Interface Language to Elmer Fudd just for the fun ... Functional programming - comp.graphics.api.opengl... Functional programming environments ... solutions manual for Introduction to Java Programming ...... and S. Ramesh SOLUTIONS MANUAL TO Assembly Language ... MANUAL TO Nanoengineering of Structural, Functional and ... Solutions Manual Programming Logic and Design ... Preferred way to get multiple returns from a function - comp.lang ...C programming has taught me to appreciate structures, but I'd like to code in the conventions of the language. ... Generic ROI? "Encapsulation" may ... Avoiding problems with short-circuit primitive operator&& versus ...> > > 1) functional-form > > This means I want to evaluate all ... The problem is that the c++ language doesn't have a ... Code should report programming errors not try to fix these. how to stop SAS jobs - comp.soft-sys.sas... stopping the few lines of programming ... trap on error that some other languages do. Perhaps if you are writing in SCL you can do this. Generic programming - Wikipedia, the free encyclopediaPolyP was the first generic programming language extension to Haskell. In PolyP, generic ... Proceedings of the ACM SIGPLAN International Conference on Functional Programming ... C Sharp (programming language) - Wikipedia, the free encyclopediaC# makes use of reification to provide "first-class" generic ... Though primarily an imperative language, since C# 3.0 it supports functional programming techniques through ... 7/30/2012 3:16:31 PM
|