Topic: [LONG] The future of C++


Author: brangdon@cix.co.uk (Dave Harris)
Date: 11 Feb 03 17:19:23 GMT
Raw View
nde_plume@ziplip.com (Nom De Plume) wrote (abridged):
 > You are rather assuming your conclusion here. Specifically,
 > you are assuming there is a need for these functors to be
 > "passed around."

Not quite. I am assuming there /may/ be a need. Whether the
functor is passed around is an implementation decision. Client
code should not depend on it.


 > > We have hard-wired the type of the parameter into for_each().
 >
 > Not really. for_each is a template function, and the type
 > of this argument can readily be templatized.

I am talking about non-template functions.


 > Thanks for trying to give a concrete example. However, this
 > doesn't seem to realistic to me. I've written compilers
 > before and, in such cases where you do distinguish between
 > the node types by the static object type (that is have a
 > while node as opposed to a generic AST node) the tree walk
 > is usually handled by a base class.

I wasn't intending to lecture on compiler design. Anyway, it
seems to me you have just renamed my classes. In your corrected
example, the tree walk is still handled by subclasses. You have a
virtual walk() function with implementations like:

    void AST1::walk(Func & f) { process(f); item->walk(f); };
    void AST2::walk(Func & f) { process(f);
            item1->walk(f); item2->walk(f); };

So my point remains. walk() cannot be a template function because
virtual functions cannot be templates.


[Quote taken out of order]
 > The primary purpose of anonymous functions as
 > I have described them is to make defining functionality for
 > standard library <algorithm> like functions a simple,
 > straightforward and easy to learn process.

This is a general point about scalability. You want to make certain
simplifying assumptions, such as that the function argument can be
a template parameter and won't need to be passed around much. This
means clients have to know quite a lot about the implementation
in order to write their code. If the implementation changes, the
client code has to be changed too.


 > I understand you trying to abstract to a more general
 > problem

We could try to generalise either on the client side or on the
server side...


 > but my opinion based on surveying lots of
 > code, is that it really isn't all that valuable, whereas
 > anonymous functions are, in the simple form I have
 > defined them, extremely valuable.

Here you are talking about the client side.

I want to abstract over the server side. Not only do I want to
support complex servers, I want to be able to switch between
simple servers and complicated ones without affecting client code.
I don't want clients to have to write different code if the server
function they are calling is virtual.

You see my point? I agree that clients with simple needs should
have simple syntax (if possible). However, that syntax should work
whether the server is a simple STL template or a complex user-
defined visitor. Introducing a syntax which only works for simple
servers is a step backwards, in my view. It's divisive.

   Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
       brangdon@cix.co.uk      |   And close your eyes with holy dread,
                               |  For he on honey dew hath fed
  http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nde_plume@ziplip.com (Nom De Plume)
Date: 5 Feb 2003 20:45:40 -0500
Raw View
brangdon@cix.co.uk (Dave Harris) wrote in message news:<memo.20030130214659.23407C@brangdon.madasafish.com>...
> Generally whenever you have two or more values which form a cohesive
> unit, which are passed around together, which must be kept in sync etc,
> it is best to make this cohesion explicit by turning it into a class.

I don't know I entirely agree with that statement Dave, however,
lets assume for a moment that it is correct. You are rather
assuming your conclusion here. Specifically, you are assuming
there is a need for these functors to be "passed around." Yet
as I said before I doubt there is a great deal of need for such
a thing at all. The primary purpose of anonymous functions as
I have described them is to make defining functionality for
standard library <algorithm> like functions a simple,
straightforward and easy to learn process. For such there is
no need to pass the functor around.

> In this case there is a further disadvantage, namely how to declare the
> extra parameter. I gave this example earlier:
>
>     void for_all( Tree *pRoot, void (*pFunc)(Leaf *, double &), double
> &);
>
> It's fine if we know the parameter will always be a double. It's no good
>
> if we want to use a string or some other type.
>
>
> This still effects the type. If your example:
>
>             inline void(int i)
>                 using total
>             {
>                total += i;
>             }
>
> is really short-hand for:
>
>             inline void(int i, int &total )
>             {
>                total += i;
>             }
>
> then the type of the anonymous function is surely void (*)( int, int& ).
>
> It cannot be passed to any function which expects void (*)( int ). We
> have
> hard-wired the type of the parameter into for_each().

Not really. for_each is a template function, and the type
of this argument can readily be templatized. (If such a word
exists :-)

> > But that is not significantly different from passing
> > a polymorphic base to the function is it?
>
> One difference is that this is not type-safe. I need to write:
>
>  int sum_em(list<int> &lst) {
>      struct MyData : Base {
>          int total;
>      } d;
>      d.total = 0;
>      for_each(lst.begin(), lst.end(),
>             inline void(int i, Base &b ) {
>                 MyData &d = dynamic_cast<MyData &>(b);
>                 d.total += i;
>             });
>      return d.total;
>  }

Perhaps for PODs. But this can readily be addressed
by a virtual function. If you are using a simple
piece of data like an int or any POD collection you
can simply pass that in as a parameter to the function
as discussed above. In the actual example above what
does Base actually add? Why not just pass in total?

I understand you trying to abstract to a more general
problem, but my opinion based on surveying lots of
code, is that it really isn't all that valuable, whereas
anonymous functions are, in the simple form I have
defined them, extremely valuable. (I base my value
judgment on several criteria: broad applicability,
simplification of code, efficiency of code, easy
learnability. In three out of these four, anonymous
functions greatly improve on functors as currently
used.)

> The need for a cast is a major drawback. Frankly, I'd call it a hack.
> It's
> not the clean solution a new language feature ought to provide. Compare
> with:
>
>  int sum_em(list<int> &lst) {
>      struct MyData : Base {
>          int total;
>          virtual void operator()( int i ) {
>              total += i;
>          }
>      } s;
>      s.total = 0;
>      for_each(lst.begin(), lst.end(), s );
>      return s.total;
>  }
>
> This illustrates how my desire for a cohesive, single object is more
> than
> aesthetics. It has greater static type safety. Think about that.

Sorry, I don't agree. You have simply miscast the problem.
Clearly this same problem could readily be implemented
in the way given before. You haven't shown any need for
the base class here. Don't get me wrong, I'm sure an
artificial reason could be created, but pragmatically
it doesn't seem to address anything other than a very, very
rare situation. (Or at least, nearly all situations where
this might be applicable, the problem can readily be
recast to be more amenable to a different, clearer solution.)

> > Regardless, what exactly do you have against templates? :-)
>
> I like templates, but sometimes they are not appropriate. One problem is
> that they make client code dependent on the implementation of the
> algorithm. This is often inconvenient because it leads to extra and
> longer
> recompilations. Sometimes it is impractical because the implementation
> needs to vary at run time.

I'll accept your former point (though processor power is
much cheaper than programmer time.) The second point is
a little confusing. I agree though that it would be
delightful if templates didn't have to be defined in
header files.

> For example, suppose we have something like a parse tree, with nodes for
>
> "if-else-statement", "while-statement" etc, with some nodes having two
> sub-nodes and others one. So my for_all() is implemented like:
>
>     struct Node;
>
>     struct Func {
>         virtual void operator()( Node *pNode ) = 0;
>     };
>
>     struct Node {
>         virtual void for_all( Func &func ) = 0;
>     };
>
>     struct IfNode : public Node {
>         virtual void for_all( Func &func ) {
>             func( this );
>             pTrueNode->for_all( func );
>             pFalseNode->for_all( func );
>         }
>         Node *pTrueNode;
>         Node *pFalseNode;
>         // ...
>     };
>
>     struct WhileNode : public Node {
>         virtual void for_all( Func &func ) {
>             func( this );
>             pBodyNode->for_all( func );
>         }
>         Node *pBodyNode;
>         // ...
>     };
>
>     void for_all( Node *pRoot, Func &func ) {
>         pRoot->for_all( func );
>     }
>
> Clearly this cannot be translated directly into a template. The tree
> structure is too dynamic. You can also see how the pain of your extra
> reference parameter has to be endured by every node in the hierarchy.

Thanks for trying to give a concrete example. However, this
doesn't seem to realistic to me. I've written compilers
before and, in such cases where you do distinguish between
the node types by the static object type (that is have a
while node as opposed to a generic AST node) the tree walk
is usually handled by a base class. (Oh, BTW for anyone
reading along who is unfamiliar with compiler terminology,
AST = abstract syntax tree, which is a tree representation
of the parsed source code of a program.)

class AST
{
  virtual void walk(Func& f) = 0;
  virtual void process(Func& f) =0;
};
class AST1 : public AST {
  AST1(AST* item);
  AST * item;
  void walk(Func & f) { process(f); item->walk(f); };
};
class AST2 : public AST {
  AST2(AST* item1, AST* item2);
  AST * item1, * item2;
  void walk(Func & f) { process(f); item1->walk(f); item2->walk(f); };
};
class ASTn: public AST {
  ASTn(std::list<AST*> items);
  std::list<AST*> items;
  void walk(Func& f)
  {
    process(f);
    std::for_each(items.begin(), items.end(), f,
                  inline void(AST* item, Func& f)
                  {
                     item->walk(f);
                  });
  }
};

(You could of course use copy semantics rather than pointers
but I suspect you wouldn't in the real world -- a discussion
for another time.)

Usually your tree would consist of the above (usually with
a tag indicating the node type.) But if you must do it by
static type you would do:

class whileAST : public AST2 {/*...*/ };
class if_elseAST : public ASTn { /* ... */ };

(You'd probably also have an AST3 since such a node is quite
common in programming languages, for example here for if_else.)

whileAST should deal with the while aspects of the node, not
the basic nodeness of the node. It should also be noted that
ASTn is all that is really needed, AST1, AST2 and so forth
are simply optimizations that should have identical functional
behavior to the general ASTn.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 06 Feb 03 07:35:18 GMT
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0302031551.1f75b82c@posting.google.com>...
> brangdon@cix.co.uk (Dave Harris) wrote
> > allan_w@my-dejanews.com (Allan W) wrote (abridged):
> > > Note that if Stroustrup or AT&T had patented the idea of virtual
> > > tables (as opposed to merely copyrighting the compiler), Java
> > > might not exist.  If someone can get a patent on using XOR to draw
> > > a line, then surely Stroustrup could have patented the virtual
> > > table -- which (unlike XOR) did NOT have prior art, and was NOT
> > > obvious.

> > > (AFAIK, the closest equivalent to virtual tables was a "jump
> > > table" used to implement such things as select/case statements.)

> > When I first started work my employers were already using jump
> > tables for polymorphism exactly as virtual function tables. They
> > were initialised by hand, and pointers to them were stored in
> > class-like data structures, and some tables were longer than others
> > so some notion of subclassing was present, too. This was in BCPL,
> > around 1983. I think Unix device drivers used them too.

> > C++ provided direct support, which was welcome. It generated the
> > indexes automatically, within a single-inheritance hierarchy.

> Another major distinction was that the address of various jump-tables
> were usually hard-coded, and unrelated to each other.

That's not true of device drivers, at least in Unix, since at least
version 7.  If memory serves me right, the old Interdata OS-32 operating
system also used this basic mechanism for device drivers.  That's circa
1975.  I suspect that it was in fact very widely used.

> By contrast, with virtual tables each object carries a pointer to the
> table it will use at runtime, and the Nth entry of each table refers
> to either the same function or the overloaded version thereof.

OK.  Generally in the case of drivers, the "object" carried the entire
vtable with it.  (Under Unix, the major device number gave the address
of the "vtable", the minor number selected a data area.)

> > It's hard to say now whether it was obvious a compiler could do
> > this.
>  [Meaning "generate the indexes of a jump-table automatically."]
> > I am inclined to say it was.

> > Support for more complex forms such as virtual multiple inheritance
> > was added later. This technology is quite complicated and I don't
> > know of any instances before C++, but then again, I suspect anyone
> > competent in the art could have devised it, given knowledge of Unix
> > device drivers.

> > If vtables were patented, I expect languages such as Java would
> > adopt Smalltalk-like dispatch, which is usually more efficient
> > anyway. I believe some implementations of Eiffel do this.

> If generating indexes was the only issue, I'd agree... it was very
> common for assembly code to emit code into several different segments
> at once, and surely that was the original way to implement this. But
> in my opinion, virtual tables represented a whole new application of
> that technique... this is starting to be a discussion of opinions
> rather than facts, so let's just say we disagree.

I don't think that the innovation was so much the vtable/vptr itself,
but the implicit calling of the constructor and destructor, with
compiler generated defaults, even in non-trivial cases (e.g. when there
was a vtable).  Even today, this is a pretty special feature (absent,
for example, in Java).

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: allan_w@my-dejanews.com (Allan W)
Date: 4 Feb 2003 15:35:59 -0500
Raw View
brangdon@cix.co.uk (Dave Harris) wrote
> allan_w@my-dejanews.com (Allan W) wrote (abridged):
> > Note that if Stroustrup or AT&T had patented the idea of virtual tables
> > (as opposed to merely copyrighting the compiler), Java might not exist.
> > If someone can get a patent on using XOR to draw a line, then surely
> > Stroustrup could have patented the virtual table -- which (unlike XOR)
> > did NOT have prior art, and was NOT obvious.
> >
> > (AFAIK, the closest equivalent to virtual tables was a "jump table"
> > used to implement such things as select/case statements.)
>
> When I first started work my employers were already using jump tables for
> polymorphism exactly as virtual function tables. They were initialised by
> hand, and pointers to them were stored in class-like data structures, and
> some tables were longer than others so some notion of subclassing was
> present, too. This was in BCPL, around 1983. I think Unix device drivers
> used them too.
>
> C++ provided direct support, which was welcome. It generated the indexes
> automatically, within a single-inheritance hierarchy.

Another major distinction was that the address of various jump-tables
were usually hard-coded, and unrelated to each other. By contrast,
with virtual tables each object carries a pointer to the table it
will use at runtime, and the Nth entry of each table refers to either
the same function or the overloaded version thereof.

> It's hard to say now
> whether it was obvious a compiler could do this.
[Meaning "generate the indexes of a jump-table automatically."]
> I am inclined to say it was.
>
> Support for more complex forms such as virtual multiple inheritance was
> added later. This technology is quite complicated and I don't know of any
> instances before C++, but then again, I suspect anyone competent in the
> art could have devised it, given knowledge of Unix device drivers.
>
> If vtables were patented, I expect languages such as Java would adopt
> Smalltalk-like dispatch, which is usually more efficient anyway. I believe
> some implementations of Eiffel do this.

If generating indexes was the only issue, I'd agree... it was very
common for assembly code to emit code into several different
segments at once, and surely that was the original way to implement
this. But in my opinion, virtual tables represented a whole new
application of that technique... this is starting to be a discussion
of opinions rather than facts, so let's just say we disagree.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: 31 Jan 03 02:19:20 GMT
Raw View
nde_plume@ziplip.com (Nom De Plume) wrote (abridged):
> Can you tell me why you think this is bad engineering?
> My preference for parameter passing is its explicitness.
> The parameter is right there. However, with functors in
> general you have a level of indirection (the operator()
> function uses state that was previously set in a ctor,
> often in a very obscure manner.)

Generally whenever you have two or more values which form a cohesive
unit,
which are passed around together, which must be kept in sync etc, it is
best to make this cohesion explicit by turning it into a class. For
example, rather than pass an x and a y, pass a Point. It leads to less
code, less clutter, a higher level of abstraction, and fewer chances of
mistakes (such as mixing the x of one point with the y of another). It
is
/more/ explicit.

See Stroustrup's "C++PL" $18.3.1 for another example. I think this is
one
of the core ideas of object orientation - to combine the data, together
with the functions that work on it, into a single abstraction. To me,
your
unbundling approach is a step backwards.

In this case there is a further disadvantage, namely how to declare the
extra parameter. I gave this example earlier:

    void for_all( Tree *pRoot, void (*pFunc)(Leaf *, double &), double
&);

It's fine if we know the parameter will always be a double. It's no good

if we want to use a string or some other type.


> The variable can be stored on the stack, and pushed there
> every time the function is called. That is, it is passed
> by reference as a parameter.

This still effects the type. If your example:

            inline void(int i)
                using total
            {
               total += i;
            }

is really short-hand for:

            inline void(int i, int &total )
            {
               total += i;
            }

then the type of the anonymous function is surely void (*)( int, int& ).

It cannot be passed to any function which expects void (*)( int ). We
have
hard-wired the type of the parameter into for_each().


> But that is not significantly different from passing
> a polymorphic base to the function is it?
>
> for_all(Tree* pRoot, void(*f)(double d, Base& b), Base& b);
>
> Now client code can subclass Base and add whatever state
> is needed there.

One difference is that this is not type-safe. I need to write:

 int sum_em(list<int> &lst) {
     struct MyData : Base {
         int total;
     } d;
     d.total = 0;
     for_each(lst.begin(), lst.end(),
            inline void(int i, Base &b ) {
                MyData &d = dynamic_cast<MyData &>(b);
                d.total += i;
            });
     return d.total;
 }

The need for a cast is a major drawback. Frankly, I'd call it a hack.
It's
not the clean solution a new language feature ought to provide. Compare
with:

 int sum_em(list<int> &lst) {
     struct MyData : Base {
         int total;
         virtual void operator()( int i ) {
             total += i;
         }
     } s;
     s.total = 0;
     for_each(lst.begin(), lst.end(), s );
     return s.total;
 }

This illustrates how my desire for a cohesive, single object is more
than
aesthetics. It has greater static type safety. Think about that.

Also, if we have to declare a local, named struct anyway, I don't think
much has been gained by the anonymous function.


> Regardless, what exactly do you have against templates? :-)

I like templates, but sometimes they are not appropriate. One problem is

that they make client code dependent on the implementation of the
algorithm. This is often inconvenient because it leads to extra and
longer
recompilations. Sometimes it is impractical because the implementation
needs to vary at run time.

For example, suppose we have something like a parse tree, with nodes for

"if-else-statement", "while-statement" etc, with some nodes having two
sub-nodes and others one. So my for_all() is implemented like:

    struct Node;

    struct Func {
        virtual void operator()( Node *pNode ) = 0;
    };

    struct Node {
        virtual void for_all( Func &func ) = 0;
    };

    struct IfNode : public Node {
        virtual void for_all( Func &func ) {
            func( this );
            pTrueNode->for_all( func );
            pFalseNode->for_all( func );
        }
        Node *pTrueNode;
        Node *pFalseNode;
        // ...
    };

    struct WhileNode : public Node {
        virtual void for_all( Func &func ) {
            func( this );
            pBodyNode->for_all( func );
        }
        Node *pBodyNode;
        // ...
    };

    void for_all( Node *pRoot, Func &func ) {
        pRoot->for_all( func );
    }

Clearly this cannot be translated directly into a template. The tree
structure is too dynamic. You can also see how the pain of your extra
reference parameter has to be endured by every node in the hierarchy. We

surely don't want (double &) and (string &) variants.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: thp@cs.ucr.edu
Date: Fri, 31 Jan 2003 16:12:15 +0000 (UTC)
Raw View
Ko van der Sloot <Ko.vanderSloot@uvt.nl> wrote:
+
+ ===================================== MODERATOR'S COMMENT:
+
+ This is beginning to drift away from the C++ Standard.
+
+
+ ===================================== END OF MODERATOR'S COMMENT
+ In article <3E170E23.9060407@animats.com>,
+ nagle@animats.com (John Nagle) writes:
+ |> Dave Harris wrote:
+ ...
+ |>     (LISP could have been the language of the Internet,
+ |> especially since most Internet-transmitted data
+ |> structures are trees.  Yahoo Store was (still is?)
+ |> a LISP application.  Understanding why that didn't
+ |> happen is a good exercise for language designers.)
+
+ Probably this is caused by the fact that LISP is NOT a Microsoft
+ trademark?

Neither is C++.  The lesson for C++ and its standardization body is
that when a language and its specification gets too obscure (and
leaves the user community in the dust), it is likely to lose mind
share, a matter which may or may not be of concern to the language's
standardizers, but may be of concern to those who have invested their
careers and their code dollars in this languate.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: 28 Jan 03 09:14:19 GMT
Raw View
brangdon@cix.co.uk (Dave Harris) wrote
> And possibly garbage collection of the stack,
> and maybe other things.

Garbage collection of the stack? What does that mean?

Sounds like an insurance policy for something indestructable.

Stack objects don't need garbage collection. They're automatically
destroyed when they go out of scope.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Anders J. Munch" <andersjm@dancontrol.dk>
Date: 29 Jan 03 13:56:26 GMT
Raw View
"Allan W" <allan_w@my-dejanews.com> wrote:
 > brangdon@cix.co.uk (Dave Harris) wrote
 > > And possibly garbage collection of the stack,
 > > and maybe other things.
 >
 > Garbage collection of the stack? What does that mean?

Heap-allocated activation records ('stack frames').

- Anders



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: rossberg@ps.uni-sb.de (Andreas Rossberg)
Date: 29 Jan 2003 12:43:13 -0500
Raw View
Hyman Rosen <hyrosen@mail.com> wrote:
>  > But it is as convenient as encoding OO in Assembler.
>  > So C++ could indeed benefit from taking a closer look
>  > at features found in such languages.
>
> Such a close look has been taken. Check out, for example,
> <http://spirit.sourceforge.net/index.php?doc=docs/phoenix_v1_0/introduction.html>.

Interesting. Thanks for the link.

> As far as my example goes, "laziness" would simply involve
> keeping a memoizing vector in the generator classes. What's
> the big deal?

Sure, for a toy example like this it is not difficult to hack up a
solution. However, much of the power of lazy evaluation actually comes
from its being fully compositional. Hence, to simulate non-trivial
applications of it in C++ you essentially had to code a lazy evaluator
yourself and wrap lots of stuff into a laziness-ready representation.

And even if you were willing to do that you'd still buy yourself
practically unsolvable memory management problems if you can't
delegate to a GC. When would you free your memoized data structures?

- Andreas
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly <llewelly.@@xmission.dot.com>
Date: 29 Jan 2003 12:45:08 -0500
Raw View
allan_w@my-dejanews.com (Allan W) writes:

> brangdon@cix.co.uk (Dave Harris) wrote
> > And possibly garbage collection of the stack,
> > and maybe other things.
>
> Garbage collection of the stack? What does that mean?
>
> Sounds like an insurance policy for something indestructable.
>
> Stack objects don't need garbage collection. They're automatically
> destroyed when they go out of scope.

Not if the language supports closures which can reference local objects.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nde_plume@ziplip.com (Nom De Plume)
Date: 30 Jan 2003 09:18:51 -0500
Raw View
brangdon@cix.co.uk (Dave Harris) wrote in message news:<memo.20030121223409.34117A@brangdon.madasafish.com>...
> Ah. Here we differ. I am looking for a convenient way to define a functor.
> A functor is a function or something which looks like a function. It is a
> more general notion.
>
> So my criticism here is lack of ambition. A language change is such a big
> deal it really ought to solve the bigger problem.

Thanks for your comments Dave, and I apologize that it took
me so long to respond (I had to deal with that little matter
of working for money -- bummer :-)

When I originally thought about this stuff I was also very
concerned with the idea of access to local state. In fact
in my original comments here I suggested a "using" mechanism
to transfer local data through into the state of a functor,
viz:

int sum_em(list<int> lst)
{
  int total = 0;
  for_each(lst.begin(), lst.end(),
           inline void(int i)
               using total
           {
              total += i;
           });
}

Here the using line indicating that we want a functor here
with the given state and the obvious behavior.

However, I have largely moved away from that view for this
simple reason: in practice it doesn't seem all that useful.

Lets be clear here, obviously access to the local state is
necessary, however, this can simply be provided via parameter
passing:

int sum_em(list<int> lst)
{
  int total = 0;
  for_each(lst.begin(), lst.end(), total,
           inline void(int i, int& total)
           {
              total += i;
           });
}

The question is, do we need something beyond that? Certainly
if you are implementing an advanced lambda facility you would
want to include such a thing. However, it only really seems
to matter when you are treating a function as a first class
object, and in particular, where you are evaluating the function
in a different place than you are defining it.

Let me offer a specific example. In the past I defined a
function to return the postal rate of a package. We might
do this:

double(*)(double weight)
postalRate(Country country)
{
  double factor;
  switch(country)
  {
  case USA: factor = 0.75; break;
  case UK:  factor = 1.25; break;
  case Australia: factor = 2.24; break;
  // ... etc
  }
  return inline (double weight) using factor
         {  return weight * factor; };
}

This is strictly speaking currying, or a crude form of it
anyway. But it is the only practical application where the
state has to be carried as opposed to passed by parameter.
Obviously this is quite esoteric, and can readily be handled
in a different way.

The main reason I have turned away from a convenient format
for functors to a convenient format for functions and member
functions is that I have walked through the tens of thousands
of lines of code I have written in the past few years and
tried to apply the anonymous function principle wherever I
could. The reality is that I could not find a single place
where carrying the state (as opposed to passing it by parameter)
would have been useful. I might add that I have found thousands
of places where anonymous functions would not only have made
my code easier to understand, but also, the very existence
of anonymous functions would have forced me to write clearer
code, eliminating lots of unnecessary exceptional control
flow structures.

Of course, I have a particular coding style different from
other people. Perhaps there are good reasons to carry the
state. I would love to hear from anybody who feels that this
is a vital feature, that can readily be used in many, many
different application areas, with some specific concrete
examples that we could wrangle and get our arms around.

> One advantage of using proper objects is that they can have arbitrary
> state. Plain function pointers can't. In some of your examples (elsewhere
> in the thread) you have tried to work around the lack by passing extra
> data with the pointer-to-function. I feel this is bad engineering - it is
> better to have the single object.

I guess this is the counter you would offer to the above.
Can you tell me why you think this is bad engineering?
My preference for parameter passing is its explicitness.
The parameter is right there. However, with functors in
general you have a level of indirection (the operator()
function uses state that was previously set in a ctor,
often in a very obscure manner.)

IMHO functors as they are used in the STL are largely
a hack to get around the lack of anonymous function
declarations. But I am sure that is a very controversial
opinion.

To say they are non-obvious is an understatement, as anyone
who has taught the concept to neophytes will agree. That is
why I favor anonymous functions declared inline on the basis
of learning. It seems a much more readily assimilable concept
for the neophyte. (Though obviously I don't have any data
to support this assertion.) After all, they are already
familiar with functions, and although there is a subtlety
there (the function definition is actually an expression
returning a pointer to the function) it is relatively
transparent until you need to understand it. To use functors
you need to understand a quite profound concept, and a
significant level of indirection. The concept of operator()
is very difficult for neophytes.

> Some other of your examples allow the lambda to use variables from the
> enclosing scope - true closures. But now this is no longer a simple
> pointer to function. In a plain:
>
>     void (*pFunc)( const Item &item );
>
> there is nowhere to store a reference to total_price_ (or to the instance
> of Items which holds the total_price_), unless you store that reference in
> the code segment (which is problematic). Your getTotalPrice() really does
> need something like a struct behind the scenes.

The variable can be stored on the stack, and pushed there
every time the function is called. That is, it is passed
by reference as a parameter. The obvious inefficiency of
this can readily be removed by inlining the function and
doing alias optimizations, so that it is no different than
if you wrote it the hard way. Such optimization is much
harder if you are using a functor.

> I am especially interested in how functions which accept lambdas should be
> declared. Your examples seem to use templates, so it is left to template
> argument deduction. Is it your intent that lambdas only be used with
> template functions? If so, this is another failure of ambition. If not...

No, it is my intention that lambdas be simply pointers
to functions in the very conventional sense. For example,
in a previous post I suggested the following code as a
use of a lambda:

double(*)(Item& i)
calcPostage(Country country)
{
// Return a function that calculates the postage
// on a given item going to the given country.
  switch(country)
  {
  case USA:  return inline double (Item& i)
                           { return i.weight * 0.50; };
  case UK:   return inline double (Item& i)
                           { return i.weight * 0.75; };
  case Australia:
             return inline double (Item& i)
                           { return i.weight * 1.25; };
  // etc
  }
}

Here the lambda is being returned, but it is still within the
regular type system.

(Of course my intention also is that we can also define
member functions inline anonymous too, but this is a fairly
trivial extension of the above.)

> Let's suppose I have a complex data structure and I want a for_all()
> routine which iterates over it. I don't want for_all() to be a template.
> How should I declare for_all() ? You seem to have in mind something like:
>
>     void for_all( Tree *pRoot, void (*pFunc)(Leaf *) );
>
> As I've argued above, I think this is problematic if we want the lambda
> argument to have access to local variables. The approach of passing
> through an extra argument looks reasonable if we are defining a template:
>
>     template <typename Func, typename Arg>
>     void for_all( Tree *pRoot, Func f, Arg &arg );
>
> but doesn't scale for concrete types:
>
>     void for_all( Tree *pRoot, void (*pFunc)(Leaf *, double &), double &);
>
> because we might want int or some other type instead of double.
>
> Currently such programming problems are solved with real structs and
> dynamic polymorphism:
>
>     struct FunctorBase {
>        virtual bool operator()( Leaf * ) = 0;
>     };
>
>     void for_all( Tree *pRoot, FunctorBase &f );
>
> Now client code can subclass FunctorBase and add whatever state is needed
> there. It is a good, general solution.

But that is not significantly different from passing
a polymorphic base to the function is it?

for_all(Tree* pRoot, void(*f)(double d, Base& b), Base& b);

Now client code can subclass Base and add whatever state
is needed there. This is surely also a good general
solution, and one that doesn't need any new syntax.

Regardless, what exactly do you have against templates? :-)

> In my view, any new proposal ought to be compatible with this. I don't
> want to add a new lambda feature if it means the author of for_all() has
> to choose between functors and lambdas.

