Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Good chained function name?

Reply
Thread Tools

Good chained function name?

 
 
Victor Bazarov
Guest
Posts: n/a
 
      02-14-2013
On 2/14/2013 10:14 AM, Öö Tiib wrote:
> [..]
> 'value' (as noun) can not be considered non-property of something whose
> 'value' it is. I never provide properties as L-Values for any by-passer
> to store references at and change at will. I feel it error-prone.
>
> I prefer immutable (after construction) properties. I feel it is safer
> It can be LOT more efficient if property's value is even set
> compile-time. Consider such things about every property.
>
> If there is certain need to mutate a property during object's life-time
> then it deserves command-like operations named by verbs. It is better
> to make such operations as safe and complete as possible. Keep invariant
> of whole object under its own control.
>
> 'value' is still hard example since it is fitting verb too. On such cases
> I prefer to use some synonymous verb (like 'assess', 'estimate', 'evaluate')
> to reduce the possible confusion:
>
> a.revalue( b.price() + c.net_value() );


Uh... Perhaps it's a wrong path we're trying to follow. 'Price' is a
verb as well as a noun, 'estimate' is a noun as well as a verb...

There is something to be said about 'set' as well (it's a noun too, I am
sure you've heard of 'std::set' :*)), but in combination with another
word it is less likely to be confused. I would definitely prefer
'set_value' to 'revalue' (along with 'value' as a "get"-like accessor).
But that's just me. Keep in mind that readability is still
subjective, let's not try to deceive *ourselves* into thinking that
there can be a complete set of readability rules suitable for everybody.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
 
 
 
Luca Risolia
Guest
Posts: n/a
 
      02-14-2013
On 14/02/2013 05:43, Nephi Immortal wrote:
> I ask you for your opinion what chained function name look like. I do not need to post class definition since you know what I am talking about.
>
> Let’s say for example I have 'A' class.
>
> A a( 1 ), b( 2 ), c( 3 );
> int data = a.get_value();
> a.set_value( 2 );
>
> What if I am going to write like this below?
>
> a.set_value( b.get_value() + c.get_value() );
>
> They can be to include operator=, operator+, and operator cast. It looks very readable than getter and setter.
>
> a = b + c;
>
> What if I choose to use chained function name?
>
> a.value() = b.value() + c.value();
>
> Is that readable?
>
> If I name value1() and value2(), I may not want to place them in the main class. I rather prefer to place them in the nested class.
>
> a.Inner().value1() = b.Inner().value1() + c.Inner().value2();
>
> What if I don’t like “Inner()”? It should be removed and operator()() is used.
>
> a().value1() = b().value1() + c().value2();
>
> Do chained function name sound good?
>


"a = b + c" looks good. All the other alternatives are more difficult to
read.

> Let’s give some ideas.
>
> int data1, data2, data3;
>
> data1 = a.Get().Bytes();
> data2 = b.Get().Kilobytes();
> data3 = c.Get().Megabytes();
>
> a.Set().Bytes( 1 );
> b.Set().Kilobytes( 2 );
> c.Set().Megabytes( 3 );
>
> data1 = a().Bytes();
> data2 = b().Kilobytes();
> data3 = c().Megabytes();
>
> a().Bytes() = 1;
> b().Kilobytes() = 2;
> c().Megabytes() = 3;
>
> a().Bytes() = b().Kilobytes() + c().Megabytes();
>
> Please comment if my code looks readable.


I think it is not readable. It's not type-safe for sure, which makes
your code error-prone. You might loose your spacecraft in the space.

I would suggest a more modern and safe approach, for example:

#include <iostream>

template<int UB, int US>
struct Unit { // a unit in the SI/IEEE systems
enum { B=UB, s=US }; // bytes and seconds
};

template<typename Unit> // a magnitude with a unit
struct Value {
double val; // the magnitude
explicit constexpr Value(double d) : val(d) {} // construct a Value
from a double
// other constructors...
Value operator+(const Value& x) {
return Value(val + x.val);
}
};

using Byte = Unit<1, 0>; // unit: byte
using MemBlock = Value<Byte>; // shortcut

constexpr Value<Byte> operator"" _B(long double d) {
return Value<Byte> (d);
}

constexpr Value<Byte> operator"" _kB(long double d) {
return Value<Byte> (d * 1024);
}

constexpr Value<Byte> operator"" _MB(long double d) {
return Value<Byte> (d * 1024 * 1024);
}

constexpr double to_B(const Value<Byte>& b) { // free functions to be simple
return b.val;
}

constexpr double to_kB(const Value<Byte>& b) {
return b.val / 1024;
}

constexpr double to_MB(const Value<Byte>& b) {
return b.val / 1024 / 1024;
}

// Let's add something useful to the example
using Second = Unit<0, 1>; // unit: sec.
// using Second2 = Unit<0, 2>; // s^2
using Time = Value<Second>; // time in seconds by default
using TransferRate = Value<Unit<1, -1>>; // bytes/second type

constexpr Value<Second> operator"" _s(long double d) {
return Value<Second> (d);
}

constexpr double to_s(const Value<Second>& s) {
return s.val;
}

constexpr TransferRate operator/(const MemBlock& m, const Time& s) {
return TransferRate(to_B(m) / to_s(s));
}

int main() {
MemBlock a = 1024.0_B;
//MemBlock b = 3.0; // NOT OK! unit needed
auto b = 3.0_kB; // OK
auto c = a + b;
std::cout << to_kB(a) << "+" << to_kB(b)
<< " = " << to_kB(c) << '\n'; // or define your operator<<()

// Another example..
TransferRate slow = c / 1.0_s;
auto fast = slow + slow;
// etc..
}

 
Reply With Quote
 
 
 
 
Nephi Immortal
Guest
Posts: n/a
 
      02-14-2013
On Thursday, February 14, 2013 5:59:55 AM UTC-6, Victor Bazarov wrote:
> On 2/13/2013 11:43 PM, Nephi Immortal wrote:
>
> > I ask you for your opinion what chained function name look like. I

>
> > do

>
> not need to post class definition since you know what I am talking about.
>
> >

>
> > Let’s say for example I have 'A' class.

>
> >

>
> > A a( 1 ), b( 2 ), c( 3 );

>
> > int data = a.get_value();

>
> > a.set_value( 2 );

>
> >

>
> > What if I am going to write like this below?

>
> >

>
> > a.set_value( b.get_value() + c.get_value() );

>
>
>
> <shrug> I've seen it done.
>
>
>
> > They can be to include operator=, operator+, and operator cast. It looks very readable than getter and setter.

>
> >

>
> > a = b + c;

>
>
>
> Looks OK to me, as well. Supposedly, the type A is a "value type" that
>
> defines addition as one of its operations.
>
>
>
> > What if I choose to use chained function name?

>
>
>
> Never heard this term, so not sure what the meaning of it is.


Hi Victor--please see my comments below.

>
>
>
> >

>
> > a.value() = b.value() + c.value();

>
> >

>
> > Is that readable?

>
>
>
> Readability is subjective. To me it's no more readable than a=b+c. Of
>
> course, if each A has different, independently settable values, then it
>
> would make sense to separate them by means of their own accessors.
>
>
>
> a.value_blah() = b.value_blah() * c.value_droo();
>
>
>
> > If I name value1() and value2(), I may not want to place them in the

>
> main class. I rather prefer to place them in the nested class.
>
> >

>
> > a.Inner().value1() = b.Inner().value1() + c.Inner().value2();

>
>
>
> I don't see any reason to do so.
>
>
>
> > What if I don’t like “Inner()”? It should be removed and operator()() is used.

>
> >

>
> > a().value1() = b().value1() + c().value2();

>
> >

>
> > Do chained function name sound good?

>
>
>
> What's "chained function"?


See my comment here.

"chained function" mean putting two or more functions together
into one line like this below.

A a;

a().func1().func2(0.func3().etc();

Inner() is nested class. Inner() is in main class to be called and return
Inner class type before chained functions in Inner class can be used.
Inner() can be replaced to operator()().

>
>
>
> > Let’s give some ideas.

>
> >

>
> > int data1, data2, data3;

>
> >

>
> > data1 = a.Get().Bytes();

>
> > data2 = b.Get().Kilobytes();

>
> > data3 = c.Get().Megabytes();

>
> >

>
> > a.Set().Bytes( 1 );

>
> > b.Set().Kilobytes( 2 );

>
> > c.Set().Megabytes( 3 );

>
> >

>
> > data1 = a().Bytes();

>
> > data2 = b().Kilobytes();

>
> > data3 = c().Megabytes();

>
> >

>
> > a().Bytes() = 1;

>
> > b().Kilobytes() = 2;

>
> > c().Megabytes() = 3;

>
> >

>
> > a().Bytes() = b().Kilobytes() + c().Megabytes();

>
> >

>
> > Please comment if my code looks readable.

>
>
>
> Since the type of 'Bytes', etc., is all the same, it seems to be OK to
>
> add them together. It's not proper from the POV of dimensioned values,
>
> though. In this particular case 'Bytes' and 'Kilobytes' don't look good
>
> as function names, but rather dimensioned types. "Storage", "Volume",
>
> or "Capacity", are better names. Whether the values returned by those
>
> functions are in bytes or kilobytes, can be easily decided, and then you
>
> can easily add those together to yield a value of the more granulated
>
> type, IOW if bytes and kilobytes are added, you get bytes in which
>
> kilobytes are multiplied correspondingly.


You can create several classes like this below.

class Byte;
class Kilobyte;
class Megabyte;
....
....

Byte, Kilobyte and Megabyte are different types.

What if I show this below?

a().Kilobytes() = b().Bytes + c().Megabytes;

b().Bytes will be converted to Kilobytes by dividing 1024 bytes and
c().Megabytes will be converted to Kilobytes by multiplying 1024 bytes
before the result is to be Kilobyte value.


>
>
>
> So, in short, no, I don't think your code is readable because it does
>
> not reflect anything that would make sense to me. But, again, it can be
>
> all in the eye of the beholder. If you don't intend your code to be
>
> read by anybody else but you, make it readable to *you*, nothing else is
>
> of any importance.
>
>
>
> V
>
> --
>
> I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      02-14-2013
On Thu, 2013-02-14, Öö Tiib wrote:
> On Thursday, 14 February 2013 16:27:29 UTC+2, Jeff Flinn wrote:

....
>> I would avoid the whole approach. I'm assuming the OP's example is just
>> that: a paired down example. Without a clearer def of the class in
>> question it's difficult to say what approach should be used, indeed are
>> these accessor/mutator pairs even needed.

>
> Try to be more constructive? Your answer feels like Nephi should just
> drop dead and stop trying.


Ignoring the "drop dead" part, remember that part of the value of
asking questions here is getting "what you're trying to do isn't
useful" type answers. There's room for both kinds.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
Nephi Immortal
Guest
Posts: n/a
 
      02-15-2013
On Thursday, February 14, 2013 12:38:25 PM UTC-6, Luca Risolia wrote:
> On 14/02/2013 05:43, Nephi Immortal wrote:
>
> > I ask you for your opinion what chained function name look like. I do not need to post class definition since you know what I am talking about.

>
> >

>
> > Let’s say for example I have 'A' class.

>
> >

>
> > A a( 1 ), b( 2 ), c( 3 );

>
> > int data = a.get_value();

>
> > a.set_value( 2 );

>
> >

>
> > What if I am going to write like this below?

>
> >

>
> > a.set_value( b.get_value() + c.get_value() );

>
> >

>
> > They can be to include operator=, operator+, and operator cast. It looks very readable than getter and setter.

>
> >

>
> > a = b + c;

>
> >

>
> > What if I choose to use chained function name?

>
> >

>
> > a.value() = b.value() + c.value();

>
> >

>
> > Is that readable?

>
> >

>
> > If I name value1() and value2(), I may not want to place them in the main class. I rather prefer to place them in the nested class.

>
> >

>
> > a.Inner().value1() = b.Inner().value1() + c.Inner().value2();

>
> >

>
> > What if I don’t like “Inner()”? It should be removed and operator()() is used.

>
> >

>
> > a().value1() = b().value1() + c().value2();

>
> >

>
> > Do chained function name sound good?

>
> >

>
>
>
> "a = b + c" looks good. All the other alternatives are more difficult to
>
> read.
>
>
>
> > Let’s give some ideas.

>
> >

>
> > int data1, data2, data3;

>
> >

>
> > data1 = a.Get().Bytes();

>
> > data2 = b.Get().Kilobytes();

>
> > data3 = c.Get().Megabytes();

>
> >

>
> > a.Set().Bytes( 1 );

>
> > b.Set().Kilobytes( 2 );

>
> > c.Set().Megabytes( 3 );

>
> >

>
> > data1 = a().Bytes();

>
> > data2 = b().Kilobytes();

>
> > data3 = c().Megabytes();

>
> >

>
> > a().Bytes() = 1;

>
> > b().Kilobytes() = 2;

>
> > c().Megabytes() = 3;

>
> >

>
> > a().Bytes() = b().Kilobytes() + c().Megabytes();

>
> >

>
> > Please comment if my code looks readable.

>
>
>
> I think it is not readable. It's not type-safe for sure, which makes
>
> your code error-prone. You might loose your spacecraft in the space.
>
>
>
> I would suggest a more modern and safe approach, for example:
>
>
>
> #include <iostream>
>
>
>
> template<int UB, int US>
>
> struct Unit { // a unit in the SI/IEEE systems
>
> enum { B=UB, s=US }; // bytes and seconds
>
> };
>
>
>
> template<typename Unit> // a magnitude with a unit
>
> struct Value {
>
> double val; // the magnitude
>
> explicit constexpr Value(double d) : val(d) {} // construct a Value
>
> from a double
>
> // other constructors...
>
> Value operator+(const Value& x) {
>
> return Value(val + x.val);
>
> }
>
> };
>
>
>
> using Byte = Unit<1, 0>; // unit: byte
>
> using MemBlock = Value<Byte>; // shortcut
>
>
>
> constexpr Value<Byte> operator"" _B(long double d) {
>
> return Value<Byte> (d);
>
> }
>
>
>
> constexpr Value<Byte> operator"" _kB(long double d) {
>
> return Value<Byte> (d * 1024);
>
> }
>
>
>
> constexpr Value<Byte> operator"" _MB(long double d) {
>
> return Value<Byte> (d * 1024 * 1024);
>
> }
>
>
>
> constexpr double to_B(const Value<Byte>& b) { // free functions to be simple
>
> return b.val;
>
> }
>
>
>
> constexpr double to_kB(const Value<Byte>& b) {
>
> return b.val / 1024;
>
> }
>
>
>
> constexpr double to_MB(const Value<Byte>& b) {
>
> return b.val / 1024 / 1024;
>
> }
>
>
>
> // Let's add something useful to the example
>
> using Second = Unit<0, 1>; // unit: sec.
>
> // using Second2 = Unit<0, 2>; // s^2
>
> using Time = Value<Second>; // time in seconds by default
>
> using TransferRate = Value<Unit<1, -1>>; // bytes/second type
>
>
>
> constexpr Value<Second> operator"" _s(long double d) {
>
> return Value<Second> (d);
>
> }
>
>
>
> constexpr double to_s(const Value<Second>& s) {
>
> return s.val;
>
> }
>
>
>
> constexpr TransferRate operator/(const MemBlock& m, const Time& s) {
>
> return TransferRate(to_B(m) / to_s(s));
>
> }
>
>
>
> int main() {
>
> MemBlock a = 1024.0_B;
>
> //MemBlock b = 3.0; // NOT OK! unit needed
>
> auto b = 3.0_kB; // OK
>
> auto c = a + b;
>
> std::cout << to_kB(a) << "+" << to_kB(b)
>
> << " = " << to_kB(c) << '\n'; // or define your operator<<()
>
>
>
> // Another example..
>
> TransferRate slow = c / 1.0_s;
>
> auto fast = slow + slow;
>
> // etc..
>
> }


Your code looks good. Unfortunately, Visual C++ 2012 does not compile!
I looked at MSDN. It says constexpr and other features are not supported.
I think it only supports partial C++x11. Is that true?

If yes, can you please revise your code to remove unsupported features.
 
Reply With Quote
 
Luca Risolia
Guest
Posts: n/a
 
      02-15-2013
On 15/02/2013 03:56, Nephi Immortal wrote:
> Your code looks good. Unfortunately, Visual C++ 2012 does not compile!
> I looked at MSDN. It says constexpr and other features are not supported.
> I think it only supports partial C++x11. Is that true?
>
> If yes, can you please revise your code to remove unsupported features.


I am sorry, but I don't have VC++2012 at the moment, so I can't answer.
I used GCC 4.7.2:

https://ideone.com/PHh3g5

 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      02-16-2013
On Thursday, 14 February 2013 18:42:48 UTC+2, Victor Bazarov wrote:
> On 2/14/2013 10:14 AM, Öö Tiib wrote:
> > [..]
> > 'value' (as noun) can not be considered non-property of something whose
> > 'value' it is. I never provide properties as L-Values for any by-passer
> > to store references at and change at will. I feel it error-prone.
> >
> > I prefer immutable (after construction) properties. I feel it is safer
> > It can be LOT more efficient if property's value is even set
> > compile-time. Consider such things about every property.
> >
> > If there is certain need to mutate a property during object's life-time
> > then it deserves command-like operations named by verbs. It is better
> > to make such operations as safe and complete as possible. Keep invariant
> > of whole object under its own control.
> >
> > 'value' is still hard example since it is fitting verb too. On such cases
> > I prefer to use some synonymous verb (like 'assess', 'estimate', 'evaluate')
> > to reduce the possible confusion:
> >
> > a.revalue( b.price() + c.net_value() );

>
> Uh... Perhaps it's a wrong path we're trying to follow. 'Price' is a
> verb as well as a noun, 'estimate' is a noun as well as a verb...


It is difficult only because of so lot of verbs and nouns are homonyms
in English. In Russian for example where commanding verb rarely is
homonym for some noun it would not be problem at all. It is not
wrong in English ... just more difficult.

> There is something to be said about 'set' as well (it's a noun too, I am
> sure you've heard of 'std::set' :*)), but in combination with another
> word it is less likely to be confused. I would definitely prefer
> 'set_value' to 'revalue' (along with 'value' as a "get"-like accessor).
> But that's just me. Keep in mind that readability is still
> subjective, let's not try to deceive *ourselves* into thinking that
> there can be a complete set of readability rules suitable for everybody.


When I see some code that is easy to read then it is usually master
involved. So it is art. What rules can achieve is uniform quality that
is usually readable enough. Worst is inconsistent mix of unfitting and
contradicting concepts. Your usage of set prefix is great for me if it
is used consistently for same thing all over the code-base.
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      02-16-2013
On Thursday, 14 February 2013 23:50:08 UTC+2, Jorgen Grahn wrote:
> On Thu, 2013-02-14, Öö Tiib wrote:
> > On Thursday, 14 February 2013 16:27:29 UTC+2, Jeff Flinn wrote:

> ...
> >> I would avoid the whole approach. I'm assuming the OP's example is just
> >> that: a paired down example. Without a clearer def of the class in
> >> question it's difficult to say what approach should be used, indeed are
> >> these accessor/mutator pairs even needed.

> >
> > Try to be more constructive? Your answer feels like Nephi should just
> > drop dead and stop trying.

>
> Ignoring the "drop dead" part, remember that part of the value of
> asking questions here is getting "what you're trying to do isn't
> useful" type answers. There's room for both kinds.


There is. Trying to make some rules how to name classes, variables
and functions in your code feels like good idea. So I disagreed that
it does deserve such answer. I trust that it is worth trying. There
maybe can not be universal naming approach that fits for every
problem domain but everybody end up using something. It makes
life easier.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Chained RDP over chained VPN Frank Winkler Cisco 2 06-20-2008 08:02 AM
Chained Comparisons Sathyaish Python 15 03-20-2006 05:52 PM
Multiple "cmp"s chained one after another Volker Grabsch Python 11 05-16-2005 01:16 PM
Can abbreviated printStackTrace() output be easily prevented for chained exceptions? Mike H Java 1 02-27-2004 04:09 PM
NAT and chained subnet bomba Cisco 6 10-29-2003 02:09 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57