Re: [boost] Re: class proposal

2003-04-24 Thread Noel Yap
Justin M. Lewis wrote:
 
 I agree.  I probably wouldn't have cared for this myself, had I never seen
 the code I'm working on now.  I mean, normally I work pretty independently.
 But, now I'm stuck with the job of maintaining code that's been around
 forever, has been ported several times to a couple different projects.  In
 places you can see how the code evolved over time.  But, the point is, it's
 becoming a mess.  And, we're at a point where we're almost starting
 everything again, but this time from scratch.  Knowing that the code will
 probably live for years, and be ported several times, and be maintained by
 many different people over its life, it seems best to me to start a project
 like that off with clarity being the #1 priority.  And, at least in my
 experience, people seem to think that functions that pass by reference
 changing the values of params is a problem, it's hard to track.  But, most
 C++ people I know prefer to avoid pointer use.  So, that really only leaves
 the one option that makes the intent explicit and clear, every time.
 
 So, I really can't give a long term analysis of how well this method works,
 if it becomes a hassle to maintain it, or not.  But, as it is, it seems more
 clear to me than anything else.  At the cost of 3 or 6 letters at the
 invocation point, you can make the operation of the function clear.
 
 func(out(x));
 
 It seems pretty simple and straight forward to me.

I believe all that will be accomplished is that these objects will
become ubiquitous in the system just as references are.  For example,
code like the following will start to pop up:

  void f( in_out int  is_not_changed_ )
  {
// use is_not_changed_, but don't change it
  }

IMHO, why not just state from the start to ban in/out parameters?  In
its place, use parameters for in and return for out.  An in/out can
done via a smart pointer.

Noel
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-24 Thread John Torjo

   void f( in_out int  is_not_changed_ )
   {
 // use is_not_changed_, but don't change it
   }

I think there would be a much bigger problem (code inside the function would
change).

Just consider

void add_char( std::string  str, char ch)
{ str += ch; }

Now, if we change it so be in_out, we'll have to use a .ref()-like function.


void add_char( in_outstd::string str, char ch)
{ str.ref() += ch; }

Of course, this is a simple example, but it illustrates the point.
The code would become obfuscated.

Frankly, I donot like it.

Best,
John


___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-24 Thread Justin M. Lewis

- Original Message -
From: Noel Yap [EMAIL PROTECTED]
To: Boost mailing list [EMAIL PROTECTED]
Sent: Thursday, April 24, 2003 4:13 AM
Subject: Re: [boost] Re: class proposal


 Justin M. Lewis wrote:
 
  in/out seems to be used fairly commonly in COM.  I'm not sure I have any
  great examples off the top of my head, but I know they're commonly used.

 I'm not a COM person, but I believe it's written in C.  If so, then you
 are correct that in/out parameters are more needed since noone would
 want to create a struct for each multiple return type.

 OTOH, C++ has templates to deal with this situation (ie boost::tuple)
 so, qualifying my previous statement, in C++ I still see no need for
 in/out parameters.



I think most COM objects are written in C++.  I should have been more
specific here, if you're looking at ActiveX objects, in/out params are used
all over the place.  Each function returns an HRESULT, iirc, any data you
want returned has to be returned in a param.


  And using pointers is part of what we're trying to avoid here.  Like I