Me either, but I don't see why it would.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: 25 Jan 2003 20:18:49 -0500
Raw View
nde_plume@ziplip.com (Nom De Plume) wrote (abridged):
>  > o   Genericity.
>  > o   Recursion.
>  > o   Garbage collection.
>  > o   Type inference.
>  > o   Pattern matching.
>  > o   List comprehensions.
>
> You missed one of the most important concepts in all pure
> functional languages, namely ubiquitous lazy evaluation.

Oops, yes. Thanks for pointing this out.


> It is a mistake to think that the reason functional
> languages handle lists so gracefully is only notational,
> rather it is a fundamental characteristic of the underlying
> machine model.

I shouldn't have implied it was only notational. I was trying to stress
the power of the underlying concepts.


> I would, along these lines, reiterate the need for
> a genuine lambda function in the language, as I have
> proposed elsewhere in this thread.

I don't think it is enough to allow functions to be anonymous and declared
in-place. They also need to be closures - to have bindings to the local
variables of their defining context. In other words, they need to be
objects rather than functions.

Also, being able to declare them in-place /is/ notational. And although I
think good notation is important, I don't think it can really be achieved
here without type inference. And possibly garbage collection of the stack,
and maybe other things. Languages like C++ and Haskell are systems of
interlocking parts, so what works well in one language won't necessarily
work well in the other.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: 25 Jan 2003 20:24:08 -0500
Raw View
jpotter@falcon.lhup.edu (John Potter) wrote
> A function which does one thing is good.
>
> A class which does one thing is good.
>
> A programming language which tries to do everything in every way is
> __________.

Exceptionally good?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Tomasz Zielonka <t.zielonka@zodiac.mimuw.edu.pl>
Date: 27 Jan 2003 05:32:44 -0500
Raw View
Tom Hyer wrote:
>>
>> The code is:
>>     quicksort [] = []
>>
>>     quicksort (first:rest) =
>>           quicksort [ x | x <- rest, x <= first ]
>>           ++ [ first ]
>>           ++ quicksort [ x | x <- rest, x > first ]
>>
>
> Also, it is worth noting that the code as written makes twice as many
> comparisons as an imperative version would (because the "x <= first"
> and "x > first" subsequences are computed independently).  I don't
> think there's a workaround.

Then you are wrong, because it's fairly simple and the resulting
function is even shorter.

qsort []     = []
qsort (x:xs) = let (lt, ge) = partition (< x) xs in qsort lt ++ [x] ++ qsort ge

Personally I think that this quick sort example doesn't do much good for
Haskell. I am often impressed by the level of abstraction, elegance and
robustness one can achieve in Haskell. This example fails to show it.

> -- Tom Hyer

Regards,
Tom

--
.signature: Too many levels of symbolic links
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: 24 Jan 03 17:04:35 GMT
Raw View
llewelly wrote:
 > Then I ask you to re-examine the thunk-based version I included in my
 > post, which you snipped.

Yes, but that version involves runtime-generated code,
which gets us back to our starting point! I said that
in order for pointers to local functions to be compatible
with pointers to normal functions, stack-based thunk code
would be required. Then people started suggesting other
ways to do it, none of which would work. Now we've come
full-circle.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Andreas Rossberg <rossberg@ps.uni-sb.de>
Date: 24 Jan 2003 13:23:37 -0500
Raw View
Hyman Rosen wrote:
> Nom De Plume wrote:
>
>>squares [] = []
>>squares [h:t] = h*h : squares t
>>SumOfFirstFive = sum(take 5 squares[1..])
>>
>
>   > Of course something like this could be done in C++ but
>
>>it would be a lot of hand coding to produce the equivalent
>>lazy mechanism.
>
> I wouldn't call it a lot - here is equivalent code to yours.
 >
 > [snipped]

Your code does not encode lazy evaluation. Consider a slight variation:

squares [] = []
squares [h:t] = h*h : squares t
firstFive = take 5 (squares [1..])
sumOfFirstFive = sum firstFive
prodOfFirstFive = prod firstFive

Laziness means that an expression is evaluated _at most once_. The
approach you sketched does not achieve that, it would compute firstFive
twice if sum and product are both requested.

Of course, you _can_ encode laziness in C++. But it is as convenient as
encoding OO in Assembler. Likewise the primary feature of functional
languages, first-class functions: they require closures and GC. Any
claim that the expressive power of today's C++ comes close to functional
languages in that regard is hence strongly exaggerating. So C++ could
indeed benefit from taking a closer look at features found in such
languages. After all, C++ exceptions have been originally borrowed from
ML, IIRC.

--
Andreas Rossberg, rossberg@ps.uni-sb.de

"Computer games don't affect kids; I mean if Pac Man affected us
  as kids, we would all be running around in darkened rooms, munching
  magic pills, and listening to repetitive electronic music."
  - Kristian Wilson, Nintendo Inc.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Thant Tessman <thant@acm.org>
Date: 24 Jan 2003 14:30:47 -0500
Raw View
Hyman Rosen wrote:
> Nom De Plume wrote:

[...]

>> Of course something like this could be done in C++ but
>> it would be a lot of hand coding to produce the equivalent
>> lazy mechanism.
>
> I wouldn't call it a lot - here is equivalent code to yours.

[...]

There's much more to lazy evaluation than Nom De Plume's pedagogical
infinite streams example suggests. Any decent book on functional
programming should cover it.

-thant
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: 25 Jan 03 13:38:18 GMT
Raw View
Andreas Rossberg wrote:
> But it is as convenient as encoding OO in Assembler.
 > So C++ could indeed benefit from taking a closer look
 > at features found in such languages.

Such a close look has been taken. Check out, for example,
<http://spirit.sourceforge.net/index.php?doc=docs/phoenix_v1_0/introduction.html>.

As far as my example goes, "laziness" would simply involve
keeping a memoizing vector in the generator classes. What's
the big deal?


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: llewelly <llewelly.@@xmission.dot.com>
Date: 23 Jan 03 07:18:05 GMT
Raw View
Hyman Rosen <hyrosen@mail.com> writes:

 > llewelly wrote:
 > > A third solution is to add another layer of indirection:
 > >   |pointer_to_closure|--->|pointer_to_nested_function|--->|nested_function_code|
 > >                           |pointer_to_stack_frame    |-+
 > >                                                        +->|stack_frame|
 >
 > Reemember, one of my requirements, or at least nice-to-haves, i sfor a pointer
 > to a closure to be just a pointer to code, so that it can be passed to things
 > that want traditional pointers to functions, like legacy C code in GUIs and
 > such. I don't think this scheme helps.

Then I ask you to re-examine the thunk-based version I included in my
     post, which you snipped.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: jpotter@falcon.lhup.edu (John Potter)
Date: 23 Jan 03 07:18:25 GMT
Raw View
On 21 Jan 2003 05:59:54 -0500, llewelly <llewelly.@@xmission.dot.com>
wrote:

 > jpotter@falcon.lhup.edu (John Potter) writes:

 > > On 18 Jan 2003 05:40:33 -0500, brangdon@cix.co.uk (Dave Harris) wrote:

 > > > What I am getting from your messages is a flat refusal
 > > > to even acknowledge the possibility.

 > > Just call me overly conservative.  I see the chance of the whole
 > > language
 > > following the path of std::string.
 > [snip]

 > What do you mean by this?

 > Do you mean you expect every new feature to come in the form of a
 >     class library with an overly large interface that contains
 >     unecessary uses of templates?

 > Do you mean something entirely different?

A function which does one thing is good.

A class which does one thing is good.

A programming language which tries to do everything in every way is
__________.

John

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Hyman Rosen <hyrosen@mail.com>
Date: 23 Jan 03 07:21:19 GMT
Raw View
Nom De Plume wrote:
> squares [] = []
> squares [h:t] = h*h : squares t
> SumOfFirstFive = sum(take 5 squares[1..])
>
  > Of course something like this could be done in C++ but
> it would be a lot of hand coding to produce the equivalent
> lazy mechanism.

I wouldn't call it a lot - here is equivalent code to yours.
Notice that I have included implementations of 1.., take,
and sum, while you have not. The C++ implementation of
squares is only eight lines, including a convenience routine
which is not strictly necessary.


struct integers_from {
     int n;
     integers_from(int n) : n(n) { }
     int operator()() { return n++; }
     bool more() { return true; }
};

template <class Input> struct squares_t {
     Input i;
     squares_t(Input i) : i(i) { }
     int operator()() { int n = i(); return n * n; }
     bool more() { return i.more(); }
};
template <class Input> squares_t<Input> squares(Input i)
{ return squares_t<Input>(i); }

template <class Input> struct take_t {
     int n;
     Input i;
     take_t(int n, Input i) : n(n), i(i) { }
     bool more() { return n > 0 && i.more(); }
     int operator()() { --n; return i(); }
};
template <class Input> take_t<Input> take(int n, Input i)
{ return take_t<Input>(n, i); }

template <class Input> int summer(Input i) {
     int sum = 0;
     while (i.more())
         sum += i();
     return sum;
}

int main()
{ return summer(take(5, squares(integers_from(1)))); }


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Thant Tessman <thant@acm.org>
Date: 23 Jan 2003 05:43:26 -0500
Raw View
Nom De Plume wrote:

[...]

> You missed one of the most important concepts in all pure
> functional languages, namely ubiquitous lazy evaluation.
> That is to say values are only calculated when they are
> used. This is a core idea in functional languages.

Not to detract from a well-written post, but lazy techniques can be
simulated in eager FP languages and vice versa without much
inconvenience. Support for lambda is at the heart of both approaches.

-thant
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Steven E. Harris" <seharris@raytheon.com>
Date: 23 Jan 2003 05:50:21 -0500
Raw View
nde_plume@ziplip.com (Nom De Plume) writes:

> Of course something like this could be done in C++ but it would be a
> lot of hand coding to produce the equivalent lazy mechanism.

I consider std::istream_iterator to be this kind of "infinite"
generator. For your infinite list, a non-default-constructed iterator
would never equal the default-constructed "end" iterator. If you
assume that the represented range is infinite, then such comparison to
check for the end would never be necessary anyway.

Could your lazy consumption of an infinite list work with such an
infinite generator?


gen_iter::gen_iter(int i)
    : i_( i )
{}


gen_iter& gen_iter::operator++()
{
    ++i_;
    return *this;
}


gen_iter gen_iter::operator++(int)
{
    const gen_iter prev = * this;
    ++i_;
    return prev;
}


int gen_iter::operator*() const
{ return i_; }


We could expand this to a random access iterator since the content
(the /i_/ variable) is easily correlated with position.

You could then write a similar "squares" iterator that wraps one of
these iterators above, doing the multiplication upon reading each new
value. Finally, SumOfFirstFive() could be written something like

template <class InIt>
int SumOfFirstFive(InIt it)
{
   int sum = 0;
   for ( size_t i = 0; i != 5; ++i, ++it )
       sum += *it;
   return sum;
}

where we assume that there are at least five valid positions. If we
are working with a delimited range, std::accumulate would do the job
too.

Maybe this is all too much work, though.

--
Steven E. Harris        :: seharris@raytheon.com
Raytheon                :: http://www.raytheon.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nde_plume@ziplip.com (Nom De Plume)
Date: 22 Jan 03 05:32:54 GMT
Raw View
brangdon@cix.co.uk (Dave Harris) wrote in message news:<memo.20030117132217.22031B@brangdon.madasafish.com>...
 > o   Genericity.
 > o   Recursion.
 > o   Garbage collection.
 > o   Type inference.
 > o   Pattern matching.
 > o   List comprehensions.

You missed one of the most important concepts in all pure
functional languages, namely ubiquitous lazy evaluation.
That is to say values are only calculated when they are
used. This is a core idea in functional languages.

It is vital to the functionality of lists in such languages.
At the core of many functional expressions is the idea of
an infinite list. For example, a function to calculate
the sum of the first five squares would look something like
this (sorry, I don't remember much exact syntax, but you
should get the idea.)

squares [] = []
squares [h:t] = h*h : squares t
SumOfFirstFive = sum(take 5 squares[1..])

The first two lines define a list which consists
of the squares of the input list of numbers. It does
this declaratively, declaring that the squares of an
empty list is empty, and the squares of a list composed
of a head h and a tail t is the square of h followed
by the squares function applied to the tail.

Finally, SumOfFirstFive is declared to be the sum of
a list consisting of the first five elements of the
squares function applied to an infinite list of integers
starting at 1.

An implementation of this kind in C++ would not work at
all, because obviously you can't calculate an infinite
list. However, in a functional language the values of
the list are calculated when they are used (lazily) and
consequently an infinite series is OK, because you only
calculate the values you actually use.

Of course something like this could be done in C++ but
it would be a lot of hand coding to produce the equivalent
lazy mechanism.

I ramble on about this quite simply to point out that
there is no way that such functionality will ever be
available as part of the C++ language. It is anathema
to the fundamental models and paradigms of C++.
However, of course, it can be simulated with a bunch of
work. It is a mistake to think that the reason functional
languages handle lists so gracefully is only notational,
rather it is a fundamental characteristic of the underlying
machine model.

Consequently, C++'s multi-paradigm approach will never
include the functional paradigm, it is too far out
of the ball park. However, we can import some of the
useful ideas in. Some libraries like lambda and bliss
have attempted to do so, by pushing the template mechanisms
to the limit, and that is good. However, IMHO one of their
fundamental goals is to simulate the lambda function of
functional languages, that is the anonymous, in-place
declaration of a function, treating a function as a first
class object like an int or a struct. The lambda library
and its ilk are clever, in both senses of that word. It
shows immense skill on the part of the writers, but it also
damns with faint praise the underlying language mechanisms
that require such machinations for a technique that is so
obviously useful, and so obviously missing.

I would, along these lines, reiterate the need for
a genuine lambda function in the language, as I have
proposed elsewhere in this thread.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: allan_w@my-dejanews.com (Allan W)
Date: 22 Jan 03 05:33:34 GMT
Raw View
kanze@gabi-soft.de (James Kanze) wrote
> Hyman Rosen <hyrosen@mail.com> wrote
> > David Thompson wrote:
> > > If such pointers take some extra space, so what?
>
> > They become incompatible with ordinary pointers to functions. That
> > means you need new syntax for naming this type of pointer, and you
> > cannot use them where ordinary function pointers are expected. This
> > somewhat lowers their utility.
>
> That's one solution.
>
> Another is to leave them compatible with ordinary pointers to functions.
> This works well, but means that ordinary function pointers "cost" more.
> If you don't need pointers to nested functions, you end up paying for
> something you don't use.  Although the price isn't that high, some
> people do oppose it.

The "cost" isn't the only reason that people object to changing the
way that pointers are represented. Another reason is compatibility
with old libraries, especially libraries in different languages.
Obviously the C++ standard can't be concerned with how the language
interfaces to other languages -- but real-world vendors must be.
If you change what a pointer looks like in C++, then all code that
crosses language borders needs to be revised -- and some of it won't
work at all, anymore.

In my opinion, it's a good idea -- but better make sure that C++
vendors can turn it on and off with a compile option, so that it
supports legacy libraries and cross-language development.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: kanze@gabi-soft.de (James Kanze)
Date: 22 Jan 03 05:33:20 GMT
Raw View
nde_plume@ziplip.com (Nom De Plume) wrote in message
news:<b59f4084.0301191451.372795be@posting.google.com>...
> kanze@gabi-soft.de (James Kanze) wrote in message
> news:<d6651fb6.0212300455.885ae41@posting.google.com>...

> >   - At every point Within a function, there is an implicitly defined
> >     class with the name __local_context.  This class is semantically
> >     defined as containing a reference to every visible variable with
> >     automatic storage duration, pre-initialized to refer to that
> >     variable.  (I can imagine that in many, if not all cases, the
actual
> >     implementation can do better.)  These member variables have the
same
> >     name as the referred to variable, and are public or protected
(TBD).

> James, I don't know if you have been following some of the comments I
> have made elsewhere in this thread regarding anonymous functions, but
> they cover IMHO most of the most common cases where this type of thing
> would be necessary.

I've not been following this thread too closely, but I've seen quite a
number of such proposals in the past.

IMHO, the class is necessary.  One of the more frequent uses of local
functions is for a callback.  In C++, the "correct" way to implement a
callback is by means of an abstract class; the client code derives from
the abstract class in order to implement the callback.

> I personally like th idea of __local_context, though I'd probably
> argue with some of the details (and you can probably forget gettting a
> new keyword into the new standard -- hence my choice of inline.)

A new keyword is not impossible, provided that there is justification.
We've done it before.  (Obviously, the keyword should be choses to
minimize possible conflicts.  I doubt that reinterpret_cast broke a
single program, for example.)  In this case, I suspect local_context
would not cause problems; I propose, however __local_context, because
this symbol cannot occur in any legal program today.

> However, one place you seem to fall short is in access to class member
> variables and functions.  (I understand your still thinking it
> through, and my comments are designed to help you improve on something
> I'd love to see in the standard.)

You seem to be suggesting something like Java's inner classes.

I hadn't actually though about the question.  A priori, the local
context is visible, and the this of the function is part of the local
context.  The only problem is naming it: if I just say this in the
class, it obviously refers to the this of the __local_context class, and
not the this of the function in which it resides.

I like the idea of being able to access the outer this, if some
appropriate syntax could be found.  (How about "that":-).  And no, I'm
not at all serious.)  What we definitly don't want is namelookup to
consider both classes indiscriminately -- I've experienced that with
Java inner classes, and it is a real disaster for program readability.
Not to mention the ambiguities that it introduces.

> Access of this kind seems to be quite a common requirement.  You state
> that the context class contains a ref to every visible automatic
> variable, but that might be quite a subtle thing to in regards to
> member variables.

I was not thinking of member variables.  __local_context should
definitly NOT make member variables visible without any special syntax.
Some way of accessing the functions this pointer should do the trick.

> For example:

> class A { public: int intVar; void g();};

> int f()
> {
>   A a;
>   A* ap = new A;
>   a.g();
>   a->g();
> }

> void A::g()
> {
>   // for a intVar is auto or at least part of an auto
>   // for ap intVar is not auto and is not part of an auto
> }

> is intVar visible in a lambda class defined in A::g?

Not without some special syntax.  Maybe __outer_this->intVar.  Or
__outer::intVar.  It's worth thinking about.

Another possibility would be a second implicit class __member_context.
If you wanted both, there's multiple inheritance, and __member_context::
can be used to resolve ambiguities.  The advantage of __member_context
is that it would have the lifetime of the object, and would still be
usable after returning from the function.  But I'm not sure it is
worthwhile -- __member_context can easily be obtained by passing a
single parameter (the this pointer) to the constructor of a local
class.  (Simulating __local_context would require passing all of the
visible variables to the constructor.)

> I suppose you could reword your statement above to include member
> variables of the enclosing class in your __local_context, but what
> about member functions?  Again, I suppose you could define
> __local_context to include aliases to those too.

You could.  Java does.  For once, someone else has done the
experimenting.  Existing practice (supposing you can apply existing
practice in Java to C++, and in this case, I think wew can) shows that
it is a bad idea.  A horrible idea, in fact, and something which must be
avoided.

Or do you think that name lookup and overload resolution is too simple
in C++.  Actually, it is slightly simpler in C++ than in Java, because
of function hiding.  So maybe it wouldn't be quite as bad as in Java.
But I'd still oppose it.

> Also can you explain why public or protected? Their access specifier
> only modifies which non-member function can call this function, yet if
> it is defined within a member the point is moot, and if it is defined
> outside of a member then it is irrelevant.

Because __local_context doesn't have any member functions.  So there
would be no way what so ever to access private variables.

Most of the uses would involve deriving from __local_context.  So
protected is probably open enough.  But there doesn't seem to be any
strong argument against public -- the only place __local_context is
visible is within the function, and of course, within the function, all
of the variables are visible anyway.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: brangdon@cix.co.uk (Dave Harris)
Date: 22 Jan 03 05:33:55 GMT
Raw View
nde_plume@ziplip.com (Nom De Plume) wrote (abridged):
> It is not really a closure,

Agreed; I mix closures with lambdas sometimes, which is a dreadful habit
:-)


> it is simply a convenient way to define a function in place.

Ah. Here we differ. I am looking for a convenient way to define a functor.
A functor is a function or something which looks like a function. It is a
more general notion.

So my criticism here is lack of ambition. A language change is such a big
deal it really ought to solve the bigger problem.


> Consequently, I don't see that inheritance has much meaning here
> (since it is only visible in the function in which it is
> declared), and similarly it is clearly not virtual
> since again, it is only usable in the function in which
> it is declared.

It is also visible to the functions it is passed to. Sort(), in your
examples. What is it these functions see? (More on this below.)


> > [A functor which is a struct with a base class]
>
> It is not really obvious to me what extra benefit this
> offers.

One advantage of using proper objects is that they can have arbitrary
state. Plain function pointers can't. In some of your examples (elsewhere
in the thread) you have tried to work around the lack by passing extra
data with the pointer-to-function. I feel this is bad engineering - it is
better to have the single object.

Some other of your examples allow the lambda to use variables from the
enclosing scope - true closures. But now this is no longer a simple
pointer to function. In a plain:

    void (*pFunc)( const Item &item );

there is nowhere to store a reference to total_price_ (or to the instance
of Items which holds the total_price_), unless you store that reference in
the code segment (which is problematic). Your getTotalPrice() really does
need something like a struct behind the scenes.

This is why I asked what you thought the type of a lambda function would
be. I don't think it can be a plain pointer-to-function if we want it to
have access to local variables.

I am especially interested in how functions which accept lambdas should be
declared. Your examples seem to use templates, so it is left to template
argument deduction. Is it your intent that lambdas only be used with
template functions? If so, this is another failure of ambition. If not...

Let's suppose I have a complex data structure and I want a for_all()
routine which iterates over it. I don't want for_all() to be a template.
How should I declare for_all() ? You seem to have in mind something like:

    void for_all( Tree *pRoot, void (*pFunc)(Leaf *) );

As I've argued above, I think this is problematic if we want the lambda
argument to have access to local variables. The approach of passing
through an extra argument looks reasonable if we are defining a template:

    template <typename Func, typename Arg>
    void for_all( Tree *pRoot, Func f, Arg &arg );

but doesn't scale for concrete types:

    void for_all( Tree *pRoot, void (*pFunc)(Leaf *, double &), double &);

because we might want int or some other type instead of double.

Currently such programming problems are solved with real structs and
dynamic polymorphism:

    struct FunctorBase {
       virtual bool operator()( Leaf * ) = 0;
    };

    void for_all( Tree *pRoot, FunctorBase &f );

Now client code can subclass FunctorBase and add whatever state is needed
there. It is a good, general solution.

In my view, any new proposal ought to be compatible with this. I don't
want to add a new lambda feature if it means the author of for_all() has
to choose between functors and lambdas.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: allan_w@my-dejanews.com (Allan W)
Date: 22 Jan 03 05:34:13 GMT
Raw View
brangdon@cix.co.uk (Dave Harris) wrote
> I think list comprehensions are really just a part of
> general support for working with lists. The C++ equivalent is probably
> c-arrays. We have literal arrays and some standard supported idioms, but
> maybe that is now feeling a bit archaic. std::vector has advantages over
> c-arrays, such as being growable. Perhaps they would be easier to work
> with if they had more support from the language syntax. Eg:
>
>     std::vector v = { 1, 2, 3, x, y, z };
>
> Maybe not. I don't have any worked out proposal, and these newsgroups may
> not be the best place for detailed brain-storming. However, the potential
> is worth exploring. What I am getting from your messages is a flat refusal
> to even acknowledge the possibility.

I not only acknowledge the possibility, I absolutely love it. Please
do discuss this at the next committee meeting.

It seems that most of the "proposals" here make the language more rich
at the expense of increasing it's complexity. Something like the code
above would make it more rich while actually getting less complex (for
the user, at least). Such code is likely to have fewer bugs, too...
such as trying to stuff a pointer into an array of int.

I think it makes sense to simplify the source language (for the user)
whenever this is feasible, especially if it can be done in a way that
doesn't break legacy code.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: jpotter@falcon.lhup.edu (John Potter)
Date: 20 Jan 03 05:55:28 GMT
Raw View
On 18 Jan 2003 05:40:33 -0500, brangdon@cix.co.uk (Dave Harris) wrote:

> What I am getting from your messages is a flat refusal
> to even acknowledge the possibility.

Just call me overly conservative.  I see the chance of the whole
language
following the path of std::string.

John

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Derek Ross <math@antiquark.com>
Date: 20 Jan 03 05:55:58 GMT
Raw View
Dave Harris wrote:
> For example, I think list comprehensions are really just a part of
> general support for working with lists. The C++ equivalent is probably

> c-arrays. We have literal arrays and some standard supported idioms,
but
> maybe that is now feeling a bit archaic. std::vector has advantages
over
> c-arrays, such as being growable. Perhaps they would be easier to work

> with if they had more support from the language syntax. Eg:
>
>     std::vector v = { 1, 2, 3, x, y, z };
>

IMHO, one of the reasons there is so much inertia with C++ is that it
almost always seems possible to recreate a feature with existing
language capabilities, rather than adding the feature to the core
language.

The example above can be emulated with template functions, so that

   vector<int> v = { 1, 2, 3, x, y, z };

becomes

   vector<int> v;
   vec << 11 , 22 , 33 , x , y , z;

Of course, it's a pain to write template functions whenever you want to
initialize an array, and the C-syntax is well known and easy to
remember.  However, if you write code that requires lots of array
initializations, it might be easier than using '.push_back'.

Also, you talked a bit about Haskell's capabilities. There is a C++
library, FC++, that claims to emulate functional language
characteristics.  It can be found at
http://www.cc.gatech.edu/~yannis/fc++/

There's also the boost-lambda library that's similar:
http://www.boost.org/libs/lambda/doc/

Just my 20 millibucks,
Derek
__________________________________________
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>

using namespace std;

template<class CONT, class VALUE>
CONT& operator<<(CONT& container, const VALUE& value)
{
 container.push_back(value);
 return container;
}

template<class CONT, class VALUE>
CONT& operator,(CONT& container, const VALUE& value)
{
 container.push_back(value);
 return container;
}

int main()
{
 int x=44, y=55, z=66;
 vector<int> vec ;
 vec << 11 , 22 , 33, x , y , z;

 ostream_iterator<int> os(cout, "\n");
 unique_copy(vec.begin(), vec.end(), os);
}

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: pavel_vozenilek@yahoo.co.uk (Pavel Vozenilek)
Date: 20 Jan 03 05:56:11 GMT
Raw View
brangdon@cix.co.uk (Dave Harris) wrote in message news:<memo.20030117132217.22031B@brangdon.madasafish.com>...
 > jpotter@falcon.lhup.edu (John Potter) wrote (abridged):
[snip]
 > std::vector has advantages over
 > c-arrays, such as being growable. Perhaps they would be easier to work
 > with if they had more support from the language syntax. Eg:
 >
 >     std::vector v = { 1, 2, 3, x, y, z };
 >
 > Maybe not. I don't have any worked out proposal, and these newsgroups may
 > not be the best place for detailed brain-storming. However, the potential
 > is worth exploring.
 >
Thorsten Ottosen (http://www.cs.auc.dk/~nesotto/init/) has library
with similar functionality (and it may be added to Boost some time).

/Pavel

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: llewelly <llewelly.@@xmission.dot.com>
Date: 20 Jan 03 05:56:53 GMT
Raw View
kanze@gabi-soft.de (James Kanze) writes:

 > Hyman Rosen <hyrosen@mail.com> wrote in message
 > news:<1042583738.40202@master.nyc.kbcfp.com>...
 > > David Thompson wrote:
 > > > If such pointers take some extra space, so what?
 >
 > > They become incompatible with ordinary pointers to functions. That
 > > means you need new syntax for naming this type of pointer, and you
 > > cannot use them where ordinary function pointers are expected. This
 > > somewhat lowers their utility.
 >
 > That's one solution.
 >
 > Another is to leave them compatible with ordinary pointers to functions.
 > This works well, but means that ordinary function pointers "cost" more.
 > If you don't need pointers to nested functions, you end up paying for
 > something you don't use.  Although the price isn't that high, some
 > people do oppose it.


A third solution is to add another layer of indirection:

  +------------------+    +--------------------------+    +--------------------+
  |pointer_to_closure|--->|pointer_to_nested_function|--->|nested_function_code|
  +------------------+    +--------------------------+    +--------------------+
                          |pointer_to_stack_frame    |-+
                          +--------------------------+ |  +-----------+
                                                       +->|stack_frame|
                                                          +-----------+

Here, nested_function_code takes a hidden parameter which is a pointer
     to the stack frame. The cost is one extra dereference to call the
     function (2 total) and one extra dereference to pass the pointer
     to the stack frame to the function.

And ordinary function pointers are implemented as they are already:

  +-------------------+    +-------------+
  |pointer_to_function|--->|function_code|
  +-------------------+    +-------------+

This scheme provides compatiblity between currently availible pointers
     to functions, and suggested pointers to closures or local
     functions, while keeping the space and calling cost of ordinary
     function pointers low. The price is additional expense in calling
     closures indirectly.

On an archeticture where pointers to data and pointers to code are
     different sizes, a similar, but thunk-based approach is needed:

  +------------------+    +----------+
  |pointer_to_closure|--->|thunk_code|
  +------------------+    +----------+----------------+   +-----------+
                          |pass_pointer_to_stack_frame|-->|stack_frame|
                          +---------------------------+   +-----------+
                          |call_nested_function_code  |-+
                          +---------------------------+ |  +--------------------+
                                                        +->|nested_function_code|
                                                           +--------------------+

Here, pass_pointer_to_stack_frame is a (run-time generated) sequence
     of machine code which adds a pointer to the stack frame to the
     argument list, and then calls the nested_function_code.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: brangdon@cix.co.uk (Dave Harris)
Date: 20 Jan 03 05:58:04 GMT
Raw View
nde_plume@ziplip.com (Nom De Plume) wrote (abridged):
> void sort_em(vector<s>& data)
> {
>   sort(data.begin(), data.end(),
>        inline bool(const s& lhs, const s& rhs)
>        {
>            return lhs.b < rhs.b;
>        });
> }

Have you thought about what the type of a closure would be? Can they
inherit? Be virtual? Const?

    struct CompareBase {
        virtual bool operator()( const s&, const s& ) const = 0;
    };

    void my_sort( s *, s *, const CompareBase & );

    void sort_em( s data[], int len ) {
        my_sort( data, data+len,
             inline bool( const s &lhs, const s &rhs )
                    const public CompareBase {
                 return lhs.b < rhs.b;
             }
    }

Without this they lose a lot of their power. Yet the syntax is getting a
verbose, because there is more to declare. And I haven't mentioned
exception specifications yet.

Because there are no templates, we can today use:

    void sort_em( s data[], int len ) {
         struct MyCompare : CompareBase {
             virtual bool operator( const s &lhs, const s &rhs ) const {
                 return lhs.b < rhs.b;
             }
         };

         my_sort( data, data+len, MyCompare() );
    }

which I think is easier to follow. The "inline" syntax is nice in simple
cases but it doesn't scale well.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nde_plume@ziplip.com (Nom De Plume)
Date: 20 Jan 2003 07:51:52 -0500
Raw View
kanze@gabi-soft.de (James Kanze) wrote in message news:<d6651fb6.0212300455.885ae41@posting.google.com>...
>   - At every point Within a function, there is an implicitly defined
>     class with the name __local_context.  This class is semantically
>     defined as containing a reference to every visible variable with
>     automatic storage duration, pre-initialized to refer to that
>     variable.  (I can imagine that in many, if not all cases, the actual
>     implementation can do better.)  These member variables have the same
>     name as the referred to variable, and are public or protected (TBD).

James, I don't know if you have been following some of the
comments I have made elsewhere in this thread regarding
anonymous functions, but they cover IMHO most of the most
common cases where this type of thing would be necessary.

I personally like th idea of __local_context, though I'd
probably argue with some of the details (and you can probably
forget gettting a new keyword into the new standard -- hence
my choice of inline.) However, one place you seem to fall
short is in access to class member variables and functions.
(I understand your still thinking it through, and my comments
are designed to help you improve on something I'd love to
see in the standard.)

Access of this kind seems to be quite a common requirement.
You state that the context class contains a ref to every
visible automatic variable, but that might be quite a
subtle thing to in regards to member variables. For example:

class A { public: int intVar; void g();};

int f()
{
  A a;
  A* ap = new A;
  a.g();
  a->g();
}

void A::g()
{
  // for a intVar is auto or at least part of an auto
  // for ap intVar is not auto and is not part of an auto
}

is intVar visible in a lambda class defined in A::g?
I suppose you could reword your statement above to
include member variables of the enclosing class in your
__local_context, but what about member functions?
Again, I suppose you could define __local_context to
include aliases to those too.

Also can you explain why public or protected? Their access
specifier only modifies which non-member function can call
this function, yet if it is defined within a member the point
is moot, and if it is defined outside of a member then it
is irrelevant.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly <llewelly.@@xmission.dot.com>
Date: 21 Jan 2003 05:59:54 -0500
Raw View
jpotter@falcon.lhup.edu (John Potter) writes:

> On 18 Jan 2003 05:40:33 -0500, brangdon@cix.co.uk (Dave Harris) wrote:
>
> > What I am getting from your messages is a flat refusal
> > to even acknowledge the possibility.
>
> Just call me overly conservative.  I see the chance of the whole
> language
> following the path of std::string.
[snip]

What do you mean by this?

Do you mean you expect every new feature to come in the form of a
    class library with an overly large interface that contains
    unecessary uses of templates?

Do you mean something entirely different?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: cbarron3@ix.netcom.com (Carl Barron)
Date: 21 Jan 2003 06:00:33 -0500
Raw View
Derek Ross <math@antiquark.com> wrote:

> using namespace std;
>
> template<class CONT, class VALUE>
> CONT& operator<<(CONT& container, const VALUE& value)
> {
>       container.push_back(value);
>       return container;
> }
>
> template<class CONT, class VALUE>
> CONT& operator,(CONT& container, const VALUE& value)
> {
>       container.push_back(value);
>       return container;
> }
>
> int main()
> {
>       int x=44, y=55, z=66;
>       vector<int> vec ;
>       vec << 11 , 22 , 33, x , y , z;
   or just use operator << ala basic_ostream<...> might be more
intuitive...
        vec << 11 << 22 << 33 << x << y << z;
>
>       ostream_iterator<int> os(cout, "\n");
>       unique_copy(vec.begin(), vec.end(), os);
> }

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nde_plume@ziplip.com (Nom De Plume)
Date: 21 Jan 2003 12:56:36 -0500
Raw View
brangdon@cix.co.uk (Dave Harris) wrote in message news:<memo.20030119173540.16537D@brangdon.madasafish.com>...
> nde_plume@ziplip.com (Nom De Plume) wrote (abridged):
> > void sort_em(vector<s>& data)
> > {
> >   sort(data.begin(), data.end(),
> >        inline bool(const s& lhs, const s& rhs)
> >        {
> >            return lhs.b < rhs.b;
> >        });
> > }
>
> Have you thought about what the type of a closure would be? Can they
> inherit? Be virtual? Const?

It is not really a closure, it is simply a convenient
way to define a function in place. Consequently, I
don't see that inheritance has much meaning here (since
it is only visible in the function in which it is
declared), and similarly it is clearly not virtual
since again, it is only usable in the function in which
it is declared.

Your question concerning const though is interesting,
and one I hadn't thought about. Again, since global
functions can't take a const specifier it isn't relevant
there, however, if it is a "class inline" that is
an anonymous member function, then it surely is relevant
whether it is const or not. However, I think the answer
is fairly obvious: it inherits its const-ness from the
enclosing function. I could go either way as to whether
this was implicit, or whether you had to explicitly
state it in the anonymous declaration, viz:

class Items {
public: double getTotalPrice() const;
private: std::list<Item> items_;
mutable double total_price_;
mutable bool dirty_;
};

double Items::getTotalPrice() const
{
  if( ! dirty_)
  {
    total_price_ = 0.0;
    for_each(items_.begin(), items_.end(),
       class inline (const Item& item) //*****
       {
           total_price_ += item.price();
       }
    dirty_ - true;
  }
  return total_price_;
}

The question is should the line marked ***** be as
is, (the const-ness being implied from the context)
or should it be:

class inline(const Item& item) const

As I say, I can go either way on that one.

>     struct CompareBase {
>         virtual bool operator()( const s&, const s& ) const = 0;
>     };
>
>     void my_sort( s *, s *, const CompareBase & );
>
>     void sort_em( s data[], int len ) {
>         my_sort( data, data+len,
>              inline bool( const s &lhs, const s &rhs )
>                     const public CompareBase {
>                  return lhs.b < rhs.b;
>              }
>     }
>
> Without this they lose a lot of their power.

It is not really obvious to me what extra benefit this
offers. If you are going to use a functor specified
outside the function then you can just go with the
syntax we already have. The syntax you give here
doesn't really make sense to me, since the anonymous
function is, obviously, a function, not a class (or
functor), so the inheritance doesn't seem appropriate.

To help develop this proposal, I would certainly welcome
any concrete examples of where this mechanism isn't
powerful enough. I've been plugging through lots of my
own code trying to rewrite all the loops using this
mechanism, and this solution seems to address 95% of them.
The main problem I have had is to do with exceptional
flow control (breaks, gotos, returns and continues, which
aren't great programming practice anyway.)

> Yet the syntax is getting a
> verbose, because there is more to declare. And I haven't mentioned
> exception specifications yet.

Personally I don't use exception specifications. I am sure
they will be subject to a serious reexamination in the next
version of the standard. However, I suppose you could include
them as part of the function declaration.

> which I think is easier to follow. The "inline" syntax is nice in simple
> cases but it doesn't scale well.

Thanks for your comments. They were both helpful and
interesting.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: 21 Jan 2003 12:57:25 -0500
Raw View
llewelly wrote:
> A third solution is to add another layer of indirection:
>   |pointer_to_closure|--->|pointer_to_nested_function|--->|nested_function_code|
>                           |pointer_to_stack_frame    |-+
>                                                        +->|stack_frame|

Reemember, one of my requirements, or at least nice-to-haves, i sfor a pointer
to a closure to be just a pointer to code, so that it can be passed to things
that want traditional pointers to functions, like legacy C code in GUIs and
such. I don't think this scheme helps.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Gabriel Dos Reis <gdr@integrable-solutions.net>
Date: 20 Jan 2003 16:13:31 -0500
Raw View
Derek Ross <math@antiquark.com> writes:

| Dave Harris wrote:
| > For example, I think list comprehensions are really just a part of
| > general support for working with lists. The C++ equivalent is probably
|
| > c-arrays. We have literal arrays and some standard supported idioms,
| but
| > maybe that is now feeling a bit archaic. std::vector has advantages
| over
| > c-arrays, such as being growable. Perhaps they would be easier to work
|
| > with if they had more support from the language syntax. Eg:
| >
| >     std::vector v = { 1, 2, 3, x, y, z };
| >
|
| IMHO, one of the reasons there is so much inertia with C++ is that it
| almost always seems possible to recreate a feature with existing
| language capabilities, rather than adding the feature to the core
| language.
|
| The example above can be emulated with template functions, so that
|
|    vector<int> v = { 1, 2, 3, x, y, z };
|
| becomes
|
|    vector<int> v;
|    vec << 11 , 22 , 33 , x , y , z;

Except that the second (ab)uses operator, overloading and operator<<
is the canonical way for formatting (there is no formatting here).
std::vector<> is usually recommended as the C++ array, still it makes it
unnecessarily painful to write things the obvious way.  I don't
consider obfuscation an acceptable way to write daily programs.

| Of course, it's a pain to write template functions whenever you want to
| initialize an array, and the C-syntax is well known and easy to
| remember.  However, if you write code that requires lots of array
| initializations, it might be easier than using '.push_back'.

That however fails with:

   static const std::vector<int> v = { /* lots of data */ };

--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 18 Jan 2003 05:36:35 -0500
Raw View
Hyman Rosen <hyrosen@mail.com> wrote in message
news:<1042583738.40202@master.nyc.kbcfp.com>...
> David Thompson wrote:
> > If such pointers take some extra space, so what?

> They become incompatible with ordinary pointers to functions. That
> means you need new syntax for naming this type of pointer, and you
> cannot use them where ordinary function pointers are expected. This
> somewhat lowers their utility.

That's one solution.

Another is to leave them compatible with ordinary pointers to functions.
This works well, but means that ordinary function pointers "cost" more.
If you don't need pointers to nested functions, you end up paying for
something you don't use.  Although the price isn't that high, some
people do oppose it.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: 18 Jan 2003 05:40:33 -0500
Raw View
jpotter@falcon.lhup.edu (John Potter) wrote (abridged):
> The notation does not look anything like procedural languages.
> [...] The concepts are not procedural.

It doesn't look much like C++. However, the concepts are not alien to
procedural languages. Here's my list:

o   Genericity.
o   Recursion.
o   Garbage collection.
o   Type inference.
o   Pattern matching.
o   List comprehensions.

The first two are in C++ already, garbage collection is available as an
option, and type inference is regularly discussed here (eg the "let x =
1;" proposal). Pattern matching is available at run-time via libraries and
a form of it at compile-time with overloading and template specialisation.
Other procedural languages, such as Cecil, get closer here.

I don't think anyone has raised list comprehensions before. They are
related to closures which are a perennial topic. Their relative novelty
makes them more worthy of discussion now. I don't think anyone is saying
they should be dropped into C++ without thought. Rather, that we should
look at what Haskell does with them, decide whether we like it, analyse
how the benefits are achieved, before thinking about how they might
translate to C++.

For example, I think list comprehensions are really just a part of
general support for working with lists. The C++ equivalent is probably
c-arrays. We have literal arrays and some standard supported idioms, but
maybe that is now feeling a bit archaic. std::vector has advantages over
c-arrays, such as being growable. Perhaps they would be easier to work
with if they had more support from the language syntax. Eg:

    std::vector v = { 1, 2, 3, x, y, z };

Maybe not. I don't have any worked out proposal, and these newsgroups may
not be the best place for detailed brain-storming. However, the potential
is worth exploring. What I am getting from your messages is a flat refusal
to even acknowledge the possibility.


 > Actually I think much of the cleanness of the code comes from not
> > having the clutter of type declarations.
>
> Yes, in the absence of state.

Actually I have seen similar cleanness in stateful languages, such as
Smalltalk.


> Type infered undeclared variables are a different story.

No-one is suggesting undeclared variables. That's too prone to errors from
typos.


> I wonder if it is worth the effort of the standard committee to
> investigate the possibility of changing C++ in unnatural ways to amuse
> the needs of a few.

I'm not asking the standards committee to do anything. I certainly don't
have a proposal for their next meeting.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Gabriel Dos Reis <gdr@integrable-solutions.net>
Date: 18 Jan 03 15:39:09 GMT
Raw View
brangdon@cix.co.uk (Dave Harris) writes:

|                                   Perhaps they would be easier to work
| with if they had more support from the language syntax. Eg:
|
|     std::vector v = { 1, 2, 3, x, y, z };
|
| Maybe not. I don't have any worked out proposal, and these newsgroups may
| not be the best place for detailed brain-storming. However, the potential
| is worth exploring.

Agreed.  I would like to see support for such thing. I do not believe
it would require major changes -- actually C99 already provides ome
kind of existing pratice ;-) Any C++ compiler already has code to deal
with like that, the only thing that is missing (i.e. visible at the
user level) is ascribing a type to that expression.  A naive approach
would consist in saying, the expression { 1, 2, 3, x, y, z } has type
'int [6]' provided x, y, z ares ints.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nagle@animats.com (John Nagle)
Date: Sat, 18 Jan 2003 19:28:25 +0000 (UTC)
Raw View
James Kanze wrote:
[proposing closures]

    It's certainly possible to put closures in C++,
but I don't see it as desirable.  LISP had closures
when it didn't have objects.  A common way to package
up a function and some data was to construct a closure.
But C++ has objects; it doesn't need closures as badly.

     Perl has true closures, but few Perl programmers
know it.  Most Perl books don't even mention them.

     Closures in C++ would result in pointers to the
stack that could easily outlive stack unwinding.
Pointers to closures are something that users are
likely to keep around, unlike ordinary references
to objects on the stack, which are usually just
passed to functions and dropped on return.  So this
introduces a new class of obscure bugs.
LISP and Perl protect their closures against that problem
with internal memory management, but C++ wouldn't.

    John Nagle
    Animats

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: 18 Jan 2003 15:52:52 -0500
Raw View
dheld@codelogicconsulting.com (David B. Held) wrote (abridged):
> I'm split on the usage of 'inline'.  On the one hand, it probably eases
> parsing.  On the other, the parser should be able to identify it as
> an anonymous function as soon as it sees <type>(<type>.

That only works if the function takes an argument. We could require a
"void", but I'd rather write:

    some_func( first, last, inline int() {
        return rand();
    } );

than:

    some_func( first, last, int(void) {
        return rand();
    } );

although I suppose it is a matter of taste.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: 16 Jan 03 05:23:19 GMT
Raw View
David Thompson wrote:
> If such pointers take some extra space, so what?

They become incompatible with ordinary pointers to functions.
That means you need new syntax for naming this type of pointer,
and you cannot use them where ordinary function pointers are
expected. This somewhat lowers their utility.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Julian Smith <jules@REMOVETHIS.op59.net>
Date: 13 Jan 03 09:02:58 GMT
Raw View
On 10 Jan 2003 23:07:56 -0500
nde_plume@ziplip.com (Nom De Plume) wrote:

> Some would argue that we put the less function as a member
> of s and use some combination of bind and mem_fn to pass
> into sort, however, that produces code that is extremely
> difficult to read.
>
> My alternative would be to allow the function "less_s"
> to be defined in place. Viz:
>
> void sort_em(vector<s>& data)
> {
>   sort(data.begin(), data.end(),
>        function bool(const s& lhs, const s& rhs)
>        {
>           return lhs.b < rhs.b;
>        });
> }
>
> I have invented a keyword "function" which means treat
> the following function definition as if it were defined
> just before the start of the containing function, do
> not give it a name, and then replace the function statement
> with a pointer to that function. This seems to me to be
> a fairly straightforward extension to a compiler.

Yes, this does make using STL algorthms a lot simpler.

My Cmm source translator system can do it - see:
http://www.op59.net/cmm/cmm-0.15/otherextensions.html#item2

The only difference from your example is that Cmm doesn't require the `function' keyword - the parser can figure out when something is a function definition instead of a conventional expression/declaration.

>
> Now, a similar syntax might be used for a functor, however
> many of the benefits that accrue to functors could be
> more gained by one slight addition to the above syntax.
>
> Lets say I want to write a function to sum the integers
> in a vector (obviously there are easier ways to do this
> but by way of illustration)
>
> int sum_em(const vector<int>& data)
> {
>   int total =0;
>   for_each(data.begin(), data.end(),
>            function void(const int datum)
>            {
>               access total;
>               total += datum;
>            });
>   return total;
> }
>
> Here I have introduced another speculative keyword: "access"
> What it means is make a reference to the "total" variable
> available in the anonymous function. This is achieved by the
> compiler by adding another anonymous parameter to the
> anonymous function and currying it with the local variable,
> and passing this curried function into for_each. (Which sounds
> rather more complex that it actually is.)

This is an interesting idea. I guess it's halfway to proper closures - making the compiler generate code that automatically has access to the entire state of the parent function.

I wonder if it would be practical to do this by implementing embedded functions as a member function of a compiler-generated class whose members were chosen to be references to all available local variables in the parent function.

>
> I believe these two additions, or something like them would
> greatly enhance the usefulness of the STL, and, perhaps more
> importantly, greatly clarify the current uses of these
> functions.
>
> Generic programming was relatively new in the C++ standard,
> and it kind of got dropped in at the last minute. Consequently
> it seems to me that this period before the revision is exactly
> the time to be looking at how generic programming is being
> used, and how to enhance the language to better support it.

Yes, now is definitely the time to try this sort of thing out and see whether it could be made to work.

- Julian

--
http://www.op59.net

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 13 Jan 03 09:03:19 GMT
Raw View
In article <b59f4084.0301100958.1e28f60d@posting.google.com>, Nom De
Plume <nde_plume@ziplip.com> writes
>Generic programming was relatively new in the C++ standard,
>and it kind of got dropped in at the last minute. Consequently
>it seems to me that this period before the revision is exactly
>the time to be looking at how generic programming is being
>used, and how to enhance the language to better support it.

I am not sure what you mean. Generic programming had (according to the
only person who could know, Bjarne Stroustrup) always been part of the
long term design of C++. What happened is that with the increasing
confidence gained between 89 and about 94 the provisions were extended
beyond what any existing compiler could handle. Then in the mid-90's we
came to realise that the generic technology we had built into C++ was
Turing complete. That was scary but a new generation of programmers came
along who started using this technology for meta-programming. There were
many motives for that, one of them being the desire to shift some
computational work to compile time and so make the resulting runtime
executable more efficient.

Those who are interested should note that the Conference mentioned in my
signature includes several key people in the arena of generic and
meta-programming. One of them (Simon Peyton Jones) was a key person in
designing and developing template extensions in Haskell, two others
(Andrei Alexandrescu and Ulrich Eisenecker) are leading authorities on
geberic and meta-programming in C++. It is no accident that they are all
together at the same (low cost)  event.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: jpotter@falcon.lhup.edu (John Potter)
Date: 13 Jan 03 09:04:21 GMT
Raw View
On 9 Jan 2003 12:36:44 -0500, brangdon@cix.co.uk (Dave Harris) wrote:

> jpotter@falcon.lhup.edu (John Potter) wrote (abridged):
> >  > > Cute. Eight lines in C++ or one using sort<>.  Unreadable gibberish
> >  > > to a procedural programmer.

> >  > It's unreadable gibberish to someone who doesn't know the notation.

> > Isn't notation what this is all about?

> Yes. But I'm not sure what your point was. You seemed to be saying the
> notation is intrinsically bad. If not that, then what?

The notation does not look anything like procedural languages.  A C++
class looks like a struct/record.  C++ has member functions not methods
because they look like procedural functions.

The concepts are not procedural.  Problem solutions require a different
mind set, paradigm.  How would these concepts fit into the grammar?

Are C++ practitioners asking for these features in the language?  Or is
it C++ dabblers who really enjoy playing in the other languages trying
to convert the practitioners?  I suspect the latter since most of the
estimated six million C++ practitioners could not care less and are not
represented on these newsgroups.

> Actually I think much of the cleanness of the code comes from not having
> the clutter of type declarations.

Yes, in the absence of state.  Type infered undeclared variables are
a different story.

> >  > o   Garbage collection.

> > Not important here.

> Well, it is, because each call to quicksort makes 4 new list objects. The
> memory for these needs to be reclaimed somehow.

It is not important here because quicksort can be done in place rather
than creating all those lists.  If you insist on the extra objects, it
is still not a problem in C++ because they are either local variables in
the function or unnamed temporaries.  C++ is not in the habbit of
creating garbage, you need to make an effort to do it.

template <class C>
C quick_sort (C const& src) {
    C ret;
    typename C::const_iterator b(src.begin());
    if (b == src.end() || ++ b == src.end())
        ret = src;
    else {
        typedef typename C::value_type V;
        remove_copy_if(b, src.end(), back_inserter(ret),
                bind2nd(greater<V>(), src.front()));
        ret = quick_sort(ret);
        ret.insert(ret.end(), src.front());
        C rst;
        remove_copy_if(b, src.end(), back_inserter(rst),
                bind1st(greater<V>(), src.front()));
        rst = quick_sort(rst);
        copy(rst.begin(), rst.end(), back_inserter(ret));
        }
    return ret;
    }

That was written to show the lack of need for garbage collection.  If
it were restricted to list and made a procedure, the whole thing would
be done using splice and the extra lists would be empty when destroyed.

> >  > o   Pattern matching.
> >  > o   List comprehensions.

> > How would you add these to C++?  Do you think there is any chance
> > of that kind of language change?  Would the library be anything more
> > than a joke?  If not why bother in csc++?

> I would add closures, garbage collection and type inference before
> seriously looking at these. All 3 of which have been discussed here
> before. I believe it is worth looking at other languages when considering
> whether C++ can or should be changed. I hope csc++ does not become too
> insular.

I wonder if it is worth the effort of the standard committee to
investigate the possibility of changing C++ in unnatural ways to amuse
the needs of a few.  C++ is what it is because of utility not elegance.

> It turns out that with recursive templates and partial specialisation C++
> has a full compile-time programming language. And this is a /functional/
> language, in that it does not allow destructive reassignment. And so it
> seems natural to me to look at other functional languages.

I wonder if this was planned or happened by accident.  would that be
extending/improving a designed feature or componding the error?

> > What is the purpose of writing a version of quick sort with a high
> > probability of failure concisely?

> I think it's generally true that large bodies of code written in languages
> with type inference, garbage collection and closures tends to be 1/3rd the
> size of the equivalent code in C++. The quicksort example is an
> illustration. The conciseness is a consequence of the power of the
> notation; it's not a special case for quicksort.

Convince me by showing me the code for introsort including the usual
med3 and insertion optimizations to quicksort.  I still see nothing but
cute, concise garbage.  You might also include timing results.

> > Maybe a discredit to the language if it can be read by other
> > than a practitioner.

> Is this humour?

Not at all.  All real programming languages with the exception of cobol
are write only.  That's why they have comments which real programmers
never use.  Smiley on the last part of the second sentence only.

> > In any case, why do you think C++ should change?

> I didn't say I thought C++ should be changed. Not in this thread, anyway.
> I do think that when considering possible directions of change, it is
> worth looking at the strengths and weaknesses of other languages.

It just might also be worth looking at the needs of practitioners.  Is
it possible that the committee is doing that in setting the goals of the
next standard as primarily library expansion with little or no core
language change?

John

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 13 Jan 2003 08:49:17 -0500
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:E96gpIBQOBH+Ewq+@robinton.demon.co.uk...
> > Every time you compare with a predefined constant, probably:
> >  min(my_long_variable, 0)
> > is a likely example.
>
> However, IIUC, the macro version has some unfortunate platform dependant
> behaviour:
>
> size_t val;
> int otherval;
> // code initialising these
>
> val = MAX(val, otherval);
>
> Now I know that good programmers would never write a comparison between
> an unsigned a signed integer type but most of us are fallible. The
> template version traps the problem and makes me deal with it, the macro
> just hides the problem.

It'll give whatever warning our compiler normally gives us on making a
signed/unsigned comparison.  The warning alerts us to the possible problem,
but doesn't break if the behaviour is what we want.

--
char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 13 Jan 03 15:08:57 GMT
Raw View
In article <3e209971.26922281@news.earthlink.net>, John Potter
<jpotter@falcon.lhup.edu> writes
>It just might also be worth looking at the needs of practitioners.  Is
>it possible that the committee is doing that in setting the goals of
the
>next standard as primarily library expansion with little or no core
>language change?

Actually, IIRC, one of the other primary goals is to make it easier to
learn and to teach. Adding support for functional programming would be
exactly the wrong thing to do for that objective.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nde_plume@ziplip.com (Nom De Plume)
Date: 14 Jan 2003 06:08:55 -0500
Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote in message news:<2TeMiFCBP$H+EwvK@robinton.demon.co.uk>...
> I am not sure what you mean. Generic programming had (according to the
> only person who could know, Bjarne Stroustrup) always been part of the
> long term design of C++.

You are right of course, as you know they were an appendix to
the ARM, and I have a first edition of "The C++ Programming
Language" which I believe mentions them obliquely.

However, what I was driving at more was the inclusion of generic
programming libraries as part of the standard library. As you
surely know, the STL was in many respects the test vehicle for
template ideas, and contributed greatly to their final design,
however, the STL per se was included as part of the standard
library in a fairly last minute fashion, if I remember correctly.

The consequence of that being, and the point I was making being,
that the community of C++ as a whole has really only started
using generic programming to a large extent since 1997, or later
when compilers really began supporting it.

It is a fairly radical departure from the previous methods
of coding using in C++, and consequently it takes a period of
time for people to get used to it, and begin to build enough
community knowledge to take the next step of improvement.

(Of course there is a large difference between people whose
job is "C++" and people whose job is programming. Scott Meyers
might be way ahead of the game, but there are plenty of
programmers who still can't quite grasp the difference between
functor and function.)

> That was scary but a new generation of programmers came
> along who started using this technology for meta-programming. There were
> many motives for that, one of them being the desire to shift some
> computational work to compile time and so make the resulting runtime
> executable more efficient.

Perhaps, but surely the principal goal was notiational
convenience and abstraction for reusability. It is true
that the "no side effect" principle of functional languages
offers certain other benefits such as partial evaluation
and generalized lazy evaluation, however, side-effects
are so thoroughly a part of C++ that there is no realistic
way to leverage these ideas to a great extent into C++.

Do you know of any research showing significant performance
enhancements through the use of the soft partial evaluation
that C++'s meta language is capable of?

> Those who are interested should note that the Conference mentioned in my
> signature includes several key people in the arena of generic and
> meta-programming. One of them (Simon Peyton Jones) was a key person in
> designing and developing template extensions in Haskell, two others
> (Andrei Alexandrescu and Ulrich Eisenecker) are leading authorities on
> geberic and meta-programming in C++. It is no accident that they are all
> together at the same (low cost)  event.

I'd love to come, but international travel is so expensive.

Getting back to C++, the point is that the extension I propose
would enhance the notational convenience for expressing
functonal ideas by raising functions closer to first class
objects.

Having given it some though (and trying it out in a few dozen
different contexts) it strikes me that a better notation would
be the following (eliminating the need for any new keywords,
and minimal additional syntax.)

struct s {int a; string b;};

void sort_em(vector<s>& data)
{
  sort(data.begin(), data.end(),
       inline bool(const s& lhs, const s& rhs)
       {
           return lhs.b < rhs.b;
       });
}

Or

// Note this defines a functor with the "inline" function
// which on construction takes a reference to total, based
// on the using declaration in the anonymous function.
int sum_em(const vector<int> data)
{
  int total = 0;
  for_each(data.begin(), data.end(),
           inline void(const int val)
           {
              using a; // Note no scope meaning enclosing function
              a += v;
           });
}

Finally, consider:

class A
{
 ...
private:
  void processValue(int v);
  void processList();
  std::list<int> dataList;
}

// By using "class inline" this function is
// declared as an anonymous private member
// function of the class of the enclosing
// member function. Giving access to processValue
void A::processList()
{
  // call processValue with every item on list
  for_each(dataList.begin(), dataList.end(),
           class inline void(const int v)
           {
               processValue(v);
           });
}
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "David Thompson" <david.thompson1@worldnet.att.net>
Date: 14 Jan 2003 17:02:49 -0500
Raw View
Hyman Rosen <hyrosen@mail.com> wrote :
> David Thompson wrote:
> > You don't need thunks (stack or otherwise), that's just
> > the gcc choice.  Displays or static links work also.
(to implement nested functions and pointers thereto)
>
> A pointer to a nested function has to have some way to carry
> around the pointer to the stack frame with which it is
> associated. As far as I can see, that leaves you with only
> two choices - either make the pointer "fat", or create a
> stack-based thunk.
....
A "fat" pointer, containing the address of the code
plus the address of the innermost stack frame, which
by static links can reach the outer stack frames; or
the addresses of all the relevant stack frames, probably
up to some modest limit after which it spills, which
is a "display".  Yes, these were the traditional ways of
implementing this in PL/1, and AFAIK Pascal and algol.

If such pointers take some extra space, so what?
So do the thunks.  Standard C, and C++, carefully
does not guarantee or require that pointers to functions
and to data be the same (not pointers to different types
of data either in many cases, but that's a different issue).
Although POSIX dlsym() effectively does.

The question is do you optimize for this case, or for
the unnested case?  gcc does the latter, because
nested functions are not traditional or Standard C and
are therefore presumably a good deal less common
in C code on average than they are/were in languages
that officially supported and even encouraged them.

--
- David.Thompson 1 now at worldnet.att.net
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "David B. Held" <dheld@codelogicconsulting.com>
Date: 14 Jan 2003 22:17:34 GMT
Raw View
"Nom De Plume" <nde_plume@ziplip.com> wrote in message
news:b59f4084.0301131346.c188f33@posting.google.com...
> [...]
> struct s {int a; string b;};
>
> void sort_em(vector<s>& data)
> {
>   sort(data.begin(), data.end(),
>        inline bool(const s& lhs, const s& rhs)
>        {
>            return lhs.b < rhs.b;
>        });
> }
> [...]
> // By using "class inline" this function is
> // declared as an anonymous private member
> // function of the class of the enclosing
> // member function. Giving access to processValue
> void A::processList()
> {
>   // call processValue with every item on list
>   for_each(dataList.begin(), dataList.end(),
>            class inline void(const int v)
>            {
>                processValue(v);
>            });
> }

While I don't know if this exact proposal is the best way to go,
I do think that anonymous functions would make the STL nicer
to use.  I tend to reuse parts of functors, but almost never whole
functors.  The result being that my code is littered with classes
whose sole purpose is to act as a functor in one calling location.
That's not the way I like to code, but it's just barely justified by
the benefit of using STL algorithms instead of hand-rolled loops.

I think being able to use local types would be a good start, since
then one could at least keep those functors where they belong.
But actually defining them inline, without the extra functor hassle
would definitely clean up the code (though it would probably
introduce a whole lot more complexity to C++ compilers, as if
they don't have enough already).  Boost.Lambda is nice, but,
unfortunately, doesn't work with all the compilers I use.  And
that kinda underscores the point that some language support
would be helpful.

There is an interesting similarity between your proposal and
class syntax.  In a way, if one were to view the function as a
class declaration, and the local variables as member data, then
the anonymous function begins to look like an inline member
function of this "class".

One thing I would argue for is the same syntax for member
and free functions.  If an anonymous function is located inside
a member function, I think it should automatically have access
to all data visible in the current scope, which should include
member variables/functions.  Firstly, because I don't see why
a distinction needs to be spelled out, and secondly, because
uniformity usually helps generic code.

Looking at this code:

> // Note this defines a functor with the "inline" function
> // which on construction takes a reference to total, based
> // on the using declaration in the anonymous function.
> int sum_em(const vector<int> data)
> {
>   int total = 0;
>   for_each(data.begin(), data.end(),
>            inline void(const int val)
>            {
>               using a; // Note no scope meaning enclosing function
>               a += v;
>            });
> }

I hope 'a' is supposed to be 'total', and that I'm not just too
dense to understand the proposal. ;)  I hope 'v' is supposed to be
'val', for the same reason.  Aren't top-level cv qualifiers for
function arguments ignored?

Anyway, going along with the function-as-class-analogue idea,
it would be even nicer if the variables did not have to be declared
explicitly.  We could just say that all variables visible in the
enclosing scope are visible inside the anonymous function, just
like all class members are visible inside a member function.  I'm
split on the usage of 'inline'.  On the one hand, it probably eases
parsing.  On the other, the parser should be able to identify it as
an anonymous function as soon as it sees <type>(<type>.
Anyway, using my rules, your example would look like this:

int sum_em(vector<int> const& data)
{
    int total = 0;
    for_each(
        data.begin(), data.end(), void(int val) { total += val; }
    );
}

That's looking pretty good, if you ask me.  Good enough to
make an FP coder drool. ;)  The interesting thing is, one
could enable this syntax without too much trouble using a
special (but not terribly complicated) preprocessor.  The
code above could be transformed into the following (almost)
conforming C++:

struct sum_em
{
    sum_em() : total(0) { }
    int operator()(vector<int> const& data)
    {
        for_each(data.begin(), data.end(), bind(_f, this));
    }
    void _f(int val) { total += val; }
    int total;
};

Of course, this assumes that Boost.Bind will become part of
the standard eventually.  Also, the preprocessor would have
to prevent users from trying to use sum_em as an object, for
those who know how it is implemented.  And you have to
worry about &sum_em, etc.  But those are just implementation
details. ;)  Ok, taking the address makes the preprocessor a
lot more complicated than I had hoped, but I think it illustrates
that we're not doing anything so complicated that a real
compiler couldn't implement it without too much trouble.

A major factor to consider is whether to allow anonymous
functions be defined anywhere an expression is allowed, or
only inside function definitions.  Consider:

namespace
{
    int N = int(void)
        { N = 0; for (int i = 0; i < 100; ++i) N += i; };
}

Should that be legal?  Also note that without the void param
list, the compiler wouldn't know that it's an anonymous
function until it sees the open brace.  I don't know if that
justifies the inline keyword or not.

On the one hand, I like orthogonality.  It's usually elegant.
And it often helps generic programming.  On the other hand,
allowing anonymous functions outside function definitions
might be a lot more complicated than inside functions.  I
don't know.  If that is the case, I would be willing to take
anonymous functions that are only allowed inside functions.

If I had the experience, I would try to hack gcc myself to
test the idea.  But alas, maybe someone more
knowledgeable and ambitious than I will try instead. ;)

Dave



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]






Author: Thant Tessman <thant@acm.org>
Date: 10 Jan 03 05:42:37 GMT
Raw View
Dave Harris wrote:

> jpotter@falcon.lhup.edu (John Potter) wrote (abridged):
>
>>>> Cute. Eight lines in C++ or one using sort<>.  Unreadable gibberish
>>>> to a procedural programmer.
>>
>>> It's unreadable gibberish to someone who doesn't know the notation.
>>
>> Isn't notation what this is all about?
>
>
> Yes. [...]

Is it? Pattern-matching and (to a more qualified degree) type inferrence
seem to be the only features on your list that are concerned explicitly
with notational convenience. (Their effect on notation is entirely
positive as far as I'm concerned.) The rest seem to facilitate
conciseness in their ability to refine the set of syntactically-valid
programs that are also semantically valid. I posit they do so in a way
that is *independent* of the syntax--or more broadly, in a way that is
independent of the language as notation.

For example, in C++ it is easy to imagine that many algorithms might be
more concisely expressed if it was meaningful for a function to return
the address of a local variable. There is nothing about C++ as
*notation* that hints about why this is a bad idea. It is only the
stack-based semantics attached to C++ function calls that make clear why
this is something the programmer shouldn't be doing.

Yeah, C++'s syntax is ugly, but its C heritage makes it very concise
when it comes to certain operations that match particularly well the
semantics of the underlying hardware. At the same time, it is C++'s
commitment to preserve these very semantics that make it difficult to
use C++ to concisely express abstractions as they wander farther away
from the hardware.

[...]

-thant


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Chris Newton <chrisnewton@no.junk.please.btinternet.com>
Date: 10 Jan 2003 06:19:29 -0500
Raw View
Tom Hyer wrote:
> brangdon@cix.co.uk (Dave Harris) wrote...
>
>>The code is:
>>    quicksort [] = []
>>
>>    quicksort (first:rest) =
>>          quicksort [ x | x <- rest, x <= first ]
>>          ++ [ first ]
>>          ++ quicksort [ x | x <- rest, x > first ]
>>
>
>
> Now can we see an example implementation of a _production-quality_
> quicksort?  It is clear that this code does not implement
> median-of-three or any such safeguards (thus its performance will be
> disastrous if the initial data are already sorted or nearly sorted).
>
> Cute examples of primitive algorithms (see also the merge in this
> thread, which is about 60% as long as the C++ equivalent but much less
> generic) are about the worst indicator of language quality I can think
> of.  A bad quicksort is shorter in Haskell; a good quicksort is
> probably longer.

I don't want to get too far into functional programming language
specifics here, as they're not topical on these newsgroups. If you don't
believe or understand anything I mention below, please take it up on a
functional programming newsgroup.

Using median-of-three for the pivot, or limiting the number of
iterations before switching to an alternative algorithm as something
like introsort would do, is trivial. I dispute your claim that a good
quicksort written using such techniques is "probably longer".

The median-of-three pivot just requires a let <env> in <expr> construct
and a function to calculate that median (written in-place or elsewhere).
That translates directly into calculating the median in a local variable
before doing the pattern match in a language like C++.

Guarding against excessive worst case behaviour in quicksort simply
requires an extra parameter to the recursion, just as it would in any
other implementation.

In neither case does this defeat the point about the pattern matching
technique expressing certain behaviour concisely and powerfully. Please
don't dismiss this idea too fast. The quicksort example barely scratches
the surface of what it can do, since it just hides a check on whether a
list is empty. Combined with a decent discriminated union construct, it
can do awesome things. If we're going to have enum and switch, why not
consider whether extending them could provide the same advantages to C++
programmers that users of languages with pattern matching currently enjoy?

Regards,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Walter" <walternospamm@digitalmars.nospaam.com>
Date: 10 Jan 2003 06:28:36 -0500
Raw View
"Ken Alverson" <Ken@Alverson.net> wrote in message
news:aufiri$qgu$1@eeyore.INS.cwru.edu...
> "Matthew Watson" <Matthew_Watson@hotmail.com> wrote in message
> news:8HAO9.2389$hG1.17807474@news-text.cableinet.net...
> > "Neil Zanella" <nzanella@cs.mun.ca> wrote in message
> > news:b68d2f19.0212222026.4f6e8b0a@posting.google.com...
> >
> > >What high level constructs? Show me one other language that has
> > templates!
> >
> > Eiffel has things that can be used very like templates.
>
> As does Ada.  Though both are genericity constructs and can't do some of
> the wackier meta-programming tricks people have managed to come up with
> using templates.

The D Programming Language, www.digitalmars.com/d/, has sophisticated
templates as well, including things like partial ordering and partial
specialization, all with a much easier to use syntax than C++.

-Walter
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: stephan beal <stephan@wanderinghorse.net>
Date: 11 Jan 03 03:10:34 GMT
Raw View
Walter wrote:
> "Ken Alverson" <Ken@Alverson.net> wrote in message
> news:aufiri$qgu$1@eeyore.INS.cwru.edu...
>> "Matthew Watson" <Matthew_Watson@hotmail.com> wrote in message
>> news:8HAO9.2389$hG1.17807474@news-text.cableinet.net...
>> > "Neil Zanella" <nzanella@cs.mun.ca> wrote in message
>> > news:b68d2f19.0212222026.4f6e8b0a@posting.google.com...
>> >
>> > >What high level constructs? Show me one other language that has
>> > templates!
>> >
>> > Eiffel has things that can be used very like templates.
>>
>> As does Ada.  Though both are genericity constructs and can't do some
of
>> the wackier meta-programming tricks people have managed to come up
with
>> using templates.
>
> The D Programming Language, www.digitalmars.com/d/, has sophisticated
> templates as well, including things like partial ordering and partial
> specialization, all with a much easier to use syntax than C
]

Java will also get templates soon:
http://developer.java.sun.com/developer/technicalArticles/releases/gener
ics/

But without the ability to typedef i would imagine that they will be
effectively unusuable for nested template definitions (too unreadable
and
unmaintainable, IMO). For example, nobody is going to want to write (or
read) this all the time:

Foo<Bar<FooBar>> myobj;

when they could instead have this:
FooBarType myobj;

--
----- stephan beal
Registered Linux User #71917 http://counter.li.org
I speak for myself, not my employer. Contents may
be hot. Slippery when wet. Reading disclaimers makes
you go blind. Writing them is worse. You have been Warned.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nde_plume@ziplip.com (Nom De Plume)
Date: 10 Jan 2003 23:07:56 -0500
Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote in message news:<An3B$PBjLrG+EwjZ@robinton.demon.co.uk>...
> C++, IMHO, supports meta-programming about as well as C
> supports OOP.

That is a pretty good comparison. However, just as the
addition of classes greatly improved our ability to
write OOP, so I think a few very simple facilities added
to C++ would radically change our ability to write
nice, easy to read generic/functional programs. (Note,
the Haskell guys would reject the idea that any language
which can produce side effects should be considered
functional, including dismissing LISP and Standard ML.
However, I think what we are seeking here is the notational
convenience of functional languages rather than the
tractability of the program for global analysis that
comes from the lack of side effects in Haskell.)

I imagine the guys who are doing great work like writing
the lambda library or Loki would have some great ideas
to improve the functional qualities of C++, but let
me, in my shortsighted way, offer my ideas.

Here is one idea that I think would radically broaden the
usefulness, or at least the usability of the STL
(or to be more precise the containers and algorithms
in the Standard Library.)

Anonymous Functions:

If I want to write a function that sorts a vector of
a particular structure, I might write:

using namespace std;

struct s {int a; string b;}

bool s_less(const s& lhs, const s& rhs)
{
  return lhs.b < rhs.b;
}

void sort_em(vector<s>& data)
{
  sort(data.begin(), data.end(), s_less);
}

When I eventually get to the sort line, I have to pass in
a function I have predefined outside of sort_em. This
requires extraneous functions all over the place. Anyone
who has used the STL will recognize this problem, having
to define lots of little functions and functors, and the
general confusion this can produce. There is a theory that
as the set of these functions/functors increases, duplication
will kick in reducing the number of new ones required.
However, I have been using the STL for a while now and
outside of the template functors included in the STL itself
I have not really seem much of that at all.

Some would argue that we put the less function as a member
of s and use some combination of bind and mem_fn to pass
into sort, however, that produces code that is extremely
difficult to read.

My alternative would be to allow the function "less_s"
to be defined in place. Viz:

void sort_em(vector<s>& data)
{
  sort(data.begin(), data.end(),
       function bool(const s& lhs, const s& rhs)
       {
          return lhs.b < rhs.b;
       });
}

I have invented a keyword "function" which means treat
the following function definition as if it were defined
just before the start of the containing function, do
not give it a name, and then replace the function statement
with a pointer to that function. This seems to me to be
a fairly straightforward extension to a compiler.

Now, a similar syntax might be used for a functor, however
many of the benefits that accrue to functors could be
more gained by one slight addition to the above syntax.

Lets say I want to write a function to sum the integers
in a vector (obviously there are easier ways to do this
but by way of illustration)

int sum_em(const vector<int>& data)
{
  int total =0;
  for_each(data.begin(), data.end(),
           function void(const int datum)
           {
              access total;
              total += datum;
           });
  return total;
}

Here I have introduced another speculative keyword: "access"
What it means is make a reference to the "total" variable
available in the anonymous function. This is achieved by the
compiler by adding another anonymous parameter to the
anonymous function and currying it with the local variable,
and passing this curried function into for_each. (Which sounds
rather more complex that it actually is.)

I believe these two additions, or something like them would
greatly enhance the usefulness of the STL, and, perhaps more
importantly, greatly clarify the current uses of these
functions.

Generic programming was relatively new in the C++ standard,
and it kind of got dropped in at the last minute. Consequently
it seems to me that this period before the revision is exactly
the time to be looking at how generic programming is being
used, and how to enhance the language to better support it.

Thoughts?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 09 Jan 03 12:19:07 GMT
Raw View
In article <avfs1j$nep$1@knossos.btinternet.com>, Chris Newton
<chrisnewton@no.junk.please.btinternet.com> writes
> "KIM Seungbeom" <musiphil@bawi.org> wrote...
>> Anyway, do we really need min/max of two values of
>> different types?
>>
>> How often do we have to write min(short_value, long_value)?
>
> Every time you compare with a predefined constant, probably:
>  min(my_long_variable, 0)
> is a likely example.

However, IIUC, the macro version has some unfortunate platform dependant
behaviour:

size_t val;
int otherval;
// code initialising these

val = MAX(val, otherval);

Now I know that good programmers would never write a comparison between
an unsigned a signed integer type but most of us are fallible. The
template version traps the problem and makes me deal with it, the macro
just hides the problem.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: brangdon@cix.co.uk (Dave Harris)
Date: 9 Jan 2003 12:36:44 -0500
Raw View
jpotter@falcon.lhup.edu (John Potter) wrote (abridged):
>  > > Cute. Eight lines in C++ or one using sort<>.  Unreadable gibberish
>  > > to a procedural programmer.
>
>  > It's unreadable gibberish to someone who doesn't know the notation.
>
> Isn't notation what this is all about?

Yes. But I'm not sure what your point was. You seemed to be saying the
notation is intrinsically bad. If not that, then what?


>  > o   Genericity.
>
> No need to say template<>.
>
>  > o   Recursion.
>
> Procedural anyway.

Sure. Haskell doesn't have a monopoly on powerful ideas.


>  > o   Type inference.
>
> More slop than template functions.

Actually I think much of the cleanness of the code comes from not having
the clutter of type declarations.


>  > o   Garbage collection.
>
> Not important here.

Well, it is, because each call to quicksort makes 4 new list objects. The
memory for these needs to be reclaimed somehow.


>  > o   Pattern matching.
>  > o   List comprehensions.
>
> How would you add these to C++?  Do you think there is any chance
> of that kind of language change?  Would the library be anything more
> than a joke?  If not why bother in csc++?

I would add closures, garbage collection and type inference before
seriously looking at these. All 3 of which have been discussed here
before. I believe it is worth looking at other languages when considering
whether C++ can or should be changed. I hope csc++ does not become too
insular.

It turns out that with recursive templates and partial specialisation C++
has a full compile-time programming language. And this is a /functional/
language, in that it does not allow destructive reassignment. And so it
seems natural to me to look at other functional languages.


> I think the average C++ programmer will find this unreadable also.

It is certainly a less clear expression of the algorithm.


> What is the purpose of writing a version of quick sort with a high
> probability of failure concisely?

I think it's generally true that large bodies of code written in languages
with type inference, garbage collection and closures tends to be 1/3rd the
size of the equivalent code in C++. The quicksort example is an
illustration. The conciseness is a consequence of the power of the
notation; it's not a special case for quicksort.


> Maybe a discredit to the language if it can be read by other
> than a practitioner.

Is this humour?


> I am unsure of the purpose of your post.

I wanted to show the Haskell code for those who can't or won't follow
links. I wanted to explore how it managed to be both simple and powerful.
I wanted to defend procedural programmers from your apparent slur that
they are incapable of understanding Haskell.


> In any case, why do you think C++ should change?

I didn't say I thought C++ should be changed. Not in this thread, anyway.
I do think that when considering possible directions of change, it is
worth looking at the strengths and weaknesses of other languages.


  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 08 Jan 03 04:00:21 GMT
Raw View
In article <av9ldv$7km$1@knossos.btinternet.com>, Chris Newton
<chrisnewton@no.junk.please.btinternet.com> writes
>C++ is a multi-paradigm language. It supports procedural and OO
designs.
>It supports and encourages a style of generic programming.

Indeed it does, but what we are currently seeing from some experts is
its use for meta-programming. C++, IMHO, supports meta-programming about

as well as C supports OOP. Yes, with care and understanding you can do
OOP in C because of its separate compilation model coupled with files
scope statics, but the language has no real support for it. You can do
meta-programming in C++ but the language has no real support for it.

It might be interesting to see a world class language designer create
C++ with meta-programming :-)


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: thomas.hyer@ubsw.com (Tom Hyer)
Date: 08 Jan 03 04:00:53 GMT
Raw View
brangdon@cix.co.uk (Dave Harris) wrote in message
news:<memo.20030105120014.48605A@brangdon.madasafish.com>...
>
> The code is:
>     quicksort [] = []
>
>     quicksort (first:rest) =
>           quicksort [ x | x <- rest, x <= first ]
>           ++ [ first ]
>           ++ quicksort [ x | x <- rest, x > first ]
>

Now can we see an example implementation of a _production-quality_
quicksort?  It is clear that this code does not implement
median-of-three or any such safeguards (thus its performance will be
disastrous if the initial data are already sorted or nearly sorted).

Cute examples of primitive algorithms (see also the merge in this
thread, which is about 60% as long as the C++ equivalent but much less
generic) are about the worst indicator of language quality I can think
of.  A bad quicksort is shorter in Haskell; a good quicksort is
probably longer.

Also, it is worth noting that the code as written makes twice as many
comparisons as an imperative version would (because the "x <= first"
and "x > first" subsequences are computed independently).  I don't
think there's a workaround.

-- Tom Hyer

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 8 Jan 2003 05:40:11 -0500
Raw View
"KIM Seungbeom" <musiphil@bawi.org> wrote...
> Anyway, do we really need min/max of two values of
> different types?
>
> How often do we have to write min(short_value, long_value)?

Every time you compare with a predefined constant, probably:
  min(my_long_variable, 0)
is a likely example.

Granted, you can always get around that specific case by writing 0L
explicitly. In general, though, if you're working with an interface
where named constants are defined for you, it may not be possible to do
this without explicitly casting or using an explicit template
specialisation, both of which rather defeat the point.

It may sound as though you should be wary of such mixed-type comparisons
anyway, and perhaps that is so. Neverthless, there are quite plausible
reasons for it to be appropriate: some libraries use "int for
everything" whereas others will use short and unsigned modifiers
liberally, for example.

Cheers,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: agriff@tin.it (Andrea Griffini)
Date: 8 Jan 2003 13:16:47 -0500
Raw View
On 08 Jan 03 04:00:21 GMT, Francis Glassborow
<francis.glassborow@ntlworld.com> wrote:

>C++, IMHO, supports meta-programming about
>as well as C supports OOP.

I think the situation is worse. In C you at
least have all the needed basic tools to do OOP;
in C++ you miss a few important things like any
method to enumerate the attributes of a class
and there's nothing that can come even near to
support such a basic feature.

Looking how template gurus can misuse inheritance to
be able to do aggregation, or template specialization
to do simple selections, or recursion to do simple
loops or lists sometimes I've the impression to be
looking to a soccer player that goes in the playfield
while having the left foot tied to the right hand.
It's really impressive to see how it can even manage
to kick the ball... but if you need to play, and if
you get past the circus effect, I think it's quite
natural remembering that no rule in soccer requires
players to penalize themselves that way.

A few ideas are very nice and englightnening, but
often the implementation shows with what a primitive
tool that line of mind is forced to work with.

Sometimes I caught myself into wondering why instead
of pretending the preprocessor didn't exist the idea
of having a full serious language with all bells and
whistles to be used at compile time wasn't used instead.

Andrea
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Sun, 5 Jan 2003 12:47:28 +0000 (UTC)
Raw View
nagle@animats.com (John Nagle) writes:

>     LISP had far too much compile-time preprocessing.
> Look up the "MIT loop macro".

For reference,
http://www-2.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/lisp/code/iter/loop/mit/mit_loop.cl
Horrifying, indeed!

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kcline17@hotmail.com (Kevin Cline)
Date: 5 Jan 2003 10:42:41 -0500
Raw View
Hyman Rosen <hyrosen@mail.com> wrote in message news:<1041280069.998496@master.nyc.kbcfp.com>...
> James Kanze wrote:
> > Some sort of partial closure could (and IMHO should) be
> > considered, however.  I'd imagine something along the following lines:
>
> What's wrong with just adopting true nested functions?
> If the implementation is able to create executable thunks
> on the stack, pointers to nested functions are the same as
> normal pointers to functions. Pascal and Ada have always
> had these, so it's not like this is a radical concept.

It depends on your definition of 'true'.

C has always had pointers to functions.  Pascal and Ada-83 don't.
Ada-95 does have access-to-subprogram types, but they are restricted to
only refer to top-level subprograms.

C++ could have nested functions with the same restrictions, but
I don't think it would be of much use.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 5 Jan 2003 10:43:00 -0500
Raw View
"Nikolaos D. Bougalis" <nikb@webmaster.com> wrote in message
news:6uJQ9.24190$oy5.1632002@news2.west.cox.net...
> "Andrei Alexandrescu" <andrewalex@hotmail.com> wrote in message
> news:auqan3$9ifom$1@ID-14036.news.dfncis.de...
> > "Nikolaos D. Bougalis" <nikb@webmaster.com> wrote in message
> > news:rtoP9.108173$vb3.3961341@news2.west.cox.net...
> > > > Hugely better except it's not actually as good as this macro in
> C++:
> > > > #define max(A, B) ((A) > (B) ? (A) : (B))
> > >
> > >     Unfounded assertion.
> >
> > Getting the virtues of the macro and getting rid of its shortcomings
> is
> not
> > easy.
> >
> > http://www.moderncppdesign.com/publications/cuj-04-2001.html
>
>     Maybe so - but in my opinion, the shortcomings outweight the
> virtues. If
> I want to compare apples and oranges, I'll write a function to do that.
> I
> won't expect to reach into my toolkit and grab one of those "universal
> adaptors" and plug an orange on one side and an apple on the other.

How would this apply to the article? The comparison works iff there is a
meaningful comparison applicable.

Andrei
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 5 Jan 2003 10:43:18 -0500
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:chwmO2p2Z3E+Ewwu@robinton.demon.co.uk...
> Not if correctly written:
>
> max<int>(a, b);
Telling the compiler which conversion to do when the macro form performs the
correct conversion automatically doesn't really strike me as being "correct".
It strikes me as being "a workaround for the inadequacies of the function
version".

--
char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "David Thompson" <david.thompson1@worldnet.att.net>
Date: 5 Jan 2003 11:26:46 -0500
Raw View
Hyman Rosen <hyrosen@mail.com> wrote :
....
> What's wrong with just adopting true nested functions?
> If the implementation is able to create executable thunks
> on the stack, pointers to nested functions are the same as
> normal pointers to functions. Pascal and Ada have always
> had these, so it's not like this is a radical concept.
>
You don't need thunks (stack or otherwise), that's just
the gcc choice.  Displays or static links work also.

And to be clear, Pascal and (IIRC) algol have nested routines
which can be passed as arguments (and used correctly),
but not a distinct pointer-to type.  PL/1 has ENTRY variables
which are semantically pointer-to-PROC although not called such.
Ada does have a true pointer (access) type, but with restrictions
that effectively prevent upward closures.

--
- David.Thompson 1 now at worldnet.att.net
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 6 Jan 2003 06:29:34 -0500
Raw View
"Stephen Toledo-Brown" <nomail@hursley.ibm.com> wrote in message
news:3E15CD36.FF970B06@hursley.ibm.com...
> As Francis already pointed out, fixing the call is trivial.
> Use either min<short>(a, b) or min<long>(a, b) according to the
> intention/context.
I don't agree that that constitutes a fix.  The compiler has rules for
converting types automagically.  I want it to actually *use them*.

Andrei's complicated template will more or less perform the conversions
appropriately, but it's no quick and easy three line function template.

--
Now Playing:  Collusion - Impetuous (Video Edit)


char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: 6 Jan 2003 06:30:15 -0500
Raw View
jpotter@falcon.lhup.edu (John Potter) wrote (abridged):
> > Haven't got a tested merge sort handy, but try the Haskell example of
> > quicksort in one of Andrei Alexandrescu's recent CUJ articles:
> >   http://www.cuj.com/experts/2012/alexandr.htm?topic=experts
>
> Cute. Eight lines in C++ or one using sort<>.  Unreadable gibberish
> to a procedural programmer.

It's unreadable gibberish to someone who doesn't know the notation.
Whether they are procedural programmers or not is all but irrelevant.

The code is:
    quicksort [] = []

    quicksort (first:rest) =
          quicksort [ x | x <- rest, x <= first ]
          ++ [ first ]
          ++ quicksort [ x | x <- rest, x > first ]

It's short because it uses a handful of powerful features, including:

o   Genericity.
o   Recursion.
o   Type inference.
o   Garbage collection.
o   Pattern matching.
o   List comprehensions.

If you don't know what a list comprehension is, let alone what its Haskell
syntax looks like, then of course you'll have trouble following the code.

(Briefly, "[ x | x <- rest, x <= first ]" means a list of x such that x is
a member of the list "rest" and x satisfies the condition "x <= first".)

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Ko.vanderSloot@uvt.nl (Ko van der Sloot)
Date: Mon, 6 Jan 2003 18:23:16 +0000 (UTC)
Raw View
===================================== MODERATOR'S COMMENT:

This is beginning to drift away from the C++ Standard.


===================================== END OF MODERATOR'S COMMENT
In article <3E170E23.9060407@animats.com>,
 nagle@animats.com (John Nagle) writes:
|> Dave Harris wrote:
...
|>     (LISP could have been the language of the Internet,
|> especially since most Internet-transmitted data
|> structures are trees.  Yahoo Store was (still is?)
|> a LISP application.  Understanding why that didn't
|> happen is a good exercise for language designers.)

Probably this is caused by the fact that LISP is NOT a Microsoft
trademark?

Ko

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Nikolaos D. Bougalis" <nikb@webmaster.com>
Date: 07 Jan 03 08:19:50 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message
news:av0g1k$n6$1@helle.btinternet.com...

> >     Let's how does your macro handle this case of mixed types you like
> > so
> > much...
> >
> > #include <iostream>
> >
> > #define max(a, b) ((a) > (b)) ? a : b
> That is not my macro.  Stop misrepresenting my position.  This shows
nothing
> more than your ability to write a faulty macro.

    Sorry, I forgot to add the extra parentheses... that would of course
mess up the whole macro...

#define max(a, b) ((a) > (b) ? (a) : (b))


> > int main(int argc, char **argv)
> > {
> >     int i = 7378;
> >     double d = 0.7378;
> >     max(i, d) = 0.7319;
> >     std::cout << "i=" << i << std::endl;
> >     std::cout << "d=" << d << std::endl;
> >     return 0;
> > }
> >
> >     Here's how:
> >
> > i=7378
> > d=0.7378
> No kidding.  What the hell does that prove?  you just evaluated:
>
> i > d ? i : d = 0.7319;
>
> the "d = 0.7319" is the false case of the conditional.  I didn't put in
those
> extra brackets for fun, you know.  I put them in because it needs it to
force
> the evaluation to occur in a certain way.

    Thanks for catching that... I did not realize I missed the extra set of
parenthesis. I guess the moral of this story is don't use function macros
because they're error-prone *grin* (and NOT that it's not a good thing to
write code after being up for more than 48 hours!)

> If you wrote the macro properly you would rightly get a compile-time
error.
> Because of the temporary created by the conversion, the thing isn't an
lvalue,
> so it fails to compile.  As it should.
>
> >     The macro only *appears* to work with different types. In reality,
> > it's
> > undefined behavior, and it's asking for trouble. Look at the example
> > again... Apples and oranges.
> The macro works fine with different types.
> The macro uses defined conversions.
> The example you've provided is completely bogus because you're using a
faulty
> macro -- not the macro I provided.

    I just tested with the macro you provided, and indeed I get a compiler
error. I stand corrected.

    -n


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Hyman Rosen <hyrosen@mail.com>
Date: 07 Jan 03 08:21:40 GMT
Raw View
David Thompson wrote:
> You don't need thunks (stack or otherwise), that's just
> the gcc choice.  Displays or static links work also.

A pointer to a nested function has to have some way to carry
around the pointer to the stack frame with which it is
associated. As far as I can see, that leaves you with only
two choices - either make the pointer "fat", or create a
stack-based thunk.

int g(int n, std::vector<int (*)()> &v)
{
     int f() { return n; }
     if (n > 0)
     {
         v.push_back(&f);
         g(n - 1, v);
     }
     else
     {
         int s = 0;
         for (i = 0; i < v.size(); ++i)
             s += v[i]();
         v.clear();
         return s;
     }
}


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: KIM Seungbeom <musiphil@bawi.org>
Date: 07 Jan 03 08:22:21 GMT
Raw View
DrPizza wrote:
>
> "Stephen Toledo-Brown" <nomail@hursley.ibm.com> wrote in message
> news:3E15CD36.FF970B06@hursley.ibm.com...
> > As Francis already pointed out, fixing the call is trivial.
> > Use either min<short>(a, b) or min<long>(a, b) according to the
> > intention/context.
> I don't agree that that constitutes a fix.  The compiler has rules for
> converting types automagically.  I want it to actually *use them*.
>
> Andrei's complicated template will more or less perform the conversions
> appropriately, but it's no quick and easy three line function template.

Anyway, do we really need min/max of two values of different types?
How often do we have to write min(short_value, long_value)?

--
KIM Seungbeom <musiphil@bawi.org>

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Hyman Rosen <hyrosen@mail.com>
Date: 07 Jan 03 08:22:29 GMT
Raw View
Kevin Cline wrote:
> Ada-95 does have access-to-subprogram types, but they are restricted to
> only refer to top-level subprograms.

This is not correct. They may point to any subprogram.
You may not place one in a pointer whose type has a
wider scope than the subprogram, though. That is, Ada
protects you from being able to call a pointer-to-function
with a function that has gone out of scope.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 7 Jan 2003 05:39:27 -0500
Raw View
"John Potter" <jpotter@falcon.lhup.edu> wrote...
> > Haven't got a tested merge sort handy, but try the Haskell
> > example of quicksort in one of Andrei Alexandrescu's recent
> > CUJ articles:
> >   http://www.cuj.com/experts/2012/alexandr.htm?topic=experts
>
> Cute. Eight lines in C++ or one using sort<>.  Unreadable
> gibberish to a procedural programmer.

So were templates, exceptions, classes and even structured programming,
when they first came along. Some would argue that templates still are
today.

> > Is there some problem with the idea that C++ could learn
> > some tricks from other languages that only help in lots
> > of cases, and not in all of them?
>
> Yes.  C++ is a procedural language.

C++ is a multi-paradigm language. It supports procedural and OO designs.
It supports and encourages a style of generic programming. Much of the
leading edge template research people discuss around here is inspired,
in one way or another, by other languages. Hell, much of the idea of
generic programming as seen in C++ is ripped straight out of the
functional world.

One of the greatest strengths of C++, IMHO, is precisely this ability to
support different programming styles depending on what most
appropriately meets the current requirements.

> Your comments seem to be nothing more than the functional
> rhetoric which has forcast the death of procedural languages
> for ages now.

I specifically gave examples of features or ideas from a diverse
spectrum of languages, including some functional, some scripting, and
some other OO ones. I was hoping to avoid the perception that I thought
C++ should metamorphose into some other specific language. If that were
the case, I would (and do) program in that other language as well.

The power in the sorting example comes from pattern matching. This
concept already exists in C++ in many places, from overloaded functions,
to template specialisation, to the humble switch statement and
enumerations.

The only other feature I've talked about that's common in functional
languages is closures. Suggestions for including a language extension
along these lines have featured in the serious C++ newsgroups for as
long as I've followed them, and I'm obviously not alone in thinking
they'd be very useful and a good solution to a common problem in today's
C++.

Adding these features would no more make C++ a functional programming
language than adding static methods to Java made it a procedural
programming language. I'm not advocating adding native higher level
functions, referential transparency, currying and lazy evaluation to
C++. I'm suggesting that certain carefully chosen features might fit in
well with what's currently there and the guidelines provided by Bjarne
and others for the development of the language.

Regards,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: 07 Jan 03 13:13:57 GMT
Raw View
On 6 Jan 2003 06:30:15 -0500, brangdon@cix.co.uk (Dave Harris) wrote:

 > jpotter@falcon.lhup.edu (John Potter) wrote (abridged):
 > > > Haven't got a tested merge sort handy, but try the Haskell example of
 > > > quicksort in one of Andrei Alexandrescu's recent CUJ articles:
 > > >   http://www.cuj.com/experts/2012/alexandr.htm?topic=experts

 > > Cute. Eight lines in C++ or one using sort<>.  Unreadable gibberish
 > > to a procedural programmer.

 > It's unreadable gibberish to someone who doesn't know the notation.

Isn't notation what this is all about?

 > Whether they are procedural programmers or not is all but irrelevant.

I don't think so.  The abstractions are unrelated.

 > The code is:
 >     quicksort [] = []
 >     quicksort (first:rest) =
 >           quicksort [ x | x <- rest, x <= first ]
 >           ++ [ first ]
 >           ++ quicksort [ x | x <- rest, x > first ]

 > It's short because it uses a handful of powerful features, including:

 > o   Genericity.

No need to say template<>.

 > o   Recursion.

Procedural anyway.

 > o   Type inference.

More slop than template functions.

 > o   Garbage collection.

Not important here.

 > o   Pattern matching.
 > o   List comprehensions.

How would you add these to C++?  Do you think there is any chance
of that kind of language change?  Would the library be anything more
than a joke?  If not why bother in csc++?

template <class Biter> void quick_sort (Biter f, Biter p)             {
    typedef iterator_traits<Biter>::value_type V;
    if (f != p)                                                      {
       Biter m(partition(succ(f), p, bind2nd(less_equal<V>(), *f)));
       quick_sort(m--, p);
       quick_sort(iterSwap(f, m), m);                                } }

I think the average C++ programmer will find this unreadable also.  What
is the purpose of writing a version of quick sort with a high
probability of failure concisely?  Note my use of nested function calls.
It seems that this is not acceptable to the average C++ programmer.

Unfortunately all of this stuff is always, "Look how concisely I can
write a bad version of an algorithm which is well written in the C++
standard library."  I guess nobody uses these features to write new
things.

 > If you don't know what a list comprehension is, let alone what its Haskell
 > syntax looks like, then of course you'll have trouble following the code.

I had no problem following the code.  I started with no knowledge of the
syntax or concept.  My conclusion was "cute", because it does what it
claims.  Maybe a discredit to the language if it can be read by other
than a practitioner.

 > (Briefly, "[ x | x <- rest, x <= first ]" means a list of x such that x is
 > a member of the list "rest" and x satisfies the condition "x <= first".)

Set notation is clear even when the symbols are distorted.  Does it mean
"list" where the order is preserved or just set?  If it used a third
list for equality, it would be a stable quick sort that fails easily.

I am unsure of the purpose of your post.  Is it an example of the usual
attempt to solve all of the worlds problems by educating all of the dumb
procedural programmers who are writing working code to the joys of
working at a higher level?  There is a point at which the abstraction
becomes incomprensible to anyone.  The higher the abstraction, the
smaller the set of users.

In any case, why do you think C++ should change?

John

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Noel Yap <Noel.Yap@morganstanley.com>
Date: 04 Jan 03 14:36:13 GMT
Raw View
Francis Glassborow wrote:
> One of the penalties paid by being a very widely used language is that
> there is a great deal of source code that has to be cared for. The more
> a language is used the more legacy code there is to break.

IMHO, such a thing should be handled by compiler switches (eg
--standard=1995).

MTC,
Noel


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: kanze@gabi-soft.de (James Kanze)
Date: 04 Jan 03 14:35:43 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message
news:<auqh6n$3ts$1@venus.btinternet.com>...
> "James Kanze" <kanze@gabi-soft.de> wrote in message
> news:d6651fb6.0212300403.2a3ae883@posting.google.com...
> > "DrPizza" <drpizza@anti-flash.co.uk> wrote in message
> > > Hugely better except it's not actually as good as this macro in
C++:
> > > #define max(A, B) ((A) > (B) ? (A) : (B))

> > You mean in cases like max( *pi ++, 0 ) ?
> Except we all know about that problem and so make sure to avoid it.

Except that we all know from actual experience that people forget, or
never knew to begin with, and that it is a very real problem.

> > I thought that this was the classical example of why macros didn't
> > work, and inline functions were needed.

> Except the inline function doesn't work either.

How doesn't it work?

> > > though I think one may need the slightly uglier
> > > #define max(A, B) *((A) > (B) ? &(A) : &(B))
> > > (or perhaps one only needs that in C?)
> > So that it won't even work with max( i, 0 )?  Offhand, I can't
> > remember ever using max or min where one of the two arguments wasn't
> > a constant; you want to forbid all of my uses?

> No, I checked, the first macro works fine in C++.  So it doesn't
> matter.

The first macro works with constants, but cannot be used as an lvalue.
The second can be used as an lvalue, but won't work with constants.  And
you cannot overload macros, like you can functions, so that the compiler
will automatically choose the appropriate one.
> > His function is always an l-value.  (I'm not convinced that this is
> > a good thing, however.)

> Sorry; it isn't a /modifiable/ l-value.  And it's occsaionally useful
> to be such.

> > His function can be overloaded on const to allow this.  Not that I
> > think it a good idea, but it is certainly possible.

> Good idea or no, it's a capability the macro has that his function
> doesn't.

No.  It's a capability that his function has, but that a macro doesn't.
You cannot overload a macro.  You must decide once and for all whether
you want a modifiable lvalue, or whether you want to support using
constants as arguments.  You can easily overload his function on const,
and have the best of both worlds (supposing that is what you want).

> > His function allows using a constant as an argument, which is
> > probably the most frequent use.

> As does the macro.

Not the one which can act as an lvalue.

> > His function only evaluates each argument once, which avoids
> > surprises with things like max( *pi++, 10 ).

> Except that the double evaluation isn't that surprising, because we
> know how macros work.

Except that it is a proven and known problem in C and C++, and has
caused many, many problems in the past.

You can't sweep it under the rug like that.

> > The template solution has problems with mixed types.  The macro
> > solution may, too, with the difference that the template solution
> > won't compile, whereas the macro solution may just give the wrong
> > results (e.g. if one argument is a float, and the other a long).

> Whether that's wrong or not is a matter of opinion.  I don't agree
> that it is.  I certainly don't think that the macro's behaviour in
> this situation is wrong:

> int a;
> short int b;
> ...
> max(a, b);

> But the template will fail.

In this case, it probably isn't wrong.  But who uses short int now
adays?

In cases where you pass it a float and an int, the template version will
not compile, whereas the macro version will silently compile to
something which occasionally gives the wrong results.

> > Generally speaking, implicit conversions are a bad thing, although C
> > (and thus C++) has so many already, banning them in one special case
> > doesn't seem to fit into the language very well.

> Implicit conversions may be bad, but promoting to a larger type isn't
> particularly bad, and the template won't even do that.

No, it won't.  The inability to compare an int with a long (or worse
yet, a size_t) is probably its greatest weakness.  On the other hand, it
will not quietly give wrong results when comparing a float with an int.

If you don't care about having wrong results, the macro wins on this one
point.  (It still looses on all of the others, of course.)  If you
prefer compiler error messages to wrong results, the template wins.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: brangdon@cix.co.uk (Dave Harris)
Date: 04 Jan 03 14:37:39 GMT
Raw View
allan_w@my-dejanews.com (Allan W) wrote (abridged):
> C++ was the first language to differentiate between those things
> that can be done at compile time, and those things that must
> wait until runtime.

I'm not sure this is true if we include the Lisp family of languages. Lisp
macros rewrite the parse tree at compile time. They can fill a similar
role to C++ templates (and have other benefits, such as a regular approach
to lazy evaluation.)

I am not convinced C++ has followed the right route here.


> When Bjarne was inventing C++, there were other languages with
> classes and runtime polymorphism... but they all did some type
> of runtime interpretation, and as a result they were extremely
> slow. At the time, if you had asked an expert how to get the
> runtime polymorphism to occur at compile time, he probably
> would have told you that this was a contradiction in terms.
> (He'd have been right, too!)

Or he might have told you about Deutsch and Schiffman's work on Smalltalk
in 1984. This including inline caching of the message dispatch, and "just
in time" compiling.


> Note that if Stroustrup or AT&T had patented the idea of virtual tables
> (as opposed to merely copyrighting the compiler), Java might not exist.
> If someone can get a patent on using XOR to draw a line, then surely
> Stroustrup could have patented the virtual table -- which (unlike XOR)
> did NOT have prior art, and was NOT obvious.
>
> (AFAIK, the closest equivalent to virtual tables was a "jump table"
> used to implement such things as select/case statements.)

When I first started work my employers were already using jump tables for
polymorphism exactly as virtual function tables. They were initialised by
hand, and pointers to them were stored in class-like data structures, and
some tables were longer than others so some notion of subclassing was
present, too. This was in BCPL, around 1983. I think Unix device drivers
used them too.

C++ provided direct support, which was welcome. It generated the indexes
automatically, within a single-inheritance hierarchy. It's hard to say now
whether it was obvious a compiler could do this. I am inclined to say it
was.

Support for more complex forms such as virtual multiple inheritance was
added later. This technology is quite complicated and I don't know of any
instances before C++, but then again, I suspect anyone competent in the
art could have devised it, given knowledge of Unix device drivers.

If vtables were patented, I expect languages such as Java would adopt
Smalltalk-like dispatch, which is usually more efficient anyway. I believe
some implementations of Eiffel do this.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Noel Yap <Noel.Yap@morganstanley.com>
Date: 04 Jan 03 14:38:01 GMT
Raw View
Hyman Rosen wrote:
> What's wrong with just adopting true nested functions?
> If the implementation is able to create executable thunks
> on the stack, pointers to nested functions are the same as
> normal pointers to functions. Pascal and Ada have always
> had these, so it's not like this is a radical concept.

Right, and you can sort of do it now using locally defined classes with
static methods.  IMHO, nested functions (and anonymous functions) would
be nice syntactic sugar.

MTC,
Noel


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: kanze@gabi-soft.de (James Kanze)
Date: 04 Jan 03 14:41:08 GMT
Raw View
llewelly <llewelly.@@xmission.dot.com> wrote in message
news:<86wulqvnem.fsf@Zorthluthik.foo>...
> kanze@gabi-soft.de (James Kanze) writes:

> [snip]
> > There are a number of third party libraries available for C++.
> [snip]
> Do developers know they exist? Do they know where to find them? I
>     don't think they do. It seems to me that C++ lacks a well-known
>     central starting point for developers to begin looking for
>     libraries.

Good question.  I know where to start looking:-).

There are also political problems involved with using a third party
library.

> Every perl developer knows to go to CPAN to start looking for
>     libraries; every perl book mentions it, usually several
>     times. Some perl books spend a whole chapter on finding existing
>     perl libraries at CPAN and related sites.

That's a good idea.  I know of CTAN for TeX; maybe we need something
similar for C++.  But it isn't as easy: in the case of TeX and Perl,
there is an organization or a single person who is more or less in
charge.  There's nothing similar for C++.

For starters, you might try following links from Bjarne Stroustrup's
site.  He's got one to a page full of GUI libraries, and another to
information about garbage collection, for example.

None of which is a substitute for standardization.  The page for GUI
libraries lists quite a few, but who knows how long some of them will be
available.  And of course, what you learn using one isn't necessarily
applicable with the next -- an important consideration for people like
me, who work on a contract basis, and change companies after each
project.

> By contrast, I don't think I own a single C++ book that mentions
>     boost. If own such a book, it didn't say much about boost.

Give them time:-).

> The primary reason C++ is backwards compatible with C is to facilitate
>     the use of existing 3rd party libraries. Yet it more and more it
>     seems it is much easier to find suitable Perl or Java libraries
>     than to find suitable C++ libraries. The C++ libraries are out
>     there - but where does one find them?

With Google:-).  And yes, it is harder than for Perl or Java.

> [snip]
> > Performance in general has ceased to be reason why people use C++.
> > Personally, I doubt that it was ever a real reason -- C++ doesn't
> > beat assembler, and rarely beats C.
> [snip]

> Given how little certain frequent posters here know about the
>     performance implications of C++ features, I strongly agree that
>     performance has ever been an important factor for most
>     people. There have always been a few, however.

And they can usually get it.  While there are cases where Java is
faster, it will usually be easier to profile and tune C++.  (For
starters, I've never seen a C++ compiler without a profiler, and I've
never seen a Java compiler with one.)

> [snip]
> > > Safety:
> > >   Eiffel supports pre- and post-conditions, etc., for defensive
> > > programming

> > True, but not as well as C++.

> The C++ support for pre- and post-conditions is (so far as I can see)
>     unknown to the majority of C++ programmers. One common technique
>     is to use public non-virtual methods and private virtual methods -
>     yet I still meet C++ programmers who say private virtual functions
>     are useless.

There is definitely a problem of education.  It's less of a problem than
with Eiffel, mainly because unless you are already aware of the
advantages of programming by contract, you've probably never heard of
Eiffel.

I stand by my statement, however, that if your goal is programming by
contract, you can probably do it better in C++ than in Eiffel.  I will
agree, however, that if you don't give a damn about programming by
contract, it's easier to ignore in C++ than in Eiffel.

> C++ does not have better support for pre- and post-conditions (than
>     Eiffel) unless one has well-educated C++ programmers.

That is probably true for everything.  One of the problems with offering
a lot of liberty is that it requires a lot of responsibility on the part
of the programmers.

> [snip]

> > True closures don't fit into the C++ model -- saying that
> > destructors won't be called on local variables (because their
> > lifetime might extend beyond the end of the function) isn't going to
> > win support from people using RAII.  Some sort of partial closure
> > could (and IMHO should) be considered, however.  I'd imagine
> > something along the following lines:

> >   - At every point Within a function, there is an implicitly defined
> >     class with the name __local_context.  This class is semantically
> >     defined as containing a reference to every visible variable with
> >     automatic storage duration, pre-initialized to refer to that
> >     variable.  (I can imagine that in many, if not all cases, the actual
> >     implementation can do better.)  These member variables have the same
> >     name as the referred to variable, and are public or protected (TBD).

> >     Every use of this "class" generates in fact a new type.  (Or it
> >     is unspecified whether it generates a new type if the sets of
> >     visible variables are identical.)

> >   - The keyword lambda declares a new class derived from this class,
> >     with a single member, the function operator().  The syntax is:

> >         lambda ( parameter-list[opt] ) [base-class-decls]
> >         {
> >             function-body
> >         }

> >     The defined function is, of course:

> >         operator()( parameter-list[opt] )
> >         {
> >             function-body
> >         }

> >     If one of the base classes happens to have a virtual function
> >     with the same signature, then this function overrides it.

> >     I still haven't thought of a good syntax for the return type.

> I think people will expect the return type to appear in the front:

That's certainly where I would expect it (in C++).  Try it with a few
typical uses, however, and see what it does to readability/parsability.
The problem is that the C++ declaration syntax doesn't adapt well to
declarations in the middle of expressions.  (Some people would claim
that it doesn't adapt well, period.  I believe I've heard it qualified
as an experiment which failed.)

> [snip]

> Most current C++ objects can have static, automatic, or dynamic
>     lifetimes. I think C++ closures will require the same
>     flexibility.

Most current C++ objects can also have temporary lifetime (which is a
fourth type).  The have temporary lifetime when the object is neither
explicitly created nor named.  A lambda object cannot be named.  I'm not
sure about the creation business : new lambda ... ?

Since the lambda objects expose the local stack frame, I don't quite see
any advantages in allowing them to have a lifetime which extends beyond
that of the local stack frame.  Since static lifetime always extends
beyond the local stack frame, we can forget it.  (Since you cannot
declare a named object with a lambda type, there would be no place to
put the static anyway.)  Automatic and temporary pose no problems.  The
real question is dynamic -- I suppose that there will be cases where it
makes sense to e.g. pass a lambda object by means of an auto_ptr.  It's
something to think about, anyway.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: KIM Seungbeom <musiphil@bawi.org>
Date: 04 Jan 03 14:42:16 GMT
Raw View
DrPizza wrote:
>
> Granted, it would be nicer if we have compiler extensions available of the
> kind that g++ provides; it has a special minimum operator that works the
> correct, intuitive way (like the macro) but only evaluates its operands once
> (like the function).

I agree. I even tested the following and it worked:

    short a = 1;
    long b = 3;
    (a <? b)++;

Why don't we bring these operators into the standard?
As Andrei Alexandrescu said, minimum and maximum are so simple
concepts that they deserve to be supported by the core language.
They have existed in practice for quite a long time, too.

It has also been shown in his article "Min and Max Redivivus"
that, without the support of the core language, it is terribly
hard to express in C++ such simple concepts.

--
KIM Seungbeom <musiphil@bawi.org>

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Daniel Sch|le" <uval@rz.uni-karlsruhe.de>
Date: 04 Jan 03 14:43:31 GMT
Raw View
> The current, released, version of MSVC (7.0) has a selection of
> different ways of handling this, including the standard-compliant way.
> Even 6.0 would exhibit the standard-compliant behaviour, but
> unfortunately only in a mode which wasn't actually useful for anything
> else.

or one can use this hack

#define for if(true)for

:)


--
Daniel.




      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: kanze@gabi-soft.de (James Kanze)
Date: 04 Jan 03 14:43:05 GMT
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0212311246.555ef8b7@posting.google.com>...
> kanze@gabi-soft.de (James Kanze) wrote
> > Just a point, but I don't think that C++ was ever "far ahead of the
> > field" in any of the ways you mention.  What has made C++ popular
> > were pratical issues (like a simple upward migration path from C),
> > NOT its underlying models.

> I do.

> When Bjarne was inventing C++, there were other languages with classes
> and runtime polymorphism... but they all did some type of runtime
> interpretation, and as a result they were extremely slow. At the time,
> if you had asked an expert how to get the runtime polymorphism to
> occur at compile time, he probably would have told you that this was a
> contradiction in terms.  (He'd have been right, too!)

I'm not sure about the time frame, but I do know that there exist (and
existed) compilers for Smalltalk.  The lack of static type checking
meant that it requires more work for the compiler to get the expected
performance, but it doesn't mean that it is impossible.

Was C++ the first OO language with static type checking.  It could be; I
don't know.  (I know that Eiffel was there very early.)

> C++ was the first language to differentiate between those things that
> can be done at compile time, and those things that must wait until
> runtime. By distinguishing between virtual functions and non-virtual
> functions, C++ allowed most processing to keep the runtime efficiency
> of C, while still implementing runtime polymorphism. C++ took
> object-oriented programming out of the laboratories and into the
> business realm.

Eiffel took a different approach: that it is the compiler's job to make
this distinction.  I don't really know how this works out in practice,
but Eiffel fans do claim the same performance as C++.

The reason for non-virtual functions has, IMHO, nothing to do with
performance, at least not today.  The reason to have non-virtual
functions is that they are necessary to maintain class invariants -- if
you don't care about programming by contract, you could make every
function virtual, always.

> In short, C++ was the first language to implement a "virtual table."
> Because it's such an obvious idea now, it's easy to forget what an
> absolutely brilliant insight this must have been when it was new --
> IMHO, it's on the same magnitude as the invention of storing programs
> in RAM instead of patch panels, or using "high level" expressions
> instead of individual (assembly-language) instructions.

Let's not exagerate.

> In the far distant future (10 years? 1000 years? Nobody can know), C++
> will be obsolete, replaced by something that renders all "high level
> languages" obsolete -- perhaps the talking computer that we all see on
> Star Trek. Even then, I think that C++ will remain worthy of study, if
> only for historical reference. Like the canals in ancient Rome, it
> represents a huge step towards our modern world.

> > "Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote
> > > Performance:
> > >   Much higher-level languages like OCaml now directly rival C and
> > >   C++ Just-in-time compilation for virtual-machine-based languages
> > >   such as Java makes the difference insignificant for many
> > >   applications that previously needed C++'s speed

> > Performance in general has ceased to be reason why people use C++.

> I beg to differ.

There are probably applications where it plays a role.  There are
certainly a lot of cases where it is a mistaken reason -- where many
other languages would be suitably fast, but no one takes time to
investigate them, because it is common knowledge that they are too
slow.  (Common knowledge is, regretfully, far too often wrong.)

> > Personally, I doubt that it was ever a real reason -- C++ doesn't
> > beat assembler, and rarely beats C.

> Assembler doesn't have expressions. C doesn't have classes.

> C++ "beats" Simula, or any other (pre-C++) language that implements
> objects.

Did it beat Eiffel in 1988?  I know of one company that did an
evaluation then to determine its future language.  Eiffel ended up being
eliminated because there were no big companies behind it, and without
the advantages of C compatibility, it was uncertain how long it would
last.  There was no problem with its performance then.

> C++ usually holds its own with post-C++ object-oriented languages; I
> think it was you that said that you can find benchmarks that prove C++
> beats Java, or benchmarks that prove the opposite, or benchmarks that
> prove that C++ and Java are essentially identical.  Note that Java has
> a virtual table.

So does Eiffel.  So does Modula-3.  So do (probably) some modern
implementations of Smalltalk, although it would certainly require some
form of global optimization to do it.  (I know that modern Smalltalk
generates exactly the same code for integer arithmetic as does C++.
Even though their integer type is a full fledged class, and operator+ is
a virtual function which a derived class can override.)

> Note that if Stroustrup or AT&T had patented the idea of virtual
> tables (as opposed to merely copyrighting the compiler), Java might
> not exist.  If someone can get a patent on using XOR to draw a line,
> then surely Stroustrup could have patented the virtual table -- which
> (unlike XOR) did NOT have prior art, and was NOT obvious.

I'm not sure about the prior art, but you're certainly right that such
details don't seem to be much of an impedament to a software patent.

Of course, all that would have meant is that the rest of the world would
have Java, but not the US, since most countries don't recognize software
patents.

> (AFAIK, the closest equivalent to virtual tables was a "jump table"
> used to implement such things as select/case statements.)

How about a computed goto in Fortran:-).

I'm afraid I don't see virtual tables as such a radical step forward.
An innovation, to be sure, but an innovation at the lowest level.  I
don't know whether Stroustrup invented them, or someone else, but I'm
sure that if he hadn't invented them, someone else would have.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: kanze@gabi-soft.de (James Kanze)
Date: 04 Jan 03 14:45:16 GMT
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0212311212.3f6b32cd@posting.google.com>...
> kanze@gabi-soft.de (James Kanze) wrote
> > "DrPizza" <drpizza@anti-flash.co.uk> wrote
> > > "Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote
> > > > template <typename T>
> > > > inline const T& max(const T& a, const T& b) {
> > > >  return (a<b)?b:a;
> > > > }

> > > Hugely better except it's not actually as good as this macro in
C++:
> > > #define max(A, B) ((A) > (B) ? (A) : (B))
> > > Your function isn't an l-value;

> > His function is always an l-value.  (I'm not convinced that this is
> > a good thing, however.)

> Why might this not be a good thing?

More a matter of taste than anything else.

> Joshua's version is a non-modifiable l-value. It won't allow code like
> this:

>     max(2,3)=4;

> If Joshua's version didn't have "const", the above code would create a
> temporary int of value 3, then change the temporary to value 4. You
> never know when you're going to need something like this!  8->

It's easy enough to overload his version on const, so that it will
allow:
    max(i,j) = 0 ;
as long as i and j are lvalues with the same type.  I just don't happen
to find such code particularly readable.  (I might add that I've never
had a need for it either.)

Joshua's version does allow:

    int const* pi = &max(2,3) ;

As I say, I'm not convinced that this is a feature.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 4 Jan 2003 16:06:26 -0500
Raw View
"Nikolaos D. Bougalis" <nikb@webmaster.com> wrote in message
news:nKJQ9.24201$oy5.1638343@news2.west.cox.net...
>     The template shown did not work. I provided one that does, and
> instead
> of acknowledging that my version worked for the situation you provided,
> you
> change things around. Onwards...
I didn't say that there was any one flaw.  Rather, there is a combination of
flaws.

>     Only if you know that "max" and "min" are macros. If you happen to
> forget, you'll be chasing "phantoms."
So put its name in ALLCAPS as an aide memoire.

>     I'm sure you'd really like to call "max" with one int and one float
> (or
> an unsigned int, or whatever else); but comparing apples and oranges
> should
> be left to a function that knows how to compare them. Not a generic
> version.
BS.

The built-in comparison operators work just fine.  They work in a defined,
predictable way.


>     Let's how does your macro handle this case of mixed types you like
> so
> much...
>
> #include <iostream>
>
> #define max(a, b) ((a) > (b)) ? a : b
That is not my macro.  Stop misrepresenting my position.  This shows nothing
more than your ability to write a faulty macro.

>
> int main(int argc, char **argv)
> {
>     int i = 7378;
>     double d = 0.7378;
>     max(i, d) = 0.7319;
>     std::cout << "i=" << i << std::endl;
>     std::cout << "d=" << d << std::endl;
>     return 0;
> }
>
>     Here's how:
>
> i=7378
> d=0.7378
No kidding.  What the hell does that prove?  you just evaluated:

i > d ? i : d = 0.7319;

the "d = 0.7319" is the false case of the conditional.  I didn't put in those
extra brackets for fun, you know.  I put them in because it needs it to force
the evaluation to occur in a certain way.

If you wrote the macro properly you would rightly get a compile-time error.
Because of the temporary created by the conversion, the thing isn't an lvalue,
so it fails to compile.  As it should.

>     The macro only *appears* to work with different types. In reality,
> it's
> undefined behavior, and it's asking for trouble. Look at the example
> again... Apples and oranges.
The macro works fine with different types.
The macro uses defined conversions.
The example you've provided is completely bogus because you're using a faulty
macro -- not the macro I provided.

--
Now Playing:  CD1   Matt Darey - Pure Euphoria

char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 4 Jan 2003 16:24:15 -0500
Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote in message
news:<chwmO2p2Z3E+Ewwu@robinton.demon.co.uk>...
> In article <auqh6n$3ts$1@venus.btinternet.com>, DrPizza
> <drpizza@anti-flash.co.uk> writes

> >Whether that's wrong or not is a matter of opinion.  I don't agree
> >that it is.  I certainly don't think that the macro's behaviour in
> >this situation is wrong:
> >int a;
> >short int b;
> >...
> >max(a, b);

> >But the template will fail.

> Not if correctly written:

> max<int>(a, b);

> And it was the need to make the simple max template work that caused
> the change in C++ circa 1993 to allow explicit specification of
> function template parameters.

This still causes problems when the two types are typedef's, and you
don't really know the actual type.  Potentially (although I cannot think
of a reasonable case in practice), you don't know the larger type.

In general, comparing two integral types is safe if both have the same
signedness, you choose the larger as the results.  Ditto comparing two
floating point types.  Compare signed and unsigned, or floating point
and integral, and you get on shaky ground.

For the built-in types, there is also a simple solution:

    template< typename T1, typename T2 >
    BinaryArithmetic< T1, T2 >::result_type
    max( T1 const& a, T2 const& b )
    {
        BinaryArithmetic< T1, T2 >::result_type result_type ;
        return (static_cast< result_type >( a )
                > static_cast< result_type >( b ))
            ?    static_cast< result_type >( a )
            :    static_cast< result_type >( b ) ;
    }

with an overload:

    template< typename T >
    T&
    max( T& a, T& b )
    {
        return a > b ? a : b ;
    }

for potential use as an lvalue (if you want that sort of thing).

I suspect that Andrei could even come up with a definition of
BinaryArithmetic which would work for user defined types.  (I'm fairly
simple minded, so I would just specialize it for all of the built-in
types, and partial specialization for the case where T1 and T2 were the
same type.)

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 4 Jan 2003 18:39:12 -0500
Raw View
Hyman Rosen <hyrosen@mail.com> wrote in message
news:<1041280069.998496@master.nyc.kbcfp.com>...
> James Kanze wrote:
> > Some sort of partial closure could (and IMHO should) be
> > considered, however.  I'd imagine something along the following lines:

> What's wrong with just adopting true nested functions?  If the
> implementation is able to create executable thunks on the stack,
> pointers to nested functions are the same as normal pointers to
> functions. Pascal and Ada have always had these, so it's not like this
> is a radical concept.

Backwards compatibility, and the idea that if you don't use something,
you don't pay for it.  The problem isn't with the function itself; it's
with pointers to functions.  A true nested function requires not only
the address of the function, but also some information to find the
context.  It you add this to a pointer to a function, you've increased
the cost even if you don't use nested functions.

The issue has been greatly discussed in the past.  There are various,
alternative solutions.  There is no consensus for any one of them, which
makes the whole thing rather difficult.

Finally, IMHO, a solution based on classes seems to fit better into the
C++ framework.  We're already used to using functional objects
extensively with STL; this would make the local context a base class for
locally defined functional objects.  (Obviously, for this to be totally
useful, we'd have to lift the restriction against instantiating
templates on local types.)

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: 05 Jan 03 02:19:20 GMT
Raw View
On 2 Jan 2003 07:49:52 -0500, "Chris Newton"
<chrisnewton@no.junk.please.btinternet.com> wrote:

> "John Potter" <jpotter@falcon.lhup.edu> wrote...
> > "Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote:

> > > My comments about the sorting algorithms related to the
> > > conciseness with which they can be *implemented* in some
> > > other languages, as an example of the fact that power
> > > and simplicity are not mutually exclusive.

> > You did not comment about sorting algorithms.

> Yes, I did. Rather than telling me what I have and haven't written, I
> invite you to visit the thread at somewhere like groups.google.com,
> where you can see all of my comments.

I have a 30 day cache.  You said merge sort not sorting algorithmS.  You
also used it as an example of how nice other languages are in general.

> My point is to demonstrate that you can write powerful code concisely
if
> the language provides the tools to do so, and that this is a
reasonable
> basis for considering the inclusion of new language (or library)
> features in C++.

Not language, see below.

> > You stated without example that merge sort could be concisely
> > implemented in other languages.  Code please.

> Haven't got a tested merge sort handy, but try the Haskell example of
> quicksort in one of Andrei Alexandrescu's recent CUJ articles:
>   http://www.cuj.com/experts/2012/alexandr.htm?topic=experts

Cute. Eight lines in C++ or one using sort<>.  Unreadable gibberish
to a procedural programmer.

> Is there some problem with the idea that C++ could learn some
> tricks from other languages that only help in lots of cases, and not
in
> all of them?

Yes.  C++ is a procedural language.  Your comments seem to be nothing
more than the functional rhetoric which has forcast the death of
procedural languages for ages now.  I have been told by a respected
person that my stl code looks too much like lisp.  That is, too much
like lisp to be presented to average professional programmers.  Trying
to make C++ look functional at the language level is a mistake and the
library will simply not see general use.  C++ may be replaced by a
functional language some day, but trying to distort it into one is
foolish.

It is easy to sell higher level solutions (library).  It is not easy to
sell a different (maybe higher level) paradigm (language).

John

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Stephen Toledo-Brown <nomail@hursley.ibm.com>
Date: 05 Jan 03 02:19:43 GMT
Raw View
DrPizza wrote:
>

> The macro has far fewer issues because ?: performs conversions.
> In most
> cases, the function won't work.  I mean, even really simple things
like:
> long a(1);
> short b(2);
> min(a, b);
>
> won't work with a function -- and fixing the function is non-trivial.

As Francis already pointed out, fixing the call is trivial.
Use either min<short>(a, b) or min<long>(a, b) according to the
intention/context. I find it's a benefit for casts/conversions to be
made explicit, and I'm clearly not alone, which is why we now have
things like const_cast, dynamic_cast, etc.

--
Steve Toledo-Brown
Speaking for myself only.
Humans please use reply-to address: nomail is a non-read spam hole.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nagle@animats.com (John Nagle)
Date: Sun, 5 Jan 2003 07:44:01 +0000 (UTC)
Raw View
Dave Harris wrote:

> allan_w@my-dejanews.com (Allan W) wrote (abridged):
>
>>C++ was the first language to differentiate between those things
>>that can be done at compile time, and those things that must
>>wait until runtime.


    PL/1 had compile-time preprocessing, probably more than
it should have had.

    LISP had far too much compile-time preprocessing.
Look up the "MIT loop macro".  Eventually, the LISP
crowd trimmed their language down to a manageable
size with Scheme, but by then it was too late.

    (LISP could have been the language of the Internet,
especially since most Internet-transmitted data
structures are trees.  Yahoo Store was (still is?)
a LISP application.  Understanding why that didn't
happen is a good exercise for language designers.)

    John Nagle
    Animats

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly <llewelly.@@xmission.dot.com>
Date: 2 Jan 2003 07:48:54 -0500
Raw View
allan_w@my-dejanews.com (Allan W) writes:

[snip]
> > though I think one may need the slightly uglier
> > #define max(A, B) *((A) > (B) ? &(A) : &(B))
> > (or perhaps one only needs that in C?)
>
> This one isn't just uglier, it's also worse -- if argument b is ++j,
> you get a syntax error.
[snip]

I think the syntax error is an improvement - better a compiler error
    than an unexpected (and unreported) increment at runtime.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 2 Jan 2003 07:49:52 -0500
Raw View
"John Potter" <jpotter@falcon.lhup.edu> wrote...
> "Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote:
> > My words quoted above referred to things like regular
> > expressions, that being one example of a generally
> > useful facility not currently provided in standard C++.
>
> Fine.  A library addition handles that with no language change.

Yes. I didn't say it needed a language change; in fact, I explicitly
mentioned this as a useful *library extension* in my first post to this
thread, and elsewhere in the thread there have been mentions of two such
libraries currently in existence.

> > My comments about the sorting algorithms related to the
> > conciseness with which they can be *implemented* in some
> > other languages, as an example of the fact that power
> > and simplicity are not mutually exclusive.
>
> You did not comment about sorting algorithms.

Yes, I did. Rather than telling me what I have and haven't written, I
invite you to visit the thread at somewhere like groups.google.com,
where you can see all of my comments.

My point is to demonstrate that you can write powerful code concisely if
the language provides the tools to do so, and that this is a reasonable
basis for considering the inclusion of new language (or library)
features in C++.

> You stated without example that merge sort could be concisely
> implemented in other languages.  Code please.

Haven't got a tested merge sort handy, but try the Haskell example of
quicksort in one of Andrei Alexandrescu's recent CUJ articles:
  http://www.cuj.com/experts/2012/alexandr.htm?topic=experts
The point is equally valid in either case. If you really want, I can
write you a similarly concise demonstration of merge sort as well.

It seems to me that this is a good example of the power of a pattern
matching system, something that I have suggested elsewhere in this
thread could be a useful and well-integrated feature in C++ also.

> Now, you seem to claim that merge sort is an example which
> proves that all algorithms are better implemented in some
> other languages.

I don't see how you can possibly read that into anything I've written
here. I have used the word "example" in this post, and in the one before
it, as you can see from the quote above. That is what I wrote, and that
is what I meant. I haven't made any claim about "all algorithms"
anywhere. Is there some problem with the idea that C++ could learn some
tricks from other languages that only help in lots of cases, and not in
all of them?

Regards,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 2 Jan 2003 07:57:14 -0500
Raw View
"Allan W" <allan_w@my-dejanews.com> wrote in message
news:7f2735a5.0212301256.6ade08a7@posting.google.com...
> Why not?
Because it doesn't yield a modifiable lvalue.
Because it doesn't perform standard conversions and hence doesn't work with
mixed types.

> The min() and max() macros are LiTERALLY the textbook examples (in
> almost every textbook) of why inline functions can be better than
> macros.
They're also excellent examples of why macros can perform useful tasks that
are extremely hard with inline functions.

> The textbook generally goes on to talk about arguments with
> side-effects:
>
>     int foo() {
>         int i=4;
>         int j=6;
>         return max(++i,++j);
>     }
Except we know better than to do that with macros.  We give them a nice
all-caps identifier (MIN and MAX), so we know they're macros, and we make sure
to not use operands with side-effects.

Meanwhile, the proposed function is left with the aforementioned problems.

Granted, it would be nicer if we have compiler extensions available of the
kind that g++ provides; it has a special minimum operator that works the
correct, intuitive way (like the macro) but only evaluates its operands once
(like the function).

> Also, user-defined types typically define operator< to test for
> less-than, but sometimes they don't define operator>. It would be
> better to put the test back the way Joshua Lehrer had it:
>
>     #define max(A, B) ((A) < (B) ? (B) : (A))
If you want.

> This one isn't just uglier, it's also worse -- if argument b is ++j,
> you get a syntax error.
It's also only necessary in C.

> Your first version of the macro isn't an lvalue, though your second
> version is.
The first version is an lvalue in C++:

"If the second and third operands are lvalues and have the same type, the
result is of that type and is an lvalue." (5.16 para. 4)

though not C.

> Joshua Lehrer's inline function IS an lvalue, albiet a nonmodifiable
> one.
> To make it modifiable, remove the keyword "const." (Please try it, or
> refer to the standard.) When you return a reference, the caller can
> modify that referenced object.
You can't simply "remove" it; you need to provide a version taking const
parameters and a version taking non-const parameters.

> The only issue is when the two data types aren't equal... a situation
> that the macro also has issues with. In most cases, both will provide
> valid results.
The macro has far fewer issues because ?: performs conversions.  In most
cases, the function won't work.  I mean, even really simple things like:
long a(1);
short b(2);
min(a, b);

won't work with a function -- and fixing the function is non-trivial.

--
Now Playing:  Electric Light Orchestra - Don't Bring Me Down

char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 2 Jan 2003 19:15:59 +0000 (UTC)
Raw View
In article <3e109286@news.toast.net>, Scott Mayo <scottm@toast.net>
writes
>This
>isn't too unreasonable; it's sort of a syntax wart in the first
>place - if it's defined *outside* the curly braces, why did
>the scope end *inside* the curly braces?

But it doesn't. Variables declared in conditionals do that (while, if
and the control expression in for) Variables declared in the initialise
expression of for are in a kind of notional scope that is opened by for
and closes on exit from the loop. The ones that catch many programmers
are like this:

for(; int i = 0; ++i) <do something >;

which, of course, does nothing :)


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "David B. Held" <dheld@codelogicconsulting.com>
Date: 01 Jan 03 12:23:02 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message
news:auk57b$ra5$1@venus.btinternet.com...
> [...]
> Hugely better except it's not actually as good as this macro in C++:
> #define max(A, B) ((A) > (B) ? (A) : (B))
>
> though I think one may need the slightly uglier
> #define max(A, B) *((A) > (B) ? &(A) : &(B))
> (or perhaps one only needs that in C?)
> [...]

What is the result of:

int i = 2, j = 3;
int k = ::max(++i, j--);

It should be obvious that the template version gives the "expected"
result.
Or perhaps the intent of second version is to catch side-effects that
produce
rvalues?  And what happens when you have side effects that produce
lvalues?  Then what?  And why shouldn't operators with side effects be
allowed in such a call?  Only because you insist on using the macro
version.

Dave



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Hyman Rosen <hyrosen@mail.com>
Date: 01 Jan 03 12:26:04 GMT
Raw View
James Kanze wrote:
> Some sort of partial closure could (and IMHO should) be
> considered, however.  I'd imagine something along the following lines:

What's wrong with just adopting true nested functions?
If the implementation is able to create executable thunks
on the stack, pointers to nested functions are the same as
normal pointers to functions. Pascal and Ada have always
had these, so it's not like this is a radical concept.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: allan_w@my-dejanews.com (Allan W)
Date: 01 Jan 03 13:27:50 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote
> "Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote
> > Here, this is very simple, very uniform, C++ snippet.  Every major
> > compiler gets it right, and this solution is hugely better than the
> > c-style solution of a macro.  It uses templates:
> >
> > template <typename T>
> > inline const T& max(const T& a, const T& b) {
> >  return (a<b)?b:a;
> > }
>
> Hugely better except it's not actually as good as this macro in C++:
> #define max(A, B) ((A) > (B) ? (A) : (B))

Why not?

The min() and max() macros are LiTERALLY the textbook examples (in
almost every textbook) of why inline functions can be better than
macros. The textbook generally goes on to talk about arguments with
side-effects:

    int foo() {
        int i=4;
        int j=6;
        return max(++i,++j);
    }
Here the macro version returns 8, because the expression ++j is
evaluated twice, while the inline version returns what the caller
is probably expecting: 7.

Also, user-defined types typically define operator< to test for
less-than, but sometimes they don't define operator>. It would be
better to put the test back the way Joshua Lehrer had it:

    #define max(A, B) ((A) < (B) ? (B) : (A))

> though I think one may need the slightly uglier
> #define max(A, B) *((A) > (B) ? &(A) : &(B))
> (or perhaps one only needs that in C?)

This one isn't just uglier, it's also worse -- if argument b is ++j,
you get a syntax error.

> Your function isn't an l-value; the macro can be (for instance, one
may wish
> to write something like:
> min(a, b) = 0;
> )

Your first version of the macro isn't an lvalue, though your second
version is.

Joshua Lehrer's inline function IS an lvalue, albiet a nonmodifiable
one.
To make it modifiable, remove the keyword "const." (Please try it, or
refer to the standard.) When you return a reference, the caller can
modify that referenced object.

> and I think the function has issues with type conversions and
promotions and
> all that stuff.

The only issue is when the two data types aren't equal... a situation
that the macro also has issues with. In most cases, both will provide
valid results.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 01 Jan 03 13:28:15 GMT
Raw View
In message <aukknh$4c2$1@knossos.btinternet.com>, Chris Newton
<chrisnewton@no.junk.please.btinternet.com> writes
>In both cases, I stand by my claim that progress is being made, and it
>would be advantageous for such things to become part of the next C++
>standard.

So perhaps it is just as well that we have not tied ourselves to
whatever was available in 1995/6. I have no problem with adding material

to C++ as long as we are in a position to understand what we are doing
and to get it right. While we got some things wrong in the current
standard, I think that had we added more we would have made far more
errors.

One of the penalties paid by being a very widely used language is that
there is a great deal of source code that has to be cared for. The more
a language is used the more legacy code there is to break.

Standards are about portability in time as well as space. Currently I
can write quite extensive code and get to compile diagnostic free with
MingW in its strictest mode. If a new Standard broke that code it would
very much annoy me because I have an entire book for programming novices

sitting on top of it, exactly the people who would simply have their
confidence destroyed if the consequence of a new compiler was to make
example code generate, for them weird, diagnostics.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: jpotter@falcon.lhup.edu (John Potter)
Date: 01 Jan 03 13:41:43 GMT
Raw View
On 30 Dec 2002 17:40:53 -0500, "Chris Newton"
<chrisnewton@no.junk.please.btinternet.com> wrote:

 > I think my comments have lost their context somewhere.

I think your comments lack any meat.

 > My words quoted above referred to things like regular expressions, that
 > being one example of a generally useful facility not currently provided
 > in standard C++.

Fine.  A library addition handles that with no language change.

 > My comments about the sorting algorithms related to the conciseness with
 > which they can be *implemented* in some other languages, as an example
 > of the fact that power and simplicity are not mutually exclusive.

You did not comment about sorting algorithms.  You stated without
example that merge sort could be concisely implemented in other
languages.  Code please.  Now, you seem to claim that merge sort is an
example which proves that all algorithms are better implemented in some
other languages.

John

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 1 Jan 2003 13:50:30 -0500
Raw View
"Nikolaos D. Bougalis" <nikb@webmaster.com> wrote in message
news:rtoP9.108173$vb3.3961341@news2.west.cox.net...
> > Hugely better except it's not actually as good as this macro in C++:
> > #define max(A, B) ((A) > (B) ? (A) : (B))
>
>     Unfounded assertion.

Getting the virtues of the macro and getting rid of its shortcomings is not
easy.

http://www.moderncppdesign.com/publications/cuj-04-2001.html


Andrei
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 1 Jan 2003 15:42:57 -0500
Raw View
"Nikolaos D. Bougalis" <nikb@webmaster.com> wrote in message
news:rtoP9.108173$vb3.3961341@news2.west.cox.net...
> "DrPizza" <drpizza@anti-flash.co.uk> wrote in message
>     Unfounded assertion.
It's nothing of the sort.

The template function doesn't work here:
double a, b;
...
min(a, b) += 2;
int c, d;
...
int smallest = min(c, d);

The macro does.

Yes, the macro has the problem with side-effects.  But so what?  We all *know*
about that problem and can consequentially *avoid* that problem.

>
> > Your function isn't an l-value; the macro can be (for instance, one
> may
> wish
> > to write something like:
> > min(a, b) = 0;
> > )
>
>     Easily fixed...
>
> template <typename T>
> inline T& max(T& a, T&b) { return (a<b) ? b : a; }
Still doesn't work properly with mixed types.

>     What kind of issues? The function will be instantiated for every
> distinct type that requires it. A different one for char, int, MyClass,
> etc.
What kind of issues?  The macro works with different types -- it performs type
promotions and conversions as necessary.  The function template... doesn't.


--
Now Playing:  Blank and Jones - The Mix Vol. 1 CD1 (D I G I T A L L Y - I M P
O R T E D - European Trance, Techno, Hi-NRG... we can't define it!)


char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 1 Jan 2003 15:43:16 -0500
Raw View
"Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote in message
news:31c49f0d.0212291358.4255a123@posting.google.com...
> I know, I know.  There are many ways to make this an lvalue, or an l-
> or r-value, depending on the type, support type conversions, etc...
> But that wasn't the point of this thread.

The point is that I disagree with the claim that that function is superior to
the macro.  It isn't.  It gives function semantics -- no macro double
evaluation or anything like that -- but sacrifices other capabilities --
things like conversions and promotions and l-valueness.


--
Now Playing:  Blank and Jones - The Mix Vol. 1 CD1 (D I G I T A L L Y - I M P
O R T E D - European Trance, Techno, Hi-NRG... we can't define it!)

char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 1 Jan 2003 17:38:02 -0500
Raw View
"James Kanze" <kanze@gabi-soft.de> wrote in message
news:d6651fb6.0212300403.2a3ae883@posting.google.com...
> "DrPizza" <drpizza@anti-flash.co.uk> wrote in message
> > Hugely better except it's not actually as good as this macro in C++:
> > #define max(A, B) ((A) > (B) ? (A) : (B))
>
> You mean in cases like max( *pi ++, 0 ) ?
Except we all know about that problem and so make sure to avoid it.

> I thought that this was the classical example of why macros didn't work,
> and inline functions were needed.
Except the inline function doesn't work either.

> > though I think one may need the slightly uglier
> > #define max(A, B) *((A) > (B) ? &(A) : &(B))
> > (or perhaps one only needs that in C?)
> So that it won't even work with max( i, 0 )?  Offhand, I can't remember
> ever using max or min where one of the two arguments wasn't a constant;
> you want to forbid all of my uses?
No, I checked, the first macro works fine in C++.  So it doesn't matter.

> His function is always an l-value.  (I'm not convinced that this is a
> good thing, however.)
Sorry; it isn't a /modifiable/ l-value.  And it's occsaionally useful to be
such.

> His function can be overloaded on const to allow this.  Not that I think
> it a good idea, but it is certainly possible.
Good idea or no, it's a capability the macro has that his function doesn't.

> His function allows using a constant as an argument, which is probably
> the most frequent use.
As does the macro.

> His function only evaluates each argument once, which avoids surprises
> with things like max( *pi++, 10 ).
Except that the double evaluation isn't that surprising, because we know how
macros work.

> The template solution has problems with mixed types.  The macro solution
> may, too, with the difference that the template solution won't compile,
> whereas the macro solution may just give the wrong results (e.g. if one
> argument is a float, and the other a long).
Whether that's wrong or not is a matter of opinion.  I don't agree that it is.
 I certainly don't think that the macro's behaviour in this situation is
wrong:
int a;
short int b;
...
max(a, b);

But the template will fail.

> Generally speaking,
> implicit conversions are a bad thing, although C (and thus C++) has so
> many already, banning them in one special case doesn't seem to fit into
> the language very well.
Implicit conversions may be bad, but promoting to a larger type isn't
particularly bad, and the template won't even do that.


--
Now Playing:  Blank and Jones - The Mix Vol. 1 CD1 (D I G I T A L L Y - I M P
O R T E D - European Trance, Techno, Hi-NRG... we can't define it!)


char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly <llewelly.@@xmission.dot.com>
Date: 1 Jan 2003 18:05:42 -0500
Raw View
kanze@gabi-soft.de (James Kanze) writes:

[snip]
> There are a number of third party libraries available for C++.
[snip]
Do developers know they exist? Do they know where to find them? I
    don't think they do. It seems to me that C++ lacks a well-known
    central starting point for developers to begin looking for
    libraries.

Every perl developer knows to go to CPAN to start looking for
    libraries; every perl book mentions it, usually several
    times. Some perl books spend a whole chapter on finding existing
    perl libraries at CPAN and related sites.

By contrast, I don't think I own a single C++ book that mentions
    boost. If own such a book, it didn't say much about boost.

The primary reason C++ is backwards compatible with C is to facilitate
    the use of existing 3rd party libraries. Yet it more and more it
    seems it is much easier to find suitable Perl or Java libraries
    than to find suitable C++ libraries. The C++ libraries are out
    there - but where does one find them?

> I don't quite see the relationship with scripting languages, but then, I
> don't know either Perl or Python.

Perl is the C++ of scripting languages; it has a loong list of
    features (OO stuff, closures, regex, hashes), a
    trust-the-programmer attitude, and is widely derided for allowing
    programmers to sin their way to damnation.

Python is the Java of scripting languages; strong support for OO,
    strong discipline to ensure no one strays from the One True Path
    of OO, constructs that strive to prevent many kinds of common
    errors, etc.

[snip]
> Performance in general has ceased to be reason why people use C++.
> Personally, I doubt that it was ever a real reason -- C++ doesn't beat
> assembler, and rarely beats C.
[snip]

Given how little certain frequent posters here know about the
    performance implications of C++ features, I strongly agree that
    performance has ever been an important factor for most
    people. There have always been a few, however.

[snip]
> > Safety:
> >   Eiffel supports pre- and post-conditions, etc., for defensive
> > programming
>
> True, but not as well as C++.

The C++ support for pre- and post-conditions is (so far as I can see)
    unknown to the majority of C++ programmers. One common technique
    is to use public non-virtual methods and private virtual methods -
    yet I still meet C++ programmers who say private virtual functions
    are useless.

C++ does not have better support for pre- and post-conditions (than
    Eiffel) unless one has well-educated C++ programmers.
[snip]

> True closures don't fit into the C++ model -- saying that destructors
> won't be called on local variables (because their lifetime might extend
> beyond the end of the function) isn't going to win support from people
> using RAII.  Some sort of partial closure could (and IMHO should) be
> considered, however.  I'd imagine something along the following lines:
>
>   - At every point Within a function, there is an implicitly defined
>     class with the name __local_context.  This class is semantically
>     defined as containing a reference to every visible variable with
>     automatic storage duration, pre-initialized to refer to that
>     variable.  (I can imagine that in many, if not all cases, the actual
>     implementation can do better.)  These member variables have the same
>     name as the referred to variable, and are public or protected (TBD).
>
>     Every use of this "class" generates in fact a new type.  (Or it is
>     unspecified whether it generates a new type if the sets of visible
>     variables are identical.)
>
>   - The keyword lambda declares a new class derived from this class,
>     with a single member, the function operator().  The syntax is:
>
>         lambda ( parameter-list[opt] ) [base-class-decls]
>         {
>             function-body
>         }
>
>     The defined function is, of course:
>
>         operator()( parameter-list[opt] )
>         {
>             function-body
>         }
>
>     If one of the base classes happens to have a virtual function with
>     the same signature, then this function overrides it.
>
>     I still haven't thought of a good syntax for the return type.

I think people will expect the return type to appear in the front:

         return-type lambda ( parameter-list[opt] ) [base-class-decls]
         {
             function-body
         }

>     Perhaps "lambda : return-type ( parameter-list[opt] ) ...".  But the
>     ':' still looks too much like a base class declaration to me.
>
>     This would allow simple predicates along the lines of:
>
>         lambda:bool( int x ) { return x < a ; }
>
>     where a is a local variable or a parameter.  (I think that this
>     simple case can be handled by the boost class, but many more
>     complicated cases can't, at least not without additional information
>     from the programmer.)
>
>   - Maybe: a keyword cleanup, which declares a new class derived from
>     this class, with just a destructor, e.g.:
>
>         cleanup { destructor-body }
>
>     This would allow simple "one of" cases of RAII.
>
> Anyway, this is just at the stage of being an idea for the moment.
[snip]

Most current C++ objects can have static, automatic, or dynamic
    lifetimes. I think C++ closures will require the same
    flexibility.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 1 Jan 2003 18:07:21 -0500
Raw View
"Nikolaos D. Bougalis" <nikb@webmaster.com> wrote in message
news:<rtoP9.108173$vb3.3961341@news2.west.cox.net>...
> "DrPizza" <drpizza@anti-flash.co.uk> wrote in message
> news:auk57b$ra5$1@venus.btinternet.com...
> > "Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote in message
> > news:31c49f0d.0212221329.672f7805@posting.google.com...
> > > Here, this is very simple, very uniform, C++ snippet.  Every major
> > > compiler gets it right, and this solution is hugely better than
> > > the c-style solution of a macro.  It uses templates:

> > > template <typename T>
> > > inline const T& max(const T& a, const T& b) {
> > >  return (a<b)?b:a;
> > > }

> > Hugely better except it's not actually as good as this macro in C++:
> > #define max(A, B) ((A) > (B) ? (A) : (B))

>     Unfounded assertion.

Actually, a completely false assertion.

> > Your function isn't an l-value; the macro can be (for instance, one
> > may wish to write something like:

> > min(a, b) = 0;
> > )

>     Easily fixed...

> template <typename T>
> inline T& max(T& a, T&b) { return (a<b) ? b : a; }

>     As a matter of fact, with C++ you can have both of those
> side-by-side, and only invoke the non-const version when you need
> to. Something which you cannot do with the macro, unless you have
> MAX_CONST or somesuch.

> > and I think the function has issues with type conversions and
> > promotions and all that stuff.

>     What kind of issues? The function will be instantiated for every
> distinct type that requires it. A different one for char, int,
> MyClass, etc.

I think that the problem he is refering to is the fact that both
parameters have to have the same type.  Something like:

    long l = 10 ;
    long m = max( l, 0 ) ;

doesn't work, for example.

In the case of long, using 0L instead of 0 will fix the problem.  In the
case of something like size_t, there is no easy fix.

I think Andrei once addressed this issue, and came up with some
complicated template to resolve it.  (It is easy to resolve for builtin
types, but I don't see a way off hand to extend it to user defined
types.)

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: 1 Jan 2003 18:07:58 -0500
Raw View
kanze@gabi-soft.de (James Kanze) wrote
> "DrPizza" <drpizza@anti-flash.co.uk> wrote
> > "Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote
> > > template <typename T>
> > > inline const T& max(const T& a, const T& b) {
> > >  return (a<b)?b:a;
> > > }
>
> > Hugely better except it's not actually as good as this macro in C++:
> > #define max(A, B) ((A) > (B) ? (A) : (B))
> > Your function isn't an l-value;
>
> His function is always an l-value.  (I'm not convinced that this is a
> good thing, however.)

Why might this not be a good thing?

Joshua's version is a non-modifiable l-value. It won't allow code like this:
    max(2,3)=4;
If Joshua's version didn't have "const", the above code would create a
temporary int of value 3, then change the temporary to value 4. You
never know when you're going to need something like this!  8->
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: 1 Jan 2003 18:08:16 -0500
Raw View
kanze@gabi-soft.de (James Kanze) wrote
> Just a point, but I don't think that C++ was ever "far ahead of the
> field" in any of the ways you mention.  What has made C++ popular were
> pratical issues (like a simple upward migration path from C), NOT its
> underlying models.

I do.

When Bjarne was inventing C++, there were other languages with
classes and runtime polymorphism... but they all did some type
of runtime interpretation, and as a result they were extremely
slow. At the time, if you had asked an expert how to get the
runtime polymorphism to occur at compile time, he probably
would have told you that this was a contradiction in terms.
(He'd have been right, too!)

C++ was the first language to differentiate between those things
that can be done at compile time, and those things that must
wait until runtime. By distinguishing between virtual functions
and non-virtual functions, C++ allowed most processing to keep
the runtime efficiency of C, while still implementing runtime
polymorphism. C++ took object-oriented programming out of the
laboratories and into the business realm.

In short, C++ was the first language to implement a "virtual table."
Because it's such an obvious idea now, it's easy to forget what an
absolutely brilliant insight this must have been when it was new --
IMHO, it's on the same magnitude as the invention of storing programs
in RAM instead of patch panels, or using "high level" expressions
instead of individual (assembly-language) instructions.

In the far distant future (10 years? 1000 years? Nobody can know),
C++ will be obsolete, replaced by something that renders all
"high level languages" obsolete -- perhaps the talking computer that
we all see on Star Trek. Even then, I think that C++ will remain
worthy of study, if only for historical reference. Like the canals
in ancient Rome, it represents a huge step towards our modern world.

> "Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote
> > Performance:
> >   Much higher-level languages like OCaml now directly rival C and C++
> >   Just-in-time compilation for virtual-machine-based languages such as
> >   Java makes the difference insignificant for many applications that
> >   previously needed C++'s speed
>
> Performance in general has ceased to be reason why people use C++.

I beg to differ.

> Personally, I doubt that it was ever a real reason -- C++ doesn't beat
> assembler, and rarely beats C.

Assembler doesn't have expressions. C doesn't have classes.

C++ "beats" Simula, or any other (pre-C++) language that implements
objects. C++ usually holds its own with post-C++ object-oriented
languages; I think it was you that said that you can find benchmarks
that prove C++ beats Java, or benchmarks that prove the opposite, or
benchmarks that prove that C++ and Java are essentially identical.
Note that Java has a virtual table.

Note that if Stroustrup or AT&T had patented the idea of virtual tables
(as opposed to merely copyrighting the compiler), Java might not exist.
If someone can get a patent on using XOR to draw a line, then surely
Stroustrup could have patented the virtual table -- which (unlike XOR)
did NOT have prior art, and was NOT obvious.

(AFAIK, the closest equivalent to virtual tables was a "jump table"
used to implement such things as select/case statements.)
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "DrPizza" <drpizza@anti-flash.co.uk>
Date: 28 Dec 2002 12:52:52 -0500
Raw View
"Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote in message
news:31c49f0d.0212221329.672f7805@posting.google.com...
> Here, this is very simple, very uniform, C++ snippet.  Every major
> compiler gets it right, and this solution is hugely better than the
> c-style solution of a macro.  It uses templates:
>
> template <typename T>
> inline const T& max(const T& a, const T& b) {
>  return (a<b)?b:a;
> }

Hugely better except it's not actually as good as this macro in C++:
#define max(A, B) ((A) > (B) ? (A) : (B))

though I think one may need the slightly uglier
#define max(A, B) *((A) > (B) ? &(A) : &(B))
(or perhaps one only needs that in C?)

Your function isn't an l-value; the macro can be (for instance, one may wish
to write something like:
min(a, b) = 0;
)
and I think the function has issues with type conversions and promotions and
all that stuff.

--
Now Playing:  Dark Moon - Zeitreise

char a[99999],*p=a;main(int c,char**V){char* v=c>0?1[V]:V;if(c<0)for(c=1;c;c
+=!(91^*v)-!(93^*v),++v);else for(;(c=*v)&&93^c;p+=!(62^c)-!(60^c),*p+=!(43^
c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p),91^c||(v=*p?main(0,++v),v-2:\
main(-1,++v)-1),++v);return v;}/*bf prog as argv[1]. drpizza@battleaxe.net*/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 28 Dec 2002 12:56:33 -0500
Raw View
"Anton V. Tykhyy" <pardux@ally.ptf.ntu-kpi.kiev.ua> wrote...
> Chris Newton <chrisnewton@no.junk.please.btinternet.com> wrote:
> > Around five years ago, C++ was far ahead of the field in terms
> > of its underlying models, its performance, its low-level control
> > and its library. Today, many other popular general purpose
> > languages have much more powerful libraries, either as standard,
> > or de facto standards that you can find on places like CPAN. The
> > performance issue is becoming ever less significant, as hardware
> > gets faster, and other tools close the gap anyway. At the same
> > time, the lack of high-level constructs and the safety concerns
> > inherent in using C++ are becoming ever more serious
> > drawbacks.
>
> could you mention what languages do you have in mind?

To give a few examples...

Libraries:
  Java's has grown a lot in recent years, not all good, but often useful
  Super-scripting languages like Perl and Python are rapidly growing up

Performance:
  Much higher-level languages like OCaml now directly rival C and C++
  Just-in-time compilation for virtual-machine-based languages such as
Java makes the difference insignificant for many applications that
previously needed C++'s speed

Higher-level constructs:
  Perl does regexes very well
  ML has exemplary pattern matching and some neat polymorphic type
features to match
  Python (and many others) have "for each" loops to simplify iteration
  Functional languages like ML, and even languages like Java and Python,
provide support for closures or similar concepts

Safety:
  Eiffel supports pre- and post-conditions, etc., for defensive
programming
  Almost no other languages in common use today encourage the use of
unsafe constructs (raw pointers, unchecked arrays, etc.) in preference
to safer alternatives

In other words, I think C++ could usefully learn things from techniques
supported by other OO languages (Java, Eiffel, etc.), from the ease of
use of the major scripting languages (Perl, Python, etc.) and from the
expressive power of functional languages (ML, etc.), and I think these
things could each fit within the "character" of C++ as a useful
extension rather than a clashing feature bolted on too late to work well
with what's already there.

> > On the other hand, we could see the introduction of a couple of
> > powerful and really useful language features: closures come to
> > mind, and perhaps
>
> please, i understand it's a stupid question but can anyone tell me
> (or point me) what are closures exactly?

It's a term that comes (AFAIK) from functional programming, and
basically means the combination of
(a) an expression to be evaluated
(b) an environment in which that evaluation takes place.
A simple expression might be 2 * (x + a), though they can be very much
more complex. The environment may specify the values of some or all
variables in the expression. In this case, you might bind a to the value
2. Then the closure would define a function taking a single input x and
yielding the value 2 * (x + 2).

In C++, this effect can be achieved using function objects (i.e.,
instances of classes that define an operator() and so can be "called"
like functions). Many of the generic algorithms in C++'s standard
library can be passed a function object, for example, to define what <
means when sorting a list of objects of some arbitrary type, or what
constitutes equality when doing a search.

Unfortunately, function objects are cumbersome and difficult to use, and
mean a whole class has to be defined (and away from the place where it
is actually used) even to provide the most simple functionality. The
standard library is full of "binders" and such toys that attempt to make
manipulating such things a little easier, but even then there are some
glaring omissions (some of which are filled by the Boost library), and
they're horribly awkward to use.

In practice, I have never seen anything but the most simple use of
function objects, because trying to do anything at all complicated is
very error-prone and makes for almost indecipherable code when you need
to fix bugs or extend things later. This is a serious drawback that
kills most of the potential in the STL and related programming
techniques.

Introducing closures into C++ with a clear and concise syntax would fix
all of these problems, let us throw out a lot of clutter from the
standard library for good, and be useful in a few other circumstances to
boot. There have been several proposals in the past, some more
comprehensive than others, for such a feature, and I very much hope that
it's still one of the top language extensions being considered for the
next standard.

Cheers,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Mon, 30 Dec 2002 13:00:06 +0000 (UTC)
Raw View
scottm@toast.net ("Scott Mayo") wrote in message
news:<3e0c7376@news.toast.net>...
> "Neil Zanella":

> > BTW, what were the scoping changes for variables within for loops?

> C++ implementations have never been quite sure if, after

>     for (int iLoop = exprStuff; booleanStuff; moreStuff)
>         stmtStuff;

> iLoop still exists.

C++ implementations based on the ARM were always quite sure: iLoop
exists until the end of the enclosing block.

C++ implementations based on the C++98 standard are quite sure: iLoop
exists until the end of the last passage through the loop (lexically,
until the end of the loop).

There was a very long period (probably not yet finished) in which C++
implementations weren't sure which rule was best for their customers.

> The fact that compilers haven't agreed on this makes for a porting
> mess, especially when people relied on the value of iLoop after
> leaving the loop. The only cure has been to teach people never, ever
> ever, to declare a variable inside such an expression.

Not at all.  You teach people not to use the variable after the end of
the loop, even if their compiler allows it.  And you teach them not to
use the same variable name twice in a function.  Code written following
both of these rules works regardless of which rule the compiler
implements.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Nikolaos D. Bougalis" <nikb@webmaster.com>
Date: 30 Dec 02 18:50:47 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message
news:auk57b$ra5$1@venus.btinternet.com...
> "Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote in message
> news:31c49f0d.0212221329.672f7805@posting.google.com...
> > Here, this is very simple, very uniform, C++ snippet.  Every major
> > compiler gets it right, and this solution is hugely better than the
> > c-style solution of a macro.  It uses templates:
> >
> > template <typename T>
> > inline const T& max(const T& a, const T& b) {
> >  return (a<b)?b:a;
> > }
>
> Hugely better except it's not actually as good as this macro in C++:
> #define max(A, B) ((A) > (B) ? (A) : (B))

    Unfounded assertion.

> Your function isn't an l-value; the macro can be (for instance, one
may
wish
> to write something like:
> min(a, b) = 0;
> )

    Easily fixed...

template <typename T>
inline T& max(T& a, T&b) { return (a<b) ? b : a; }

    As a matter of fact, with C++ you can have both of those
side-by-side,
and only invoke the non-const version when you need to. Something which
you
cannot do with the macro, unless you have MAX_CONST or somesuch.

> and I think the function has issues with type conversions and
promotions
and
> all that stuff.

    What kind of issues? The function will be instantiated for every
distinct type that requires it. A different one for char, int, MyClass,
etc.

    -n


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: usenet_cpp@lehrerfamily.com (Joshua Lehrer)
Date: 30 Dec 02 19:43:35 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message news:<auk57b$ra5$1@venus.btinternet.com>...
 >
 > Your function isn't an l-value; the macro can be (for instance, one may wish
 > to write something like:
 > min(a, b) = 0;
 > )
 > and I think the function has issues with type conversions and promotions and
 > all that stuff.
 >

I know, I know.  There are many ways to make this an lvalue, or an l-
or r-value, depending on the type, support type conversions, etc...
But that wasn't the point of this thread.

joshua lehrer
factset research systems

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Matthew Watson" <Matthew_Watson@hotmail.com>
Date: 30 Dec 02 19:44:25 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message
news:auk57b$ra5$1@venus.btinternet.com...
 > Hugely better except it's not actually as good as this macro in C++:
 > #define max(A, B) ((A) > (B) ? (A) : (B))
 >
 > though I think one may need the slightly uglier
 > #define max(A, B) *((A) > (B) ? &(A) : &(B))
 > (or perhaps one only needs that in C?)
 >
 > Your function isn't an l-value; the macro can be (for instance, one may
wish
 > to write something like:
 > min(a, b) = 0;
 > )

That macro has horrible problems, not the least of which is calls such as
max( ++i, --j ).

If you really must be able to change one of the function's referands, you'd
declare the template thusly:

template <typename T>
inline T& max( T& a, T& b ) {
     return (a<b)?b:a;
}

Then you can do max(x,y) = z, although the utility of such an operation
escapes me for the moment.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: kanze@gabi-soft.de (James Kanze)
Date: 30 Dec 02 19:46:41 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message
news:<auk57b$ra5$1@venus.btinternet.com>...
> "Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote in message
> news:31c49f0d.0212221329.672f7805@posting.google.com...
> > Here, this is very simple, very uniform, C++ snippet.  Every major
> > compiler gets it right, and this solution is hugely better than the
> > c-style solution of a macro.  It uses templates:

> > template <typename T>
> > inline const T& max(const T& a, const T& b) {
> >  return (a<b)?b:a;
> > }

> Hugely better except it's not actually as good as this macro in C++:
> #define max(A, B) ((A) > (B) ? (A) : (B))

You mean in cases like max( *pi ++, 0 ) ?

I thought that this was the classical example of why macros didn't work,
and inline functions were needed.

> though I think one may need the slightly uglier
> #define max(A, B) *((A) > (B) ? &(A) : &(B))
> (or perhaps one only needs that in C?)

So that it won't even work with max( i, 0 )?  Offhand, I can't remember
ever using max or min where one of the two arguments wasn't a constant;
you want to forbid all of my uses?

> Your function isn't an l-value;

His function is always an l-value.  (I'm not convinced that this is a
good thing, however.)

> the macro can be (for instance, one may wish to write something like:
> min(a, b) = 0;

His function can be overloaded on const to allow this.  Not that I think
it a good idea, but it is certainly possible.

His function allows using a constant as an argument, which is probably
the most frequent use.

His function only evaluates each argument once, which avoids surprises
with things like max( *pi++, 10 ).

> )

> and I think the function has issues with type conversions and
> promotions and all that stuff.

The template solution has problems with mixed types.  The macro solution
may, too, with the difference that the template solution won't compile,
whereas the macro solution may just give the wrong results (e.g. if one
argument is a float, and the other a long).  Generally speaking,
implicit conversions are a bad thing, although C (and thus C++) has so
many already, banning them in one special case doesn't seem to fit into
the language very well.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: kanze@gabi-soft.de (James Kanze)
Date: 30 Dec 02 19:48:16 GMT
Raw View
"Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote in
message news:<auikr1$n27$1@venus.btinternet.com>...
> "Anton V. Tykhyy" <pardux@ally.ptf.ntu-kpi.kiev.ua> wrote...
> > Chris Newton <chrisnewton@no.junk.please.btinternet.com> wrote:
> > > Around five years ago, C++ was far ahead of the field in terms of
> > > its underlying models, its performance, its low-level control and
> > > its library. Today, many other popular general purpose languages
> > > have much more powerful libraries, either as standard, or de facto
> > > standards that you can find on places like CPAN. The performance
> > > issue is becoming ever less significant, as hardware gets faster,
> > > and other tools close the gap anyway. At the same time, the lack
> > > of high-level constructs and the safety concerns inherent in using
> > > C++ are becoming ever more serious drawbacks.

Just a point, but I don't think that C++ was ever "far ahead of the
field" in any of the ways you mention.  What has made C++ popular were
pratical issues (like a simple upward migration path from C), NOT its
underlying models.

> > could you mention what languages do you have in mind?

> To give a few examples...

> Libraries:
>   Java's has grown a lot in recent years, not all good, but often
>   useful.  Super-scripting languages like Perl and Python are rapidly
>   growing up

There are a number of third party libraries available for C++.  There
will probably be more library support for some things in the next
version of the standard as well.  With any luck, we'll stick with
existing practice this time around, and we'll end up with libraries that
actually work.  Without the overhead of having to continue to support
those that didn't, as is the case with Java.

I don't quite see the relationship with scripting languages, but then, I
don't know either Perl or Python.

> Performance:
>   Much higher-level languages like OCaml now directly rival C and C++
>   Just-in-time compilation for virtual-machine-based languages such as
>   Java makes the difference insignificant for many applications that
>   previously needed C++'s speed

Performance in general has ceased to be reason why people use C++.
Personally, I doubt that it was ever a real reason -- C++ doesn't beat
assembler, and rarely beats C.

> Higher-level constructs:
>   Perl does regexes very well

So.  So does boost::regexp.

>   ML has exemplary pattern matching and some neat polymorphic type
> features to match

For example.

>   Python (and many others) have "for each" loops to simplify iteration

You mean like std::for_each...

>   Functional languages like ML, and even languages like Java and
Python,
> provide support for closures or similar concepts

Java does NOT have support for closures, at least not in the classical
sense.  You can sort of fudge it with inner classes, but you can do
everything you can do with inner classes in C++.  In a somewhat more
verbose form, but the results are often more readable.

> Safety:
>   Eiffel supports pre- and post-conditions, etc., for defensive
> programming

True, but not as well as C++.

>   Almost no other languages in common use today encourage the use of
> unsafe constructs (raw pointers, unchecked arrays, etc.) in preference
> to safer alternatives

I don't see much in C++ encouraging the use of raw pointers.  And the
standard also allows implementations where all array accesses are
checked; you can't blame the language if people don't want correct
programs.

> In other words, I think C++ could usefully learn things from
> techniques supported by other OO languages (Java, Eiffel, etc.), from
> the ease of use of the major scripting languages (Perl, Python, etc.)
> and from the expressive power of functional languages (ML, etc.), and
> I think these things could each fit within the "character" of C++ as a
> useful extension rather than a clashing feature bolted on too late to
> work well with what's already there.

> > > On the other hand, we could see the introduction of a couple of
> > > powerful and really useful language features: closures come to
> > > mind, and perhaps

> > please, i understand it's a stupid question but can anyone tell me
> > (or point me) what are closures exactly?

> It's a term that comes (AFAIK) from functional programming, and
> basically means the combination of
> (a) an expression to be evaluated
> (b) an environment in which that evaluation takes place.
> A simple expression might be 2 * (x + a), though they can be very much
> more complex. The environment may specify the values of some or all
> variables in the expression. In this case, you might bind a to the
value
> 2. Then the closure would define a function taking a single input x
and
> yielding the value 2 * (x + 2).

The important part of closures, at least as I understand them, is the
binding of local variables.  This really only works well in a langage in
which everything is garbage collected, since the "closure" may be
returned from the function and used after the function has been exited.

This is probably less of a problem for OO languages like C++ or Java,
since it is often possible to replace the local variables with member
variables.

Beyond that, Java allows the use of local variables in local inner
classes, provided the variables are declared const -- the obvious
implementation is that they make a copy in the inner class.

A number of significant uses of closure do not require the extension of
lifetime beyond the end of the function.  For those, it would be
possible to extend C++ (of Java) to support a limited form of closure;
I've made suggestions along these lines in the past (under the name of
lambda classes).

> In C++, this effect can be achieved using function objects (i.e.,
> instances of classes that define an operator() and so can be "called"
> like functions). Many of the generic algorithms in C++'s standard
> library can be passed a function object, for example, to define what <
> means when sorting a list of objects of some arbitrary type, or what
> constitutes equality when doing a search.

> Unfortunately, function objects are cumbersome and difficult to use,
> and mean a whole class has to be defined (and away from the place
> where it is actually used) even to provide the most simple
> functionality.

The "away from the place where it is actually used" is the real
problem.  Along with, possibly, the fact that you cannot see local
variables within the class.

> The standard library is full of "binders" and such toys that attempt
> to make manipulating such things a little easier, but even then there
> are some glaring omissions (some of which are filled by the Boost
> library), and they're horribly awkward to use.

> In practice, I have never seen anything but the most simple use of
> function objects, because trying to do anything at all complicated is
> very error-prone and makes for almost indecipherable code when you
> need to fix bugs or extend things later. This is a serious drawback
> that kills most of the potential in the STL and related programming
> techniques.

Actually, my experience is the reverse.  It's when the functionality is
complex that function objects get called into play the most.  If you
have a twenty line for loop, you'll probably split off the body of the
loop into a separate function anyway, so making it a functional object
is no real difference.  It's the one or two liners that are a pain.

> Introducing closures into C++ with a clear and concise syntax would
> fix all of these problems, let us throw out a lot of clutter from the
> standard library for good, and be useful in a few other circumstances
> to boot. There have been several proposals in the past, some more
> comprehensive than others, for such a feature, and I very much hope
> that it's still one of the top language extensions being considered
> for the next standard.

True closures don't fit into the C++ model -- saying that destructors
won't be called on local variables (because their lifetime might extend
beyond the end of the function) isn't going to win support from people
using RAII.  Some sort of partial closure could (and IMHO should) be
considered, however.  I'd imagine something along the following lines:

  - At every point Within a function, there is an implicitly defined
    class with the name __local_context.  This class is semantically
    defined as containing a reference to every visible variable with
    automatic storage duration, pre-initialized to refer to that
    variable.  (I can imagine that in many, if not all cases, the actual
    implementation can do better.)  These member variables have the same
    name as the referred to variable, and are public or protected (TBD).

    Every use of this "class" generates in fact a new type.  (Or it is
    unspecified whether it generates a new type if the sets of visible
    variables are identical.)

  - The keyword lambda declares a new class derived from this class,
    with a single member, the function operator().  The syntax is:

        lambda ( parameter-list[opt] ) [base-class-decls]
        {
            function-body
        }

    The defined function is, of course:

        operator()( parameter-list[opt] )
        {
            function-body
        }

    If one of the base classes happens to have a virtual function with
    the same signature, then this function overrides it.

    I still haven't thought of a good syntax for the return type.
    Perhaps "lambda : return-type ( parameter-list[opt] ) ...".  But the
    ':' still looks too much like a base class declaration to me.

    This would allow simple predicates along the lines of:

        lambda:bool( int x ) { return x < a ; }

    where a is a local variable or a parameter.  (I think that this
    simple case can be handled by the boost class, but many more
    complicated cases can't, at least not without additional information
    from the programmer.)

  - Maybe: a keyword cleanup, which declares a new class derived from
    this class, with just a destructor, e.g.:

        cleanup { destructor-body }

    This would allow simple "one of" cases of RAII.

Anyway, this is just at the stage of being an idea for the moment.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Kevin Goodsell <goodsell@bridgernet.com>
Date: 30 Dec 02 19:49:46 GMT
Raw View
On 27 Dec 2002 03:37:59 -0500, nzanella@cs.mun.ca (Neil Zanella)
wrote:

>BTW, what were the scoping changes for variables within for loops?

I believe they are referring to this:

for (int i=0; i<WHATEVER; i++)
{

/* ... */

} /* In new C++, i goes out of scope here */

/* Back in the day, i would still exist here, as if it were declared
just before the for loop. */

-Kevin

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Will Dean" <news@nospam.demon.co.uk>
Date: 30 Dec 2002 17:40:11 -0500
Raw View
"John Nagle" <nagle@animats.com> wrote in message
news:3E0C9609.6080502@animats.com...

> MSVC still does it the old way, where the scope of "i" continues
> to the end of the "}" enclosing the entire "for" statement.

The current, released, version of MSVC (7.0) has a selection of
different ways of handling this, including the standard-compliant way.
Even 6.0 would exhibit the standard-compliant behaviour, but
unfortunately only in a mode which wasn't actually useful for anything
else.

Will
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 30 Dec 2002 17:40:53 -0500
Raw View
"Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote...
> "Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote...
> > "Hillel Y. Sims" <usenet@phatbasset.com> wrote...
> > > "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
wrote...
> > >
> > > #include <algorithm>
> > > std::stable_sort(vec.begin(), vec.end());
> >
> > My argument is simply that it would be great to see
> > these things as part of the next C++ standard, with
> > comparable power and ease of use to other languages
> > that have them today.
>
> std::stable_sort is already part of the standard.  It is easy
> to use. It has power equal to, if not greater than other
> languages.

I think my comments have lost their context somewhere.

My words quoted above referred to things like regular expressions, that
being one example of a generally useful facility not currently provided
in standard C++.

My comments about the sorting algorithms related to the conciseness with
which they can be *implemented* in some other languages, as an example
of the fact that power and simplicity are not mutually exclusive.

In both cases, I stand by my claim that progress is being made, and it
would be advantageous for such things to become part of the next C++
standard.

Regards,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 30 Dec 2002 17:41:32 -0500
Raw View
John Nagle <nagle@animats.com> wrote in message
news:<3E0C9609.6080502@animats.com>...
> Neil Zanella wrote:

> > BTW, what were the scoping changes for variables within for loops?

>     The current C++ standard requires this scoping:

>       for (int i = 0; i<100; i++)
>  { ...
>  }     // scope of i ends here

> This complicates the general rule for syntax of scopes, but it's
> convenient and helps optimizers.

How does it complicate the general rule?  (Or perhaps more precisely,
what IS the general rule?)  Consider a case like:

    if ( ... ) int i = f() ;
    //  i not in scope here...

The new rule is more logical and more coherent with the rest of the
language.

The only general rule that I have been able to deduce is that if a
declaration is enclosed in a larger statement (function definition,
compound statement, if, for, etc.), its scope ends at the end of the
enclosing statement.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Nikolaos D. Bougalis" <nikb@webmaster.com>
Date: 02 Jan 03 04:20:55 GMT
Raw View
"Andrei Alexandrescu" <andrewalex@hotmail.com> wrote in message
news:auqan3$9ifom$1@ID-14036.news.dfncis.de...
> "Nikolaos D. Bougalis" <nikb@webmaster.com> wrote in message
> news:rtoP9.108173$vb3.3961341@news2.west.cox.net...
> > > Hugely better except it's not actually as good as this macro in
C++:
> > > #define max(A, B) ((A) > (B) ? (A) : (B))
> >
> >     Unfounded assertion.
>
> Getting the virtues of the macro and getting rid of its shortcomings
is
not
> easy.
>
> http://www.moderncppdesign.com/publications/cuj-04-2001.html

    Maybe so - but in my opinion, the shortcomings outweight the
virtues. If
I want to compare apples and oranges, I'll write a function to do that.
I
won't expect to reach into my toolkit and grab one of those "universal
adaptors" and plug an orange on one side and an apple on the other.

    -n


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Nikolaos D. Bougalis" <nikb@webmaster.com>
Date: 02 Jan 03 04:21:26 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message
news:auqgk9$33n$1@venus.btinternet.com...
> "Nikolaos D. Bougalis" <nikb@webmaster.com> wrote in message
> news:rtoP9.108173$vb3.3961341@news2.west.cox.net...
> > "DrPizza" <drpizza@anti-flash.co.uk> wrote in message
> >     Unfounded assertion.
> It's nothing of the sort.
>
> The template function doesn't work here:
> double a, b;
> ...
> min(a, b) += 2;
> int c, d;
> ...
> int smallest = min(c, d);
>
> The macro does.

    The template shown did not work. I provided one that does, and
instead
of acknowledging that my version worked for the situation you provided,
you
change things around. Onwards...

> Yes, the macro has the problem with side-effects.  But so what?  We
all
*know*
> about that problem and can consequentially *avoid* that problem.

    Only if you know that "max" and "min" are macros. If you happen to
forget, you'll be chasing "phantoms."

> > > Your function isn't an l-value; the macro can be (for instance,
one
> > may
> > wish
> > > to write something like:
> > > min(a, b) = 0;
> > > )
> >
> >     Easily fixed...
> >
> > template <typename T>
> > inline T& max(T& a, T&b) { return (a<b) ? b : a; }
> Still doesn't work properly with mixed types.

    I'm sure you'd really like to call "max" with one int and one float
(or
an unsigned int, or whatever else); but comparing apples and oranges
should
be left to a function that knows how to compare them. Not a generic
version.

    Let's how does your macro handle this case of mixed types you like
so
much...

#include <iostream>

#define max(a, b) ((a) > (b)) ? a : b

int main(int argc, char **argv)
{
    int i = 7378;
    double d = 0.7378;
    max(i, d) = 0.7319;
    std::cout << "i=" << i << std::endl;
    std::cout << "d=" << d << std::endl;
    return 0;
}

    Here's how:

i=7378
d=0.7378


> >     What kind of issues? The function will be instantiated for every
> > distinct type that requires it. A different one for char, int,
MyClass,
> > etc.
> What kind of issues?  The macro works with different types -- it
performs
type
> promotions and conversions as necessary.  The function template...
doesn't.

    The macro only *appears* to work with different types. In reality,
it's
undefined behavior, and it's asking for trouble. Look at the example
again... Apples and oranges.

    -n


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Nikolaos D. Bougalis" <nikb@webmaster.com>
Date: 02 Jan 03 04:21:49 GMT
Raw View
"DrPizza" <drpizza@anti-flash.co.uk> wrote in message
news:auqgnb$37e$1@venus.btinternet.com...
> "Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote in message
> news:31c49f0d.0212291358.4255a123@posting.google.com...
> > I know, I know.  There are many ways to make this an lvalue, or an
l-
> > or r-value, depending on the type, support type conversions, etc...
> > But that wasn't the point of this thread.
>
> The point is that I disagree with the claim that that function is
superior
to
> the macro.  It isn't.  It gives function semantics -- no macro double
> evaluation or anything like that -- but sacrifices other capabilities
--
> things like conversions and promotions and l-valueness.

    We've been over this. The template function macro can be an l-value.
It
just can't be an l-value in the way you want it to be -- to be a "short
int"
l-value some of the time, and an "int" value the rest.

    -n


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 02 Jan 03 04:22:50 GMT
Raw View
In article <auqh6n$3ts$1@venus.btinternet.com>, DrPizza
<drpizza@anti-flash.co.uk> writes
>Whether that's wrong or not is a matter of opinion.  I don't agree that
it is.
> I certainly don't think that the macro's behaviour in this situation
is
>wrong:
>int a;
>short int b;
>...
>max(a, b);
>
>But the template will fail.

Not if correctly written:

max<int>(a, b);

And it was the need to make the simple max template work that caused the

change in C++ circa 1993 to allow explicit specification of function
template parameters.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: scottm@toast.net ("Scott Mayo")
Date: Thu, 2 Jan 2003 06:29:43 +0000 (UTC)
Raw View
"James Kanze" <kanze@gabi-soft.de>:
> scottm@toast.net ("Scott Mayo"):

> > C++ implementations have never been quite sure if, after

> >     for (int iLoop = exprStuff; booleanStuff; moreStuff)
> >         stmtStuff;

> > iLoop still exists.

> C++ implementations based on the ARM were always quite sure: iLoop
> exists until the end of the enclosing block.
> C++ implementations based on the C++98 standard are quite sure: iLoop
> exists until the end of the last passage through the loop (lexically,
> until the end of the loop).

> > The fact that compilers haven't agreed on this makes for a porting
> > mess, especially when people relied on the value of iLoop after
> > leaving the loop. The only cure has been to teach people never, ever
> > ever, to declare a variable inside such an expression.

> Not at all.  You teach people not to use the variable after the end of
> the loop, even if their compiler allows it.

Possible, but hard. It's not too uncommon for the value of the
controlling variable to be very useful after the loop exits, and
plenty of people do primary implementation on compilers
that leave the value available. Someone else gets to do the
port, and then you have thousand lines of code that
need last minute tweaking. I've found it easier to try to
convince people not to declare such variables at all. This
isn't too unreasonable; it's sort of a syntax wart in the first
place - if it's defined *outside* the curly braces, why did
the scope end *inside* the curly braces?

It's always interesting when people speak about making
changes to a language, as if having to go back into working
code is simply a minor price of using an evolving language.
Maybe for some folk: but for some shops, the prospect of
touching working code is nearly unthinkable, and having to
touch it unexpectedly, because some other group upgraded
the compiler and now six language rules have changed, is
nearly cause for bloodshed. If I could plead for a
universal compiler option (admittedly, this isn't something the
standard can mandate), it would be "I don't care what
version of the language you now implement, please treat
my code as if it was 1996 again and nothing has changed."




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nzanella@cs.mun.ca (Neil Zanella)
Date: 27 Dec 2002 03:37:59 -0500
Raw View
usenet_cpp@lehrerfamily.com (Joshua Lehrer) wrote:

> Here, this is very simple, very uniform, C++ snippet.  Every major
> compiler gets it right, and this solution is hugely better than the
> c-style solution of a macro.  It uses templates:
>
> template <typename T>
> inline const T& max(const T& a, const T& b) {
>  return (a<b)?b:a;
> }

Much easier using STL, which is now also part of standard C++:

#include <algorithm>

std::max(a, b); // :-)

> Now, that said, sometimes the language needs to break old code, like
> with the 'for' loop.  Our compiler vendor supplied us a switch, to let
> us select whether to use the old or new standard.  This helped us in
> fixing up our code, and gave us the option of never fixing our code.
> As you would probably agree, we decided it was better to fix our code,
> and remain standards compliant, than rely on a non-standard, not
> portable switch.

g++ has a -Wno-deprecated switch for such purposes.

BTW, what were the scoping changes for variables within for loops?

Thanks,

Neil
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: scottm@toast.net ("Scott Mayo")
Date: Fri, 27 Dec 2002 20:56:28 +0000 (UTC)
Raw View
"Neil Zanella":

> BTW, what were the scoping changes for variables within for loops?

C++ implementations have never been quite sure if, after

    for (int iLoop = exprStuff; booleanStuff; moreStuff)
        stmtStuff;

iLoop still exists. The fact that compilers haven't agreed on this makes for
a porting mess, especially when people relied on the value of iLoop after
leaving the loop. The only cure has been to teach people never, ever
ever, to declare a variable inside such an expression.

"Don't use the bad features of a language." Words to live by.



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: usenet_cpp@lehrerfamily.com (Joshua Lehrer)
Date: 28 Dec 02 12:28:58 GMT
Raw View
"Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote in message news:<au7smr$mmd$1@venus.btinternet.com>...
 > "Hillel Y. Sims" <usenet@phatbasset.com> wrote...
 > > "Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote...
 > >
 > > #include <algorithm>
 > > std::stable_sort(vec.begin(), vec.end());
 > >
 > My argument is simply that it
 > would be great to see these things as part of the next C++ standard,
 > with comparable power and ease of use to other languages that have them
 > today.
 >

std::stable_sort is already part of the standard.  It is easy to use.
It has power equal to, if not greater than other languages.

joshua lehrer
factset research systems

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Ken Alverson" <Ken@Alverson.net>
Date: 28 Dec 02 12:29:27 GMT
Raw View
"Matthew Watson" <Matthew_Watson@hotmail.com> wrote in message
news:8HAO9.2389$hG1.17807474@news-text.cableinet.net...
> "Neil Zanella" <nzanella@cs.mun.ca> wrote in message
> news:b68d2f19.0212222026.4f6e8b0a@posting.google.com...
>
> >What high level constructs? Show me one other language that has
> templates!
>
> Eiffel has things that can be used very like templates.

As does Ada.  Though both are genericity constructs and can't do some of
the wackier meta-programming tricks people have managed to come up with
using templates.

Ken



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: John Nagle <nagle@animats.com>
Date: 28 Dec 02 12:33:43 GMT
Raw View
Neil Zanella wrote:

> BTW, what were the scoping changes for variables within for loops?


    The current C++ standard requires this scoping:

      for (int i = 0; i<100; i++)
 { ...
 }     // scope of i ends here

This complicates the general rule for syntax of scopes, but it's
convenient and helps optimizers.

MSVC still does it the old way, where the scope of "i" continues
to the end of the "}" enclosing the entire "for" statement.

    John Nagle
    Animats

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Hyman Rosen <hyrosen@mail.com>
Date: 26 Dec 02 11:55:05 GMT
Raw View
Neil Zanella wrote:
> What high level constructs? Show me one other language that has
> templates! Safety concerns? That's the price of efficiency. What
 > other language supports both imperative and object-oriented
 > constructs? What other language supports functional programming
 > and low level memory management.

I know you think your questions are rhetorical, but actually, the
answer to all of them is Ada.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Anton V. Tykhyy" <pardux@ally.ptf.ntu-kpi.kiev.ua>
Date: 26 Dec 02 12:25:03 GMT
Raw View
In comp.lang.c++.moderated Chris Newton <chrisnewton@no.junk.please.btinternet.com> wrote:
 > The biggest concern I have with C++ at the moment is that it's being
 > driven by a really heavyweight process. If there's one thing that we've
 > learned in software development over the past few years, it's that
 > heavyweight processes usually suck. The community processes and
 > benevolent dictatorships associated with some other popular languages
 > may not produce quite the same quality, but they evolve things that are
 > *useful enough* many times faster, and they are learning from their
 > mistakes.
  agreed

 > Around five years ago, C++ was far ahead of the field in terms of its
 > underlying models, its performance, its low-level control and its
 > library. Today, many other popular general purpose languages have much
 > more powerful libraries, either as standard, or de facto standards that
 > you can find on places like CPAN. The performance issue is becoming ever
 > less significant, as hardware gets faster, and other tools close the gap
 > anyway. At the same time, the lack of high-level constructs and the
 > safety concerns inherent in using C++ are becoming ever more serious
 > drawbacks.
  could you mention what languages do you have in mind?

 > On the other hand, we could see the introduction of a couple of powerful
 > and really useful language features: closures come to mind, and perhaps
  please, i understand it's a stupid question but can anyone tell me
  (or point me) what are closures exactly?

[skip]

 > And of course, to maintain credibility in the face of cleaner languages,
 > C++ needs some tidying up, and the new standard needs presenting using
 > techniques from this millenium: a well-linked web site in plain English
 > beats ~1,000 pages of closely written tech-speak any day.
  yup.

[skip]

Regards, pardux

=== ICQ#38457991 === Origin: Delirium canis (c) ===

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 26 Dec 2002 10:56:37 -0500
Raw View
"Hyman Rosen" <hyrosen@mail.com> wrote...
> Chris Newton wrote:
> > The biggest concern I have with C++ at the moment is
> > that it's being driven by a really heavyweight process.
>
> C++ does not need to be "driven" at all. It is an ANSI/ISO
> standard language, and generally speaking, it's shape is
> fixed and final.

I hope you mean that C++ 98 is pretty much fixed and final (and I agree
with that sentiment).

> Anything more drastic will require the invention of a new language.

But people are doing more with C++ all the time. There are a few
compiler-specific extensions that are widely used, and many new and
powerful libraries arriving all the time. Clearly it is in everyone's
interests for there to be a "new version" of C++ at some point, just as
there has been with every other language I can recall that has been
successful in the long term. I think the "new language" you mention is
C++0x.

Regards,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 26 Dec 2002 10:56:56 -0500
Raw View
"Hillel Y. Sims" <usenet@phatbasset.com> wrote...
> "Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote...
> > Those who've seen a merge sort written in half a dozen lines
> > of functional code, or who've seen five lines of Perl regex'ing
> > do more than 50 lines could in today's standard C++, will
> > understand what I'm getting at here.
>
> #include <algorithm>
> std::stable_sort(vec.begin(), vec.end());
>
> 2 lines ;-)

I appreciate that you're probably writing in jest, but still, that's
using a sort, not an implementation of the algorithm. I can do the
former in two *words* in several other languages: sort vec. :-)

> (Also, check out the boost.regex package, it's quite nice.)

It certainly has a lot of potential, as does the package that's being
developed by some of the folks at Microsoft (apologies for forgetting
who exactly mentioned it previously). My argument is simply that it
would be great to see these things as part of the next C++ standard,
with comparable power and ease of use to other languages that have them
today.

Cheers,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 26 Dec 2002 12:56:11 -0500
Raw View
Hyman Rosen <hyrosen@mail.com> wrote in message
news:<8KwN9.67413$_S2.64338@nwrddc01.gnilink.net>...
> Chris Newton wrote:
>  > The biggest concern I have with C++ at the moment is that it's
>  > being driven by a really heavyweight process.

> C++ does not need to be "driven" at all. It is an ANSI/ISO standard
> language, and generally speaking, it's shape is fixed and final. We'll
> have some slight corrections to the standard to fix oversights, and
> for the most part, that will be it. There's some tinkering that will
> happen down the road, but the changes will be minor, not unlike the
> latest changes to C. This is it folks. This is all you get. Anything
> more drastic will require the invention of a new language.

I'm not sure that everyone considers the changes in C minor.

More to the point, how much the language changes is entirely up to the
committee; modern Fortran doesn't begin to resemble the Fortran I
learned thirty years ago, for example.

The scenario I expect is considerable extention in the libraries, but
very few changes in the language.  But I don't have a cristal ball, so
I'm just guessing.

> I suggest that those who are interested begin working. The new
> languages could tentatively be called "C++ with Aspects", or "C++ with
> Reflection", or "C++ with Improved Syntax", just like C++ began as "C
> with Classes".

The new language will be called C++.  The same way that the new language
invented by the committee last time around was called C++.  And just as
the other language I mentionned is still called Fortran.  (About the
only freedom the committee doesn't have is to change the name.)

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Maciej Sinilo <msinilo@NOSPAM.kki.net.pl> (dot)
Date: 26 Dec 2002 12:56:46 -0500
Raw View
In article from 23 Dec 02 13:59:08 GMT Hyman Rosen says...
> Chris Newton wrote:
>  > The biggest concern I have with C++ at the moment is that it's being
>  > driven by a really heavyweight process.
>
> C++ does not need to be "driven" at all. It is an ANSI/ISO standard
> language, and generally speaking, it's shape is fixed and final. We'll
> have some slight corrections to the standard to fix oversights, and
> for the most part, that will be it. There's some tinkering that will
> happen down the road, but the changes will be minor, not unlike the
> latest changes to C. This is it folks. This is all you get. Anything
> more drastic will require the invention of a new language.
>
> I suggest that those who are interested begin working. The new languages
> could tentatively be called "C++ with Aspects", or "C++ with Reflection",
> or "C++ with Improved Syntax", just like C++ began as "C with Classes".
Some people already tried this -- an example may be D language
(http://www.digitalmars.com/d/), not to mention C#.

--
Maciej Sinilo
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Matthew Watson <Matthew_Watson@hotmail.com>
Date: 26 Dec 2002 12:57:16 -0500
Raw View
"Neil Zanella" <nzanella@cs.mun.ca> wrote in message
news:b68d2f19.0212222026.4f6e8b0a@posting.google.com...

>What high level constructs? Show me one other language that has
templates!

Eiffel has things that can be used very like templates.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 26 Dec 2002 12:57:42 -0500
Raw View
"Joshua Lehrer" <usenet_cpp@lehrerfamily.com> wrote...
> "Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote...
> > <soapbox>
> > To all those responsible for the standard: I respectfully submit
> > that it doesn't matter a damn if you break existing code a bit
> > while tidying up templates, exceptions, overload resolution and
> > such. [...] There is no value in maintaining backward compatibility
> > with a ten-year-old standard behaviour that was never widely
> > adopted.
> > </soapbox>
>
> I can't disagree with you more.  I work on a project with 4.5 million
> lines of code, not including the compiler supplied libraries
> (platform, std).  Years ago, the language changed with respect to the
> lifetime of variables declared inside the initialization of a for
> loop.  This created a massive amount of work for us.

Sorry, I wasn't clear. I'm not advocating arbitrary changes in
behaviour, or anything as significant as changing the scope of a
commonly used construction. As I mentioned, I work on widely ported code
myself, so I'm painfully aware of the problems that little differences
can cause.

I've seen a lot of arguments in favour of such-and-such a simplification
of C++ discussed on-line, many of which had real merit, but were felt by
some to be unworkable because they changed past behaviour in some subtle
way. My point is that if you're discussing a feature that is almost
impossible to get right reliably anyway (witness any number of past
threads on csc++ or clc++m about some fine point that even half the
experts present miss at first) then chances are almost no-one is using
it, and many of those who are only get it right inadvertently, so it's
an accident waiting to happen. IOWs, backward compatibility isn't much
of an issue, and is given a disproportionately high significance when
considering a language amendment that would be much more widely useful.

Regards,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Chris Newton" <chrisnewton@no.junk.please.btinternet.com>
Date: 22 Dec 2002 07:54:25 -0500
Raw View
"Grex" <tiff_master@yahoo.com> wrote...
> Has C++ become a dying language?
> What is the future of C++?

I very much doubt C++ is about to die. The installed base is too big,
and too many other things are fundamentally tied to it. Its popularity
and usefulness compared to other tools available may well diminish,
though.

The biggest concern I have with C++ at the moment is that it's being
driven by a really heavyweight process. If there's one thing that we've
learned in software development over the past few years, it's that
heavyweight processes usually suck. The community processes and
benevolent dictatorships associated with some other popular languages
may not produce quite the same quality, but they evolve things that are
*useful enough* many times faster, and they are learning from their
mistakes.

Around five years ago, C++ was far ahead of the field in terms of its
underlying models, its performance, its low-level control and its
library. Today, many other popular general purpose languages have much
more powerful libraries, either as standard, or de facto standards that
you can find on places like CPAN. The performance issue is becoming ever
less significant, as hardware gets faster, and other tools close the gap
anyway. At the same time, the lack of high-level constructs and the
safety concerns inherent in using C++ are becoming ever more serious
drawbacks.

I think C++ will be in one of two places in another five years, around
the time of the next standard becoming relevant.

On the one hand, the new standard could consist of 5,436 minor
corrections to issues that only three people cared about anyway. The
"ambitious" library extensions could amount to some smart pointers and
expression templates that every other general purpose language in
popular use will have taken for granted for years. The standards
committee and five regulars on clc++m would be very proud, but most of
the programming world would continue their ignorance of the existence of
a C++ standard.

On the other hand, we could see the introduction of a couple of powerful
and really useful language features: closures come to mind, and perhaps
replacing switch and enums with a serious pattern matching system, which
is a very useful programming technique that IMHO could fit well into the
structure of C++. The standard library could provide some much-needed
missing features (smart pointers, regexes, etc.). The library could also
provide a good framework for things like GUI and console I/O, serial and
Internet comms, database access and filesystems. I don't expect a full
implementation that supports everything in the universe, but an approach
like the STL-based parts we have now would be very helpful IMHO: provide
the really common stuff as standard, and design it for extensibility.

The catch is that with a process as slow-moving as the current one seems
to be, I don't see how those working on the standard have a hope of
reaching the second vision in spite of their superb efforts.

And of course, to maintain credibility in the face of cleaner languages,
C++ needs some tidying up, and the new standard needs presenting using
techniques from this millenium: a well-linked web site in plain English
beats ~1,000 pages of closely written tech-speak any day.

<soapbox>
To all those responsible for the standard: I respectfully submit that it
doesn't matter a damn if you break existing code a bit while tidying up
templates, exceptions, overload resolution and such. The current rules
are so absurdly complicated that even if one person has been clever
enough to write something that works, it is almost necessarily
unmaintainable, write-only code that has no place in a properly
engineered project.

I work on an application that ships on something like 15 diverse
platforms, and we *expect* that a few things will need fixing up in
supporting a new compiler. But right now, we can't use a lot of the most
useful language features, because the rules are so complex that there's
no uniformity even in how compilers get them wrong.

There is no value in maintaining backward compatibility with a
ten-year-old standard behaviour that was never widely adopted.
</soapbox>

However, even if the language remains as it is today, I don't like
things like Java or C# will ever kill it. They have too many of the same
weaknesses, a few more of their own, and not enough compensating good
points to make them useful in as diverse a range of applications as C++
has found.

If anything is going to come along in future and take over from these
languages, I think it will be a new and quite radically different
language, not another take on C syntax with OO on top. Look for a
language that is theoretically sound in its underlying models for OO,
exceptions, multithreading and such. Also look for a language with a
much simpler formal grammar, so that it's not only easier to read and
write, but also much more amenable to generation and processing by
tools. Those who've seen a merge sort written in half a dozen lines of
functional code, or who've seen five lines of Perl regex'ing do more
than 50 lines could in today's standard C++, will understand what I'm
getting at here.

Cheers,
Chris
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: usenet_cpp@lehrerfamily.com (Joshua Lehrer)
Date: 23 Dec 02 07:20:29 GMT
Raw View
"Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote in
message news:<atvqu4$iof$1@knossos.btinternet.com>...
> <soapbox>
> To all those responsible for the standard: I respectfully submit that
it
> doesn't matter a damn if you break existing code a bit while tidying
up
> templates, exceptions, overload resolution and such. The current rules
> are so absurdly complicated that even if one person has been clever
> enough to write something that works, it is almost necessarily
> unmaintainable, write-only code that has no place in a properly
> engineered project.
>
> I work on an application that ships on something like 15 diverse
> platforms, and we *expect* that a few things will need fixing up in
> supporting a new compiler. But right now, we can't use a lot of the
most
> useful language features, because the rules are so complex that
there's
> no uniformity even in how compilers get them wrong.
>
> There is no value in maintaining backward compatibility with a
> ten-year-old standard behaviour that was never widely adopted.
> </soapbox>

I can't disagree with you more.  I work on a project with 4.5 million
lines of code, not including the compiler supplied libraries
(platform, std).  Years ago, the language changed with respect to the
lifetime of variables declared inside the initialization of a for
loop.  This created a massive amount of work for us.  Not only did we
have to go through and "correct" every single file, we needed to find
ways to test every file to make sure that our fix-up was correct.
Unit tests could only test so much of the system.  This costs our
engineering base a massive amount of time which we could have spent
developing new software, and hence, making money.

I submit that our code is properly engineered, and we make use of such
things as templates, exceptions, and overloads.  Our code is mission
critical to our clients, and has a very high reliability.  What rules
do you find so absurd?  Sure, there are a few tricky areas, but I can
honestly say that rarely do I find myself in one of those areas.  What
are the "most useful language features" with rules "so complex that
there's no uniformity"?

Here, this is very simple, very uniform, C++ snippet.  Every major
compiler gets it right, and this solution is hugely better than the
c-style solution of a macro.  It uses templates:

template <typename T>
inline const T& max(const T& a, const T& b) {
 return (a<b)?b:a;
}

Keeping things backwards compatible is one of the things that makes
C++ so powerful.  With relatively few exceptions, we are guaranteed
that our code will always work in the future, even as new
functionality is added to the language.

Now, that said, sometimes the language needs to break old code, like
with the 'for' loop.  Our compiler vendor supplied us a switch, to let
us select whether to use the old or new standard.  This helped us in
fixing up our code, and gave us the option of never fixing our code.
As you would probably agree, we decided it was better to fix our code,
and remain standards compliant, than rely on a non-standard, not
portable switch.

joshua lehrer
factset research systems

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Hillel Y. Sims" <usenet@phatbasset.com>
Date: 23 Dec 02 07:24:17 GMT
Raw View
"Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote in
message
news:atvqu4$iof$1@knossos.btinternet.com...
[..]
> Those who've seen a merge sort written in half a dozen lines of
> functional code, or who've seen five lines of Perl regex'ing do more
> than 50 lines could in today's standard C++, will understand what I'm
> getting at here.
>

#include <algorithm>
std::stable_sort(vec.begin(), vec.end());

2 lines ;-)

(Also, check out the boost.regex package, it's quite nice.)

hys

--
(c) 2002 Hillel Y. Sims
hsims AT factset.com


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Hyman Rosen <hyrosen@mail.com>
Date: 23 Dec 02 13:59:08 GMT
Raw View
Chris Newton wrote:
 > The biggest concern I have with C++ at the moment is that it's being
 > driven by a really heavyweight process.

C++ does not need to be "driven" at all. It is an ANSI/ISO standard
language, and generally speaking, it's shape is fixed and final. We'll
have some slight corrections to the standard to fix oversights, and
for the most part, that will be it. There's some tinkering that will
happen down the road, but the changes will be minor, not unlike the
latest changes to C. This is it folks. This is all you get. Anything
more drastic will require the invention of a new language.

I suggest that those who are interested begin working. The new languages
could tentatively be called "C++ with Aspects", or "C++ with Reflection",
or "C++ with Improved Syntax", just like C++ began as "C with Classes".

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nzanella@cs.mun.ca (Neil Zanella)
Date: 23 Dec 02 13:58:31 GMT
Raw View
"Chris Newton" <chrisnewton@no.junk.please.btinternet.com> wrote in message news:<atvqu4$iof$1@knossos.btinternet.com>...
 > "Grex" <tiff_master@yahoo.com> wrote...
 > > Has C++ become a dying language?
 > > What is the future of C++?
 >
 > I very much doubt C++ is about to die. The installed base is too big,
 > and too many other things are fundamentally tied to it. Its popularity
 > and usefulness compared to other tools available may well diminish,
 > though.

C++ has way too many strengths compared to other languages.
Most useful tools so to speak are written in C++ in the first place.

 > *useful enough* many times faster, and they are learning from their
 > mistakes.

Several developers choose C++ because they enjoy its speed an
flexibility.
Consider that C++ fast (perhaps only C beats its in this respect but
compilers are getting better by the day). Also consider that not one
but several APIs
have been written in C and C++ supporting GUI development, networking,
numerical algorithms, embedded programming, etc...

 > Around five years ago, C++ was far ahead of the field in terms of its
 > underlying models, its performance, its low-level control and its
 > library. Today, many other popular general purpose languages have much
 > more powerful libraries, either as standard, or de facto standards that
 > you can find on places like CPAN.

Everyone knows perl is too slow for serious applications.

 > The performance issue is becoming ever
 > less significant, as hardware gets faster, and other tools close the gap
 > anyway. At the same time, the lack of high-level constructs and the
 > safety concerns inherent in using C++ are becoming ever more serious
 > drawbacks.

What high level constructs? Show me one other language that has
templates!
Safety concerns? That's the price of efficiency. Such concerns aren't
really
concerns when you know what you're doing. What other language supports
both
imperative and object-oriented constructs? What other language
supports
functional programming and low level memory management. Yeah, let's
see
someone write an operating system in perl.

 > I think C++ will be in one of two places in another five years, around
 > the time of the next standard becoming relevant.

I expect that the popularity of C++ will increase. C and C++ have been
around
for a long time now and they're here to stay. A lot of work has been
done in
these two programming languages: they are very well suited for serious
tasks.

 > On the one hand, the new standard could consist of 5,436 minor
 > corrections to issues that only three people cared about anyway.

Does Java even have a standard? I think the fact that the standard
aims at
being comprehensive and succint is a sign that C++ is a more mature
language
than others.

 > The "ambitious" library extensions could amount to some smart pointers and
 > expression templates that every other general purpose language in
 > popular use will have taken for granted for years.

What more do you need? C++ supports iterators, automatic pointers, and
provides
you with a framework to construct classes that use smart pointers. No
matter
what the need may be, an efficient library can be written in C++ to
support it.

 > The standards
 > committee and five regulars on clc++m would be very proud, but most of
 > the programming world would continue their ignorance of the existence of
 > a C++ standard.

There is no evidence of your statement. Every book that teaches about
C++
mentiones the standard, so unless you learned C++ in 1 evening on the
net
then you would know about the standard, and you would refer to it when
you need to find out how something works. Also, the standard makes
programs more portable, which is extremely important for cross
platform development. The standard is also important because
it documents how C++ works, and in large projects you really
do need to know this well.

Personally I am sick of Java's undocumented features. Even those
features
that are documented don't always work as they should. Also, C++ is
more
portable than Java because C++ compilers are more mature and are still
getting better by the day.

 > On the other hand, we could see the introduction of a couple of powerful
 > and really useful language features: closures come to mind, and perhaps
 > replacing switch and enums with a serious pattern matching system, which
 > is a very useful programming technique that IMHO could fit well into the
 > structure of C++. The standard library could provide some much-needed
 > missing features (smart pointers, regexes, etc.). The library could also
 > provide a good framework for things like GUI and console I/O, serial and
 > Internet comms, database access and filesystems. I don't expect a full
 > implementation that supports everything in the universe, but an approach
 > like the STL-based parts we have now would be very helpful IMHO: provide
 > the really common stuff as standard, and design it for extensibility.
 >
 > The catch is that with a process as slow-moving as the current one seems
 > to be, I don't see how those working on the standard have a hope of
 > reaching the second vision in spite of their superb efforts.

Tell us, where did you "see" this process? New versions of compilers
and
APIs as well as new APIs are released several times a year. On the
other
hand this is not the case with Java APIs. In Java, you cannot do
anything
that the JDK does not let you do. With C++ on the other hand, you can
do
just about anything.

As far as I'm concerned the standard is very mature. If you're
expecting
the standard to incorporate a GUI framework then forget it, it won't
happen.
That's a bonus though, becuase there are already many out there and we
can
learn a lot from their software architecture.

 > And of course, to maintain credibility in the face of cleaner languages,
 > C++ needs some tidying up, and the new standard needs presenting using
 > techniques from this millenium: a well-linked web site in plain English
 > beats ~1,000 pages of closely written tech-speak any day.

Nothing stops you from buying some good textbooks and the standard.
Who knows, you may be looking into writing a very simple application
that does not need any of C++. In that case I would recommend
switching
to Java.

 > <soapbox>
 > To all those responsible for the standard: I respectfully submit that it
 > doesn't matter a damn if you break existing code a bit while tidying up
 > templates, exceptions, overload resolution and such. The current rules
 > are so absurdly complicated that even if one person has been clever
 > enough to write something that works, it is almost necessarily
 > unmaintainable, write-only code that has no place in a properly
 > engineered project.

If you can do better, write your own language and call it
simplifiedc++
or something similar, but be warned, designing a good language may
require
substantial amount of time and effort, and there will still be
pitfalls.

 > I work on an application that ships on something like 15 diverse
 > platforms, and we *expect* that a few things will need fixing up in
 > supporting a new compiler. But right now, we can't use a lot of the most
 > useful language features, because the rules are so complex that there's
 > no uniformity even in how compilers get them wrong.

 > There is no value in maintaining backward compatibility with a
 > ten-year-old standard behaviour that was never widely adopted.

Such as? One must be patient. Haste always leads to catastrophic
consequences in the long run. I don't expect that Java will stay
around for as long as C++. Java is already a mess now, imagine
what it will be like in several years from now. At least C++
committee tries not to make a mess of things by being cautious.

 > However, even if the language remains as it is today, I don't like
 > things like Java or C# will ever kill it. They have too many of the same
 > weaknesses, a few more of their own, and not enough compensating good
 > points to make them useful in as diverse a range of applications as C++
 > has found.

Once again, if you can come up with a language that suits you better,
there's flex and bison and you can use them to write your own
compiler.
Let us know how it turns out.

 > If anything is going to come along in future and take over from these
 > languages, I think it will be a new and quite radically different
 > language, not another take on C syntax with OO on top. Look for a
 > language that is theoretically sound in its underlying models for OO,
 > exceptions, multithreading and such. Also look for a language with a
 > much simpler formal grammar, so that it's not only easier to read and
 > write, but also much more amenable to generation and processing by
 > tools. Those who've seen a merge sort written in half a dozen lines of
 > functional code, or who've seen five lines of Perl regex'ing do more
 > than 50 lines could in today's standard C++, will understand what I'm
 > getting at here.

I invite you to post your perl examples. regexing can be done with
flex
which works with both C and C++ and has been around for longer than
perl.

Regards,

Neil

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]