said,
  I avoid using pointers whenever possible at this point.

 I'm a little confused.  Either you pass in the entire object or you pass
 in a pointer (even if it's wrapped in another class).  How is this new
 class supposed to be implemented?


And, it's not either pass in a whole object or pass in a pointer, you're
forgetting references.  This new class takes in a reference, and stores
that.  It doesn't do anything with pointers.

  And, again, the real intent here is to insure clarity at the point of
  invocation.  In my case I'm looking at 100's of thousands of lines of
code,
  written over the past 8 years.  It's tiresome trying to chase down where
  values COULD have changed.  In this setup you KNOW exactly what calls
are
  changing parameter values, and it's enforced.  As long as the library
calls
  use the c_out and c_in_out classes people using the library are forced
to
  conform to the format.  So, 8 years, and a few million lines of code
later,
  no one will wonder what might cause a variable they're tracking to
change
  values.

 I think if parameters are used for in parameters only and return values
 are used for out parameters only, the same thing is achieved.  For
 example,

   inOutValue = square( inOutValue );

 vs (using an extension for generality):

   square( c_in_out typeof( inOutValue ) ( inOutValue ) );

 Noel


And, again, returning an object isn't always desirable, you could be copying
large objects for no reason.  You may not call a copy constructor, but an =
operator is being used.

___
 Unsubscribe  other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-24 Thread Justin M. Lewis
I diagree with this.  The code I've written using this looks more like

void add_char( in_outstd::string str, char ch)
{
  std::string s = str;
  s += ch;
}

- Original Message -
From: John Torjo [EMAIL PROTECTED]
To: Boost mailing list [EMAIL PROTECTED]
Sent: Thursday, April 24, 2003 5:20 AM
Subject: Re: [boost] Re: class proposal



void f( in_out int  is_not_changed_ )
{
  // use is_not_changed_, but don't change it
}

 I think there would be a much bigger problem (code inside the function
would
 change).

 Just consider

 void add_char( std::string  str, char ch)
 { str += ch; }

 Now, if we change it so be in_out, we'll have to use a .ref()-like
function.


 void add_char( in_outstd::string str, char ch)
 { str.ref() += ch; }

 Of course, this is a simple example, but it illustrates the point.
 The code would become obfuscated.

 Frankly, I donot like it.

 Best,
 John


 ___
 Unsubscribe  other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-24 Thread Noel Yap
Justin M. Lewis wrote:
 And, it's not either pass in a whole object or pass in a pointer, you're
 forgetting references.  This new class takes in a reference, and stores
 that.  It doesn't do anything with pointers.

I didn't really forget references.  IMHO, references are pointers that
are implicitly dereferenced.  At the machine level, they are typically
treated the same (eg address is passed by value).

 And, again, returning an object isn't always desirable, you could be copying
 large objects for no reason.  You may not call a copy constructor, but an =
 operator is being used.

My reply to this was to use smart pointers.  But as Terje Slettebø
pointed out (but I got distracted by work before sending out my reply),
smart pointers don't resolve the problem that the object may still
change from underneath.

I still think there's no need for the proposed wrapper class since:

  void f( T value_may_change_, T const value_may_not_change_ );

is still an acceptible alternative.  IOW, if users stick to using T
only to indicate values that may change, and T const to indicate values
that may not change, the wrapper class has no added value (forgive the
unintended pun).

Noel
-- 
NOTICE: If received in error, please destroy and notify sender.  Sender
does not waive confidentiality or privilege, and use is prohibited.
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-24 Thread Noel Yap
Justin M. Lewis wrote:
 
 I diagree with this.  The code I've written using this looks more like
 
 void add_char( in_outstd::string str, char ch)
 {
   std::string s = str;
   s += ch;
 }

I think you're assuming everyone will code the way you want.  If you're
going to force everyone to code this way, why not just have them code
like:

  void add_char( std::string str_, char ch_ )
  {
str += ch;
  }

  int len( std::string const str )
  {
return str.length();
  }

What is the added value of the proposed class?  It's not that it forces
people to change the value if it's used:

  int len( in_out std::string  str )
  {
return static_cast std::string ( str ).length();
  }

Noel
-- 
NOTICE: If received in error, please destroy and notify sender.  Sender
does not waive confidentiality or privilege, and use is prohibited.
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-24 Thread Justin M. Lewis
Everyone is ignoring the possibility of objects that can't be copied in
this, too.  Some objects intentionally hide their operator =, making
returning it from a function impossible.

And, I think a lot of people are missing a big part of the point here.  You
can enforce the use of making it explicit at the point of invocation that
the param is changing.  The compiler will give an error if a c_out or
c_in_out object isn't passed.  You can't enforce a naming convention or
commenting at the point of invocation, at least not everywhere, like where I
work.  So, by writing a function using these objects, it's a guarantee that
anyone who uses my functions has to make it explicit what the effect of
calling my functions is.



- Original Message -
From: Noel Yap [EMAIL PROTECTED]
To: Boost mailing list [EMAIL PROTECTED]
Sent: Thursday, April 24, 2003 4:13 AM
Subject: Re: [boost] Re: class proposal


 Justin M. Lewis wrote:
 
  in/out seems to be used fairly commonly in COM.  I'm not sure I have any
  great examples off the top of my head, but I know they're commonly used.

 I'm not a COM person, but I believe it's written in C.  If so, then you
 are correct that in/out parameters are more needed since noone would
 want to create a struct for each multiple return type.

 OTOH, C++ has templates to deal with this situation (ie boost::tuple)
 so, qualifying my previous statement, in C++ I still see no need for
 in/out parameters.

  And using pointers is part of what we're trying to avoid here.  Like I
said,
  I avoid using pointers whenever possible at this point.

 I'm a little confused.  Either you pass in the entire object or you pass
 in a pointer (even if it's wrapped in another class).  How is this new
 class supposed to be implemented?

  And, again, the real intent here is to insure clarity at the point of
  invocation.  In my case I'm looking at 100's of thousands of lines of
code,
  written over the past 8 years.  It's tiresome trying to chase down where
  values COULD have changed.  In this setup you KNOW exactly what calls
are
  changing parameter values, and it's enforced.  As long as the library
calls
  use the c_out and c_in_out classes people using the library are forced
to
  conform to the format.  So, 8 years, and a few million lines of code
later,
  no one will wonder what might cause a variable they're tracking to
change
  values.

 I think if parameters are used for in parameters only and return values
 are used for out parameters only, the same thing is achieved.  For
 example,

   inOutValue = square( inOutValue );

 vs (using an extension for generality):

   square( c_in_out typeof( inOutValue ) ( inOutValue ) );

 Noel
 ___
 Unsubscribe  other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: class proposal

2003-04-23 Thread Justin M. Lewis
That depends.  At one point the out and in_out classes had assert checks
in them.  c_out would check to make sure that it was assigned some value
inside the called function, for example.  The other thing is, the idea
here is to force people CALLING your function (func) to show the world
what's going on by using the out or in_out function at the point func is
called.  You'd also want totally separate types that can't be implicitly
cast from one to the other, since the point here is to make it clear at
the point func is called what is happening to the parameters that are
passed.


-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Gennadiy Rozental
Sent: Wednesday, April 23, 2003 1:20 AM
To: [EMAIL PROTECTED]
Subject: [boost] Re: class proposal

 void func(CRetValint x){x = 1977;};

Basically boost::ref could be used for the same purpose, isn't it? Just
different name

Gennadiy.




___
Unsubscribe  other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-23 Thread Terje Slettebø
From: Justin M. Lewis [EMAIL PROTECTED]

 Well, I guess, based on all the code I've been reading at work it didn't
 seem so small, chasing down all kinds of functions across 100's of files
 to see why exactly values are changing mid function I'm looking at
 without warning.

 Anyway, this would allow for stronger enforcement of the rule that
 changing params should be marked somehow.  As the programmer of a
 library people are using, I can force them to mark the params they're
 passing as out or in_out, so in 5 years when someone else comes along
 and has to debug it, it's all clear what's happening.

Why not use T  if the function may change it, and const T  if it won't?
Simple and clear. No need to use pointers, to differentiate between it.

An advantage with references is that you may pass by value, or const
reference, and to the caller, it's called in the same way, so the pass by
value or const reference may be an implementation detail.


Regards,

Terje

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: class proposal

2003-04-23 Thread Justin M. Lewis
Sorry if the explanation is a bit confusing.  The whole idea here is to
make it explicit at the function invocation that a parameter being
passed will be used to return a value.

A good example of where this would be useful is with a function call
that takes some params, and returns several different things in
different params, and still has an explicit return for an error code.
At the invocation point it would be impossible to tell what's going on.

int chk;
chk = GetSomething(p1, p2, p3, p4, p5);

where the actual declaration of GetSomething is like

int GetSomething(int ret1, int ret2, int v1, int v2, int v3);

It's impossible to tell at the invocation which params are returning,
and which are being used to calculate the return.  At the invocation it
looks like chk might be what you're trying to get.

With classes like I'm suggesting it would be obvious, the declaration
would be:
int GetSomething(c_outint ret1, c_outint ret2, int v1, int v2, int
v3);

And at the invocation now, it has to be explicit that those first 2
params are out params.

chk = GetSomething(out(p1), out(p2), p3, p4, p5);

It REQUIRES you to use the out helper function at the invocation, so
anyone reading the code later can see, without checking the
implementation of GetSomething, that those 2 params are being set, and
the last ones are not.



-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Terje Slettebø
Sent: Wednesday, April 23, 2003 11:17 AM
To: Boost mailing list
Subject: Re: [boost] Re: class proposal

From: Terje Slettebø [EMAIL PROTECTED]

 From: Justin M. Lewis [EMAIL PROTECTED]

  Well, I guess, based on all the code I've been reading at work it
didn't
  seem so small, chasing down all kinds of functions across 100's of
files
  to see why exactly values are changing mid function I'm looking at
  without warning.
 
  Anyway, this would allow for stronger enforcement of the rule that
  changing params should be marked somehow.  As the programmer of a
  library people are using, I can force them to mark the params
they're
  passing as out or in_out, so in 5 years when someone else comes
along
  and has to debug it, it's all clear what's happening.

 Why not use T  if the function may change it, and const T  if it
won't?

After I sent it, I realised that the issue was marking it at the
_caller's_
side, so then this doesn't apply.

It was a little difficult to understand the proposal, as it mentioned
c_in_out and c_out, while the code example uses CRetVal and the retval
function.


Regards,

Terje

___
Unsubscribe  other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-23 Thread Justin M. Lewis
Yes, it is better.

The first example has the problem of, you still have to go look up the
function to see if it's actually changing anything, or if it's taking the
param in, reading teh value, then modifying based on what was read.

The second example has the problem of copying a potentially large object,
and it doesn't allow for in/out params.



- Original Message -
From: Gregory Colvin [EMAIL PROTECTED]
To: Boost mailing list [EMAIL PROTECTED]
Sent: Wednesday, April 23, 2003 5:34 PM
Subject: Re: [boost] Re: class proposal


 On Wednesday, Apr 23, 2003, at 16:07 America/Denver, Justin M. Lewis
 wrote:
  Sorry if the explanation is a bit confusing.  The whole idea here is to
  make it explicit at the function invocation that a parameter being
  passed will be used to return a value.
 
  A good example of where this would be useful is with a function call
  that takes some params, and returns several different things in
  different params, and still has an explicit return for an error code.
  At the invocation point it would be impossible to tell what's going on.
 
  int chk;
  chk = GetSomething(p1, p2, p3, p4, p5);
 
  where the actual declaration of GetSomething is like
 
  int GetSomething(int ret1, int ret2, int v1, int v2, int v3);
 
  It's impossible to tell at the invocation which params are returning,
  and which are being used to calculate the return.  At the invocation it
  looks like chk might be what you're trying to get.
 
  With classes like I'm suggesting it would be obvious, the declaration
  would be:
  int GetSomething(c_outint ret1, c_outint ret2, int v1, int v2, int
  v3);
 
  And at the invocation now, it has to be explicit that those first 2
  params are out params.
 
  chk = GetSomething(out(p1), out(p2), p3, p4, p5);
 
  It REQUIRES you to use the out helper function at the invocation, so
  anyone reading the code later can see, without checking the
  implementation of GetSomething, that those 2 params are being set, and
  the last ones are not.

 Is this really that much better than

 chk = GetSomething(p1, p2, p3, p4, p5);

 or

 GotSomething ret = GetSomething(p3,p4,p5);

 ?

 ___
 Unsubscribe  other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-23 Thread Noel Yap
Justin M. Lewis wrote:
 
 Yes, it is better.
 
 The first example has the problem of, you still have to go look up the
 function to see if it's actually changing anything, or if it's taking the
 param in, reading teh value, then modifying based on what was read.

Then how about:

  boost::tuple boost::shared_ptr LargeObject   result = f(
largeObjectSharedPtr );

 The second example has the problem of copying a potentially large object,
 and it doesn't allow for in/out params.

I'm still not convinced that in/out parameters are necessary.

Noel
-- 
NOTICE: If received in error, please destroy and notify sender.  Sender
does not waive confidentiality or privilege, and use is prohibited.
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: class proposal

2003-04-23 Thread Justin M. Lewis
I agree.  I probably wouldn't have cared for this myself, had I never seen
the code I'm working on now.  I mean, normally I work pretty independently.
But, now I'm stuck with the job of maintaining code that's been around
forever, has been ported several times to a couple different projects.  In
places you can see how the code evolved over time.  But, the point is, it's
becoming a mess.  And, we're at a point where we're almost starting
everything again, but this time from scratch.  Knowing that the code will
probably live for years, and be ported several times, and be maintained by
many different people over its life, it seems best to me to start a project
like that off with clarity being the #1 priority.  And, at least in my
experience, people seem to think that functions that pass by reference
changing the values of params is a problem, it's hard to track.  But, most
C++ people I know prefer to avoid pointer use.  So, that really only leaves
the one option that makes the intent explicit and clear, every time.

So, I really can't give a long term analysis of how well this method works,
if it becomes a hassle to maintain it, or not.  But, as it is, it seems more
clear to me than anything else.  At the cost of 3 or 6 letters at the
invocation point, you can make the operation of the function clear.

func(out(x));

It seems pretty simple and straight forward to me.

Justin



- Original Message -
From: Alisdair Meredith [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
Sent: Wednesday, April 23, 2003 7:01 PM
Subject: [boost] Re: class proposal


  Justin M. Lewis wrote:

  My idea was, if you make a simple template class, originally I called
  it CRetVal, you could force people to specify at the time the function
  is called what's going on.  I made a helper template function retval
  that would create and return a CRetVal object of the desired type to
  save from needing to use template notation in line all over the
  place.  So, the above would become something more like.

  void func(CRetValint x){x = 1977;};

 Interesting idea.  I think I like it, similar to the way I like the idea
 of an unmanaged_ptr template to indicate deliberate raw pointer use
 clearly.

 Unfortunately, I think it is a hard sell, persuading people to type many
 more characters to do something they have been familiar with using much
 leaner syntax for years.  If clarity matters it is usually indicated by
 clear function/parameter naming, handily placed comments etc. so various
 strategies for coping with the problem are out there.

 Persuading people that the increased clarity of intent for the single
 parameter is worth the extra code-obfuscation of the call as a whole (as
 any additional wrapper-syntax tends to obfuscate) may be a hard sell.
 On the basis that nothing teaches like experience I'd certainly be
 interested in giving it a go here though g

 --
 AlisdairM

 ___
 Unsubscribe  other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost