www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - handful and interval

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
I'd like to add a simple function to std called "handful". It would 
return a small, read-only set of which main facility is membership test:

string a = "class";
if (a in handful("struct", "class", "union"))
{
     ...
}

Would it be generally useful, and if so what module does it belong to?

Same question about "interval", which is a fair amount more interesting 
if done right. An interval is a pair of values from a type that supports 
inequality comparison. It would have a variety of interval-specific 
operations, of which this would probably be quite popular:

int x;
...
if (x in interval(1, 2))
{
     ...
}


Destroy,

Andrei
Sep 02 2012
next sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <alex lycus.org> writes:
On 02-09-2012 16:22, Andrei Alexandrescu wrote:
 I'd like to add a simple function to std called "handful". It would
 return a small, read-only set of which main facility is membership test:

 string a = "class";
 if (a in handful("struct", "class", "union"))
 {
      ...
 }

 Would it be generally useful, and if so what module does it belong to?

Yes! I have wanted this so many times in my code. I think std.algorithm is a reasonable place. Though, maybe just call the function set(). It won't collide with anything else anyway (like a Set in std.container or whatever). Also, please avoid backing it with an AA (I don't know if you wanted to do that, but just saying). While it would make the code significantly simpler, it means involving the GC, which is undesirable for such a simple utility function. (I still think allowing 'in' on arrays would be a better approach, but this is better than nothing!)
 Same question about "interval", which is a fair amount more interesting
 if done right. An interval is a pair of values from a type that supports
 inequality comparison. It would have a variety of interval-specific
 operations, of which this would probably be quite popular:

 int x;
 ...
 if (x in interval(1, 2))
 {
      ...
 }

I don't deal much in this sort of code, but I can see it being useful (it's certainly prettier than writing the checks out manually). I don't really know what else I would expect from such a type, though.
 Destroy,

 Andrei

-- Alex Rønne Petersen alex lycus.org http://lycus.org
Sep 02 2012
parent reply "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 2 September 2012 at 14:42:43 UTC, Alex Rønne Petersen 
wrote:
 On 02-09-2012 16:22, Andrei Alexandrescu wrote:
 int x;
 ...
 if (x in interval(1, 2))
 {
     ...
 }

I don't deal much in this sort of code, but I can see it being useful (it's certainly prettier than writing the checks out manually). I don't really know what else I would expect from such a type, though.

Hm, maybe assert(interval(1, 3) & interval(2, 4) == interval(2, 3)) and similar operations? David
Sep 02 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 4:50 PM, David Nadlinger wrote:
 On Sunday, 2 September 2012 at 14:42:43 UTC, Alex Rønne Petersen wrote:
 On 02-09-2012 16:22, Andrei Alexandrescu wrote:
 int x;
 ...
 if (x in interval(1, 2))
 {
 ...
 }

I don't deal much in this sort of code, but I can see it being useful (it's certainly prettier than writing the checks out manually). I don't really know what else I would expect from such a type, though.

Hm, maybe assert(interval(1, 3) & interval(2, 4) == interval(2, 3)) and similar operations?

Thought about sugar for set operations using arithmetic operators, but decided against, because that would create a lot of confusion with http://en.wikipedia.org/wiki/Interval_arithmetic. Andrei
Sep 02 2012
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
[snip]

The alternative would be to simply define these as functions:

if (a.among("struct", "class", "union")) { ... }
if (b.between(1, 100)) { ... }


Andrei
Sep 02 2012
next sibling parent reply "Tyro[17]" <nospam home.com> writes:
On 9/2/12 11:45 PM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }


 Andrei

if (a in ["struct", "class", "union"]) { ... } if (a in someArrayVar) { ... } works wonders for me. Why not? Somehow I cannot see the disadvantages. Please educate. Andrew
Sep 02 2012
next sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <alex lycus.org> writes:
On 02-09-2012 17:05, Tyro[17] wrote:
 On 9/2/12 11:45 PM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }


 Andrei

if (a in ["struct", "class", "union"]) { ... } if (a in someArrayVar) { ... } works wonders for me. Why not? Somehow I cannot see the disadvantages. Please educate. Andrew

The argument seems to be that since an array search is O(n) and an AA lookup is O(1), this example would be "misleading". Not that I think this matters at all in practice. -- Alex Rønne Petersen alex lycus.org http://lycus.org
Sep 02 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-09-02 17:06, Alex Rønne Petersen wrote:

 The argument seems to be that since an array search is O(n) and an AA
 lookup is O(1), this example would be "misleading".

What would it be for this set type? -- /Jacob Carlborg
Sep 02 2012
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 5:05 PM, Tyro[17] wrote:
 On 9/2/12 11:45 PM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }


 Andrei

if (a in ["struct", "class", "union"]) { ... } if (a in someArrayVar) { ... } works wonders for me. Why not? Somehow I cannot see the disadvantages. Please educate. Andrew

The first could be make to work, the second I am against on a big-oh complexity basis. The problem with making the first work is inconsistency. Andrei
Sep 02 2012
prev sibling next sibling parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Sunday, 2 September 2012 at 14:49:34 UTC, Andrei Alexandrescu 
wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }


 Andrei

I prefer this. There doesn't seem to be a clear vision for the 'in' operator. Let's not make the situation more complicated before we've figured that out. How do we know which uses of 'in' are abuse, and which are merely exploiting intuition justifiably?
Sep 02 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 6:22 PM, Jakob Ovrum wrote:
 On Sunday, 2 September 2012 at 14:49:34 UTC, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }


 Andrei

I prefer this.

Me too, upon some more thought. (Interval could become a legit numeric library, but that's a separate idea.)
 There doesn't seem to be a clear vision for the 'in' operator. Let's not
 make the situation more complicated before we've figured that out. How
 do we know which uses of 'in' are abuse, and which are merely exploiting
 intuition justifiably?

Yah, agreed. Andrei
Sep 02 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 6:44 PM, Andrei Alexandrescu wrote:
[snip]

The remaining question is where to put among and between. std.functional?

Andrei
Sep 02 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/02/2012 06:45 PM, Andrei Alexandrescu wrote:
 On 9/2/12 6:44 PM, Andrei Alexandrescu wrote:
 [snip]

 The remaining question is where to put among and between. std.functional?

 Andrei

They are not combinators. std.algorithm.
Sep 02 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 7:31 PM, Timon Gehr wrote:
 On 09/02/2012 06:45 PM, Andrei Alexandrescu wrote:
 On 9/2/12 6:44 PM, Andrei Alexandrescu wrote:
 [snip]

 The remaining question is where to put among and between. std.functional?

 Andrei

They are not combinators. std.algorithm.

I'd argue they aren't quite algorithms either... Andrei
Sep 02 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/03/2012 01:37 AM, Andrei Alexandrescu wrote:
 On 9/2/12 7:31 PM, Timon Gehr wrote:
 On 09/02/2012 06:45 PM, Andrei Alexandrescu wrote:
 On 9/2/12 6:44 PM, Andrei Alexandrescu wrote:
 [snip]

 The remaining question is where to put among and between.
 std.functional?

 Andrei

They are not combinators. std.algorithm.

I'd argue they aren't quite algorithms either... Andrei

Interesting. What is the Phobos definition of algorithm?
Sep 03 2012
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, September 03, 2012 01:37:19 Andrei Alexandrescu wrote:
 On 9/2/12 7:31 PM, Timon Gehr wrote:
 On 09/02/2012 06:45 PM, Andrei Alexandrescu wrote:
 On 9/2/12 6:44 PM, Andrei Alexandrescu wrote:
 [snip]
 
 The remaining question is where to put among and between. std.functional?
 
 Andrei

They are not combinators. std.algorithm.

I'd argue they aren't quite algorithms either...

Well, from the looks of it, handful (or among or whatever you want to call it) is basically a functor for canFind (just with in instead of parens). So, it's an algorithm that's been thrown into a struct rather than kept as a separate function - kind of like map or other lazy, range-based functions except that it's using in instead of the range API. So, I think that it fits in std.algorithm reasonably well, but it _is_ also a bit of an odd fit. I think that the problem is that you're essentially introducing a new idiom, and it doesn't quite fit anywhere in what we have. - Jonathan M Davis
Sep 02 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 9/2/2012 7:45 AM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }

Is between inclusive or not of the endpoints?
Sep 02 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 10:24 PM, Walter Bright wrote:
 On 9/2/2012 7:45 AM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }

Is between inclusive or not of the endpoints?

After quite a bit of thought, I think inclusive is the right way. There are two reasons: 1. Ranges that end in e.g. float.max or int.max would not be expressible if bounds were not included. 2. SQL defines between to include the limits, which sets a precedent. Ranges are open to the right but I think intervals are quite different. Andrei
Sep 02 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 9/2/2012 4:40 PM, Andrei Alexandrescu wrote:
 On 9/2/12 10:24 PM, Walter Bright wrote:
 On 9/2/2012 7:45 AM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }

Is between inclusive or not of the endpoints?

After quite a bit of thought, I think inclusive is the right way.

Then there's no way to specify an empty interval. I suppose with "between" that would not be relevant.
 There are two
 reasons:

 1. Ranges that end in e.g. float.max or int.max would not be expressible if
 bounds were not included.

 2. SQL defines between to include the limits, which sets a precedent.

 Ranges are open to the right but I think intervals are quite different.


 Andrei

Sep 02 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 6:47 AM, Walter Bright wrote:
 On 9/2/2012 4:40 PM, Andrei Alexandrescu wrote:
 On 9/2/12 10:24 PM, Walter Bright wrote:
 On 9/2/2012 7:45 AM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }

Is between inclusive or not of the endpoints?

After quite a bit of thought, I think inclusive is the right way.

Then there's no way to specify an empty interval. I suppose with "between" that would not be relevant.

Apparently I didn't think enough :o). Andrei
Sep 02 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, September 02, 2012 21:47:13 Walter Bright wrote:
 On 9/2/2012 4:40 PM, Andrei Alexandrescu wrote:
 On 9/2/12 10:24 PM, Walter Bright wrote:
 On 9/2/2012 7:45 AM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]
 
 The alternative would be to simply define these as functions:
 
 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }

Is between inclusive or not of the endpoints?

After quite a bit of thought, I think inclusive is the right way.

Then there's no way to specify an empty interval. I suppose with "between" that would not be relevant.

It could take a std.aglorithm.openRight as its third, parameter, then you could choose to do one or the other. It just becomes a question of which is the default. Certainly, my natural inclination is to go with having intervals be open on the right, but if you have a choice, it's less of an issue regardless of which is the default. - Jonathan M Davis
Sep 02 2012
prev sibling parent "Sven Torvinger" <Sven torvinger.se> writes:
On Monday, 3 September 2012 at 04:56:54 UTC, Jonathan M Davis 
wrote:
 It could take a std.aglorithm.openRight as its third, 
 parameter, then you
 could choose to do one or the other. It just becomes a question 
 of which is
 the default.

 Certainly, my natural inclination is to go with having 
 intervals be open on
 the right, but if you have a choice, it's less of an issue 
 regardless of which
 is the default.

 - Jonathan M Davis

http://www.boost.org/doc/libs/1_51_0/libs/icl/doc/html/index.html Recently at work, I was quite pleasantly surprised by the boost solution... it solves a number of problems quite elegantly, different policies for handling overlapping ranges and etc... and found myself wishing for the same in D. ex. typedef std::set<string> guests; interval_map<time, guests> party; party += make_pair(interval<time>::right_open(time("20:00"), time("22:00")), guests("Mary")); party += make_pair(interval<time>::right_open(time("21:00"), time("23:00")), guests("Harry")); // party now contains [20:00, 21:00)->{"Mary"} [21:00, 22:00)->{"Harry","Mary"} //guest sets aggregated on overlap [22:00, 23:00)->{"Harry"}
Sep 02 2012
prev sibling next sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 2 September 2012 at 16:44:40 UTC, Andrei Alexandrescu 
wrote:
 On 9/2/12 6:44 PM, Andrei Alexandrescu wrote:
 [snip]

 The remaining question is where to put among and between. 
 std.functional?

 Andrei

Without second thought, I'd say std.container.set for the first, std.functional for the second (not too sure about it).
Sep 02 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Sun, 02 Sep 2012 22:24:17 +0200, Walter Bright  
<newshound2 digitalmars.com> wrote:

 On 9/2/2012 7:45 AM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }

Is between inclusive or not of the endpoints?

struct Between(string boundaries = "[]", T) { ... } ? -- Simen
Sep 02 2012
prev sibling next sibling parent "David Piepgrass" <qwertie256 gmail.com> writes:
 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }

Is between inclusive or not of the endpoints?

After quite a bit of thought, I think inclusive is the right way.

Then there's no way to specify an empty interval. I suppose with "between" that would not be relevant.

Perhaps b.between(1, 0) would always return false. However I'd use different names: among=>isOneOf, between=>isInRange. I would also define another function inRange that ensures, rather than tests, that a value is in range: string userInput = "-7"; int cleanInput = inRange(parse!int(userInput), 1, 100);
Sep 03 2012
prev sibling next sibling parent "David Piepgrass" <qwertie256 gmail.com> writes:
 However I'd use different names: among=>isOneOf, 
 between=>isInRange.

should be named so that you can tell they return bool, as "between" could easily be a function that places a value into a range rather than tests whether it is in range.
Sep 03 2012
prev sibling parent "sclytrack" <fake person.de> writes:
On Sunday, 2 September 2012 at 20:24:29 UTC, Walter Bright wrote:
 On 9/2/2012 7:45 AM, Andrei Alexandrescu wrote:
 On 9/2/12 4:22 PM, Andrei Alexandrescu wrote:
 [snip]

 The alternative would be to simply define these as functions:

 if (a.among("struct", "class", "union")) { ... }
 if (b.between(1, 100)) { ... }

Is between inclusive or not of the endpoints?

"between" inclusive "in between" exclusive
Sep 03 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-09-02 16:22, Andrei Alexandrescu wrote:
 I'd like to add a simple function to std called "handful". It would
 return a small, read-only set of which main facility is membership test:

 string a = "class";
 if (a in handful("struct", "class", "union"))
 {
      ...
 }

 Would it be generally useful, and if so what module does it belong to?

I really don't like the name "handful". What would be the difference compared to a regular set container? To me it sounds like we should have a standard set container in Phobos, std.container.set. -- /Jacob Carlborg
Sep 02 2012
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 02/09/2012 16:51, Jacob Carlborg a écrit :
 On 2012-09-02 16:22, Andrei Alexandrescu wrote:
 I'd like to add a simple function to std called "handful". It would
 return a small, read-only set of which main facility is membership test:

 string a = "class";
 if (a in handful("struct", "class", "union"))
 {
 ...
 }

 Would it be generally useful, and if so what module does it belong to?

I really don't like the name "handful". What would be the difference compared to a regular set container? To me it sounds like we should have a standard set container in Phobos, std.container.set.

+1, and we are back to the allocator design.
Sep 02 2012
parent Don Clugston <dac nospam.com> writes:
On 02/09/12 22:42, SomeDude wrote:
 On Sunday, 2 September 2012 at 15:09:50 UTC, deadalnix wrote:
 Le 02/09/2012 16:51, Jacob Carlborg a écrit :
 I really don't like the name "handful". What would be the difference
 compared to a regular set container? To me it sounds like we should have
 a standard set container in Phobos, std.container.set.

+1, and we are back to the allocator design.

+2 on the basis of typical "real world" (if I may says so) usage. It calls for a set container, both mutable and immutable. For a "handful" of values (say 5 or less), I'm not even sure the O(1) method is faster than the O(n) one. As for the intervals, I suppose one would have to define open intervals, because I think they would be much more useful than closed ones when the intervals are contiguous (in particular with floats/doubles). One must be able to translate x0 <= x < x1 in intervals else they are practically useless for anything else than integers and other discrete values.

But practically everything on a computer uses discrete values. Floating point numbers always do, for example; they are *not* mathematical real numbers with infinite precision. For floats and doubles, any non-empty interval can be expressed using closed intervals. Use the nextUp() and nextDown() to convert between open and closed intervals. [ x .. y ] == ( nextDown(x) .. nextUp(y) ) ( x .. y ) == [ nextUp(x) .. nextDown(y) ] In general: Fully closed interval: cannot express an empty interval. Fully open interval: cannot express a maximum-sized interval. Empty intervals can be expressed but not uniquely. Half-open: not closed under negation. Either of the first two are reasonable choices for arithmetic applications. The third is broken for anything that allows negative values.
Sep 03 2012
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 4:51 PM, Jacob Carlborg wrote:
 On 2012-09-02 16:22, Andrei Alexandrescu wrote:
 I'd like to add a simple function to std called "handful". It would
 return a small, read-only set of which main facility is membership test:

 string a = "class";
 if (a in handful("struct", "class", "union"))
 {
 ...
 }

 Would it be generally useful, and if so what module does it belong to?

I really don't like the name "handful". What would be the difference compared to a regular set container? To me it sounds like we should have a standard set container in Phobos, std.container.set.

The difference is in scale and primitives offered. Handful would be read-only and limited to the size of its initializer. Its representation would take advantage of that. Anyhow, I think among would be a simpler solution for this all. Andrei
Sep 02 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-09-02 17:17, Andrei Alexandrescu wrote:

 The difference is in scale and primitives offered. Handful would be
 read-only and limited to the size of its initializer. Its representation
 would take advantage of that.

 Anyhow, I think among would be a simpler solution for this all.

This doesn't sound like an approach you would take Andrei :) I would expect you to say something like: "This isn't general enough, we need a general set container that is fast and efficient enough for this uses cases as well". -- /Jacob Carlborg
Sep 02 2012
prev sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 2 September 2012 at 15:09:50 UTC, deadalnix wrote:
 Le 02/09/2012 16:51, Jacob Carlborg a écrit :
 I really don't like the name "handful". What would be the 
 difference
 compared to a regular set container? To me it sounds like we 
 should have
 a standard set container in Phobos, std.container.set.

+1, and we are back to the allocator design.

+2 on the basis of typical "real world" (if I may says so) usage. It calls for a set container, both mutable and immutable. For a "handful" of values (say 5 or less), I'm not even sure the O(1) method is faster than the O(n) one. As for the intervals, I suppose one would have to define open intervals, because I think they would be much more useful than closed ones when the intervals are contiguous (in particular with floats/doubles). One must be able to translate x0 <= x < x1 in intervals else they are practically useless for anything else than integers and other discrete values.
Sep 02 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-09-02 16:22, Andrei Alexandrescu wrote:

 Same question about "interval", which is a fair amount more interesting
 if done right. An interval is a pair of values from a type that supports
 inequality comparison. It would have a variety of interval-specific
 operations, of which this would probably be quite popular:

 int x;
 ...
 if (x in interval(1, 2))
 {
      ...
 }

Isn't this a bit like std.range.iota? Perhaps extending that returned value with opIn and other functionality. -- /Jacob Carlborg
Sep 02 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/2/12 4:56 PM, Jacob Carlborg wrote:
 On 2012-09-02 16:22, Andrei Alexandrescu wrote:

 Same question about "interval", which is a fair amount more interesting
 if done right. An interval is a pair of values from a type that supports
 inequality comparison. It would have a variety of interval-specific
 operations, of which this would probably be quite popular:

 int x;
 ...
 if (x in interval(1, 2))
 {
 ...
 }

Isn't this a bit like std.range.iota? Perhaps extending that returned value with opIn and other functionality.

Iota is a different notion (it has a step). Andrei
Sep 02 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-09-02 17:16, Andrei Alexandrescu wrote:

 Iota is a different notion (it has a step).

Yes, but that is optional, making "iota" a more general form of an interval. -- /Jacob Carlborg
Sep 02 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 8:29 AM, Jacob Carlborg wrote:
 On 2012-09-02 17:16, Andrei Alexandrescu wrote:

 Iota is a different notion (it has a step).

Yes, but that is optional, making "iota" a more general form of an interval.

I think in this case the generalization goes the wrong way. Andrei
Sep 02 2012
prev sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Mon, 03 Sep 2012 08:29:34 +0200, Jacob Carlborg <doob me.com> wrote:

 On 2012-09-02 17:16, Andrei Alexandrescu wrote:

 Iota is a different notion (it has a step).

Yes, but that is optional, making "iota" a more general form of an interval.

It's not optional, it has a default value. -- Simen
Sep 02 2012
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 02-Sep-12 18:22, Andrei Alexandrescu wrote:
 I'd like to add a simple function to std called "handful". It would
 return a small, read-only set of which main facility is membership test:

 string a = "class";
 if (a in handful("struct", "class", "union"))
 {
      ...
 }

 Would it be generally useful, and if so what module does it belong to?

One thing I'd love to see is thing like handful!("struct", "class", "union") that does pre-process contents at compile time to speed up search. In other words it's possible to not only come close to a series of a == "struct" || a == "class" || a == "union" but surpass it. At the very least handful!(a,b,c) can take expression tuple and make x in handful!(a,b,c) lower to: return x == a || x == b || x == c; even for run-time variables a, b & c. -- Olshansky Dmitry
Sep 02 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-09-02 17:29, Dmitry Olshansky wrote:

 I wouldn't question utility but rather the implementation of the above.
 One thing I'd love to see is thing like
 handful!("struct", "class", "union")

 that does pre-process contents at compile time to speed up search.
 In other words it's possible to not only come close to  a series of a ==
 "struct" || a == "class" || a == "union" but surpass it.

Sounds like an enhanced tuple?
 At the very least handful!(a,b,c) can take expression tuple and make
 x in handful!(a,b,c) lower to:
 return x == a || x == b || x == c;

 even for run-time variables a, b & c.

-- /Jacob Carlborg
Sep 02 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 8:28 AM, Jacob Carlborg wrote:
 On 2012-09-02 17:29, Dmitry Olshansky wrote:

 I wouldn't question utility but rather the implementation of the above.
 One thing I'd love to see is thing like
 handful!("struct", "class", "union")

 that does pre-process contents at compile time to speed up search.
 In other words it's possible to not only come close to a series of a ==
 "struct" || a == "class" || a == "union" but surpass it.

Sounds like an enhanced tuple?

Tuple is the representation of an interval but that's where commonality stops. Andrei
Sep 02 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 8:31 AM, Andrei Alexandrescu wrote:
 On 9/3/12 8:28 AM, Jacob Carlborg wrote:
 On 2012-09-02 17:29, Dmitry Olshansky wrote:

 I wouldn't question utility but rather the implementation of the above.
 One thing I'd love to see is thing like
 handful!("struct", "class", "union")

 that does pre-process contents at compile time to speed up search.
 In other words it's possible to not only come close to a series of a ==
 "struct" || a == "class" || a == "union" but surpass it.

Sounds like an enhanced tuple?

Tuple is the representation of an interval but that's where commonality stops.

Rats, sorry (no coffee yet). It was about "handful" and I was at "interval". I can see how an inclusion for tuple would make sense, even in the current notion - i.e. we could add "in" to Tuple and get to write: if (x in tuple("struct", "class", "union")) { ... } Andrei
Sep 02 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 10:27 AM, Philippe Sigaud wrote:
 People here are talking about sets, but does Andrei really have sets in
 mind? That has consequences if you want 'in' to return a pointer to a value.

I wanted to define a couple of simple convenience functions. It seems we've headed into a paralysis of analysis. Andrei
Sep 03 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 11:37 AM, Sven Torvinger wrote:
 On Monday, 3 September 2012 at 09:01:37 UTC, Andrei Alexandrescu wrote:
 On 9/3/12 10:27 AM, Philippe Sigaud wrote:
 People here are talking about sets, but does Andrei really have sets in
 mind? That has consequences if you want 'in' to return a pointer to a
 value.

I wanted to define a couple of simple convenience functions. It seems we've headed into a paralysis of analysis. Andrei

I would advocate using, a < x < b, this trivially addresses open/closed intervals etc. I disagree with the porting from other languages argument... comparing bool with < > is not a common occurring pattern, and even if there is such code in the wild, many coding standards would force the use of () if using such an expression anyway... so the porting issues would be minimal.

It's a sensible argument. What about "among"? Andrei
Sep 03 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 1:24 PM, David Nadlinger wrote:
 On Monday, 3 September 2012 at 11:20:27 UTC, Sven Torvinger wrote:
 if (a.among("struct", "class", "union")) { ... }

Wouldn't that rather be a.among!("struct", "class", "union")?

I'd rather have a regular function (more generally applicable) that the inliner takes care of. Andrei
Sep 03 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 3:53 PM, David Nadlinger wrote:
 On Monday, 3 September 2012 at 12:58:05 UTC, Andrei Alexandrescu wrote:
 On 9/3/12 1:24 PM, David Nadlinger wrote:
 On Monday, 3 September 2012 at 11:20:27 UTC, Sven Torvinger wrote:
 if (a.among("struct", "class", "union")) { ... }

Wouldn't that rather be a.among!("struct", "class", "union")?

I'd rather have a regular function (more generally applicable) that the inliner takes care of.

Where would the real difference to ["struct", "class", "union"].canFind(a) then?

Convenience. I find the other easier to write and read.
 A sufficiently smart compiler (tm) could
 optimize this to a efficient string "prefix switch statement" just as well…

I agree. But then http://c2.com/cgi/wiki?SufficientlySmartCompiler. Andrei
Sep 03 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/03/2012 08:01 PM, David Nadlinger wrote:
 On Monday, 3 September 2012 at 14:04:18 UTC, Andrei Alexandrescu wrote:
 A sufficiently smart compiler (tm) could
 optimize this to a efficient string "prefix switch statement" just as
 well…

I agree. But then http://c2.com/cgi/wiki?SufficientlySmartCompiler.

This is exactly my point: My feeling is that the increased complexity

What complexity?
 by introducing a second syntax resp. a new special case (i.e. among) for
 such a simple operation is only worth it if it leaves no reason to
 revert to a hand-written replacement for performance reason,

[ ].canFind( ) allocates on the GC heap without a sufficiently smart compiler.
 and I'm not sure if the signature taking runtime parameters is enough for that
 (without assuming such a sufficiently smart compiler).

 David

Sep 03 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/03/2012 08:53 PM, Jonathan M Davis wrote:
 On Monday, September 03, 2012 20:29:27 Timon Gehr wrote:
 On 09/03/2012 08:01 PM, David Nadlinger wrote:
 On Monday, 3 September 2012 at 14:04:18 UTC, Andrei Alexandrescu wrote:
 A sufficiently smart compiler (tm) could
 optimize this to a efficient string "prefix switch statement" just as
 well…

I agree. But then http://c2.com/cgi/wiki?SufficientlySmartCompiler.

This is exactly my point: My feeling is that the increased complexity

What complexity?

He probably means that adding another function to do exactly what an existing function already does is complicating the library. The new function needs to bring enoug to the table to be worth it, and the syntactic change of allowing you to do if(value in handful(value1, value2, value3) {}

I am certainly not arguing for that one.
 instead of

 if(canFind([value1, value2, value3], value)) {}

 isn't worth that.

 by introducing a second syntax resp. a new special case (i.e. among) for
 such a simple operation is only worth it if it leaves no reason to
 revert to a hand-written replacement for performance reason,

[ ].canFind( ) allocates on the GC heap without a sufficiently smart compiler.

That's then a performance issue which make may something like handful worth it, but Andrei seems to be arguing based on aesthetics rather than performance. And if you're arguing performance, I'd argue that the "in" solution is a bad one anyway, because it requires constructing and returning a struct, whereas you could just make what you're looking for the first argument. e.g. if(among(value, value1, value2, value3)) {} The syntax is less clear this way,

value.among(value1, value2, value3).
 and perhaps the syntactic convenience of
 the whole in idea outweighs the performcance cost there (particularly since it
 should still be cheaper than a heap allocation),

Basic function inlining usually works satisfactorily. Also, optimizing non-bottlenecks is usually not worth the effort, but I still generally avoid gratuitous allocations.
 but the only reason to argue against canFind that I can see is performance,

There are a couple unimportant ones like: - "canFind"? - it is unwritten law that x == 2 is preferred to 2 == x. (I have never experienced a bikeshedding discussion on that point, which is quite remarkable, as it is completely unimportant and there are multiple ways to do it.) this is much like x.among(2) vs [2].canFind(x);
 and if you're arguing
 performance, then I'm not sure that the in idea is necessarily the way to go.

 Regardless, the point is that there needs to be a practical reason for
 something like handful, not an aesthetic one.

I am arguing against pointless inefficiency. The motivation is almost purely aesthetic. (well, it *might* save time in the profiler, better spent optimizing non-obvious inefficiencies and avoid the application obtaining a sluggish feel, but I have absolutely no data to back that up.) I don't have an opinion on whether or not those specific functions should be added, but Phobos is certainly lacking many simple functions.
Sep 03 2012
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 8:01 PM, David Nadlinger wrote:
 On Monday, 3 September 2012 at 14:04:18 UTC, Andrei Alexandrescu wrote:
 A sufficiently smart compiler (tm) could
 optimize this to a efficient string "prefix switch statement" just as
 well…

I agree. But then http://c2.com/cgi/wiki?SufficientlySmartCompiler.

This is exactly my point: My feeling is that the increased complexity by introducing a second syntax resp. a new special case (i.e. among)

"among" is a simple function, not a special case. Andrei
Sep 03 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/03/2012 05:05 PM, bearophile wrote:
 David Nadlinger:

 Where would the real difference to ["struct", "class",
 "union"].canFind(a) then? A sufficiently smart compiler (tm) could
 optimize this to a efficient string "prefix switch statement" just as
 well…

I think a smart compiler is not needed. Maybe a general solution is to introduce a way to define overloaded templates callable as functions, that get called if the input is a literal (or statically known, but D design requires you to asks explicitly for a CT evaluation): void foo(static int[] a) {} void foo(int[] a) {} void main(string[] args) { foo([1, 2]); // calls first foo int[] a = [1, 2] ~ args.length; foo(a); // calls second foo } Bye, bearophile

It is not general enough. (and static is the wrong keyword.) This would eventually lead to a solution like bool among(S,T...)(S needle, auto enum T haystack){ ... foreach(h;haystack) static if(__traits(isConstant, h)){ ... } ... } Which is still rather specific. Anyway, I don't consider among trying to be clever crucial at all.
Sep 03 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/3/12 9:15 PM, Timon Gehr wrote:
 This would eventually lead to a solution like

 bool among(S,T...)(S needle, auto enum T haystack){
 ...
 foreach(h;haystack) static if(__traits(isConstant, h)){ ... }
 ...
 }

 Which is still rather specific.

 Anyway, I don't consider among trying to be clever crucial at all.

I'd be happy with: uint among(S, T...)(S needle, T haystack) { foreach (i, straw; haystack) { if (needle == straw) return i + 1; } return 0; } The only issue is that all straws in the haystack are evaluated eagerly, even if not needed. I think it's okay to live with that. Andrei
Sep 03 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Mon, 03 Sep 2012 08:34:33 +0200, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 we could add "in" to Tuple and get to write:

 if (x in tuple("struct", "class", "union")) { ... }

if (x in tuple(1, new Foo(), "baa!") { ... } Just kidding. tuple has the inconvenience that we don't know the values at compile-time. If we did, we could take advantage of some cleverer tricks for fast comparison. At the same time, it's a neat and logical solution. -- Simen
Sep 02 2012
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--00248c6a673210b58904c8c7e920
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Le 3 sept. 2012 08:42, "Simen Kjaeraas" <simen.kjaras gmail.com> a =C3=A9cr=
it :
 On Mon, 03 Sep 2012 08:34:33 +0200, Andrei Alexandrescu <

 we could add "in" to Tuple and get to write:

 if (x in tuple("struct", "class", "union")) { ... }

if (x in tuple(1, new Foo(), "baa!") { ... } Just kidding.

I was about to say the same, except not kidding :) I can see value in having this: finding if a value in a struct '.tupleof', for example. Or finding a range among a tuple of ranges, all of subtly different types and that cannot be put in an array. I was imagining 'in' to return a boolean, but if you need it to return a possible value, then it can return a pointer to CommonType!(Ts) if this exists, or a pointer to Algebraic!(Types...). Of course, that would also be a interesting place to use an Option!(T) type= .
 tuple has the inconvenience that we don't know the values at compile-time=

 If we did, we could take advantage of some cleverer tricks for fast
 comparison. At the same time, it's a neat and logical solution.

We can try to get a fully-CT version, using template arguments, but I'm not sure that would be interesting. People here are talking about sets, but does Andrei really have sets in mind? That has consequences if you want 'in' to return a pointer to a value= . --00248c6a673210b58904c8c7e920 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <p><br> Le 3 sept. 2012 08:42, &quot;Simen Kjaeraas&quot; &lt;<a href=3D"mailto:sim= en.kjaras gmail.com">simen.kjaras gmail.com</a>&gt; a =C3=A9crit=C2=A0:<br> &gt;<br> &gt; On Mon, 03 Sep 2012 08:34:33 +0200, Andrei Alexandrescu &lt;<a href=3D= "mailto:SeeWebsiteForEmail erdani.org">SeeWebsiteForEmail erdani.org</a>&gt= ; wrote:<br> &gt;<br> &gt;&gt; we could add &quot;in&quot; to Tuple and get to write:<br> &gt;&gt;<br> &gt;&gt; if (x in tuple(&quot;struct&quot;, &quot;class&quot;, &quot;union&= quot;)) { ... }<br> &gt;<br> &gt;<br> &gt; if (x in tuple(1, new Foo(), &quot;baa!&quot;) { ... }<br> &gt;<br> &gt; Just kidding.</p> <p>I was about to say the same, except not kidding :)<br> I can see value in having this: finding if a value in a struct &#39;.tupleo= f&#39;, for example. Or finding a range among a tuple of ranges, all of sub= tly different types and that cannot be put in an array.<br> I was imagining &#39;in&#39; to return a boolean, but if you need it to re= turn a possible value, then it can return a pointer to CommonType!(Ts) if t= his exists, or a pointer to Algebraic!(Types...).</p> <p>Of course, that would also be a interesting place to use an Option!(T) t= ype.</p> <p> &gt; tuple has the inconvenience that we don&#39;t know the values at c= ompile-time.<br> &gt; If we did, we could take advantage of some cleverer tricks for fast<br=


9;m not sure that would be interesting.<br></p> <p>People here are talking about sets, but does Andrei really have sets in = mind? That has consequences if you want &#39;in&#39; to return a pointer to= a value.</p> <p> </p> --00248c6a673210b58904c8c7e920--
Sep 03 2012
prev sibling next sibling parent "Sven Torvinger" <Sven torvinger.se> writes:
On Monday, 3 September 2012 at 09:01:37 UTC, Andrei Alexandrescu 
wrote:
 On 9/3/12 10:27 AM, Philippe Sigaud wrote:
 People here are talking about sets, but does Andrei really 
 have sets in
 mind? That has consequences if you want 'in' to return a 
 pointer to a value.

I wanted to define a couple of simple convenience functions. It seems we've headed into a paralysis of analysis. Andrei

I would advocate using, a < x < b, this trivially addresses open/closed intervals etc. I disagree with the porting from other languages argument... comparing bool with < > is not a common occurring pattern, and even if there is such code in the wild, many coding standards would force the use of () if using such an expression anyway... so the porting issues would be minimal.
Sep 03 2012
prev sibling next sibling parent "Sven Torvinger" <Sven torvinger.se> writes:
On Monday, 3 September 2012 at 10:42:34 UTC, Andrei Alexandrescu 
wrote:
 I would advocate using, a < x < b, this trivially addresses 
 open/closed
 intervals etc.

 I disagree with the porting from other languages argument... 
 comparing
 bool with < > is not a common occurring pattern, and even if 
 there is
 such code in the wild, many coding standards would force the 
 use of ()
 if using such an expression anyway... so the porting issues 
 would be
 minimal.

It's a sensible argument. What about "among"? Andrei

Since 'among' only is concerned with equality it doesn't suffer from the open/closed interval complication... thus in this case, the simplest solution is the best imho... 'in' sugar would not add much to the readability. if (a.among("struct", "class", "union")) { ... }
Sep 03 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 3 September 2012 at 11:20:27 UTC, Sven Torvinger wrote:
 if (a.among("struct", "class", "union")) { ... }

Wouldn't that rather be a.among!("struct", "class", "union")? If the string is not known at compile-time, I'd prefer to focus on optimizing something along the lines of ["struct", "class", "union"].canFind(a) (something similar is actually a quite common idiom in Ruby). David
Sep 03 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 3 September 2012 at 12:58:05 UTC, Andrei Alexandrescu 
wrote:
 On 9/3/12 1:24 PM, David Nadlinger wrote:
 On Monday, 3 September 2012 at 11:20:27 UTC, Sven Torvinger 
 wrote:
 if (a.among("struct", "class", "union")) { ... }

Wouldn't that rather be a.among!("struct", "class", "union")?

I'd rather have a regular function (more generally applicable) that the inliner takes care of.

Where would the real difference to ["struct", "class", "union"].canFind(a) then? A sufficiently smart compiler (tm) could optimize this to a efficient string "prefix switch statement" just as well… David
Sep 03 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
David Nadlinger:

 Where would the real difference to ["struct", "class", 
 "union"].canFind(a) then? A sufficiently smart compiler (tm) 
 could optimize this to a efficient string "prefix switch 
 statement" just as well…

I think a smart compiler is not needed. Maybe a general solution is to introduce a way to define overloaded templates callable as functions, that get called if the input is a literal (or statically known, but D design requires you to asks explicitly for a CT evaluation): void foo(static int[] a) {} void foo(int[] a) {} void main(string[] args) { foo([1, 2]); // calls first foo int[] a = [1, 2] ~ args.length; foo(a); // calls second foo } Bye, bearophile
Sep 03 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 3 September 2012 at 14:04:18 UTC, Andrei Alexandrescu 
wrote:
 A sufficiently smart compiler (tm) could
 optimize this to a efficient string "prefix switch statement" 
 just as well…

I agree. But then http://c2.com/cgi/wiki?SufficientlySmartCompiler.

This is exactly my point: My feeling is that the increased complexity by introducing a second syntax resp. a new special case (i.e. among) for such a simple operation is only worth it if it leaves no reason to revert to a hand-written replacement for performance reason, and I'm not sure if the signature taking runtime parameters is enough for that (without assuming such a sufficiently smart compiler). David
Sep 03 2012
prev sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 3 September 2012 at 22:37:30 UTC, Andrei Alexandrescu 
wrote:
 "among" is a simple function, not a special case.

I was more thinking of the »in … handful« proposal here, which would entail creating a new type (presumably just with a single method, opIn_r) just to get a somewhat spiffy syntax for a single use case, even if other more conventional designs (like among) work just as well. In this case, I think it is questionable if the "more interesting" syntax justifies the additional cognitive overhead induced by adding such single-use types over just using familiar concepts. As for among, I'm not really opposed to it, even though I'm still not quite sure whether template arguments vs. runtime arguments are the right design – but maybe I'm just overestimating the optimization potential gained by being able to access the parameters at compile time (if they are actually evaluatable at compile time, that is). David
Sep 03 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

I remember naming the first thing bunch().

 if (x in interval(1, 2))
 {
     ...
 }

Is interval() for time intervals too? :-) Bye, bearophile
Sep 02 2012
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Sep 2, 2012 at 5:29 PM, Dmitry Olshansky <dmitry.olsh gmail.com> wrote:

 I wouldn't question utility but rather the implementation of the above.
 One thing I'd love to see is thing like
 handful!("struct", "class", "union")

 that does pre-process contents at compile time to speed up search.
 In other words it's possible to not only come close to  a series of a ==
 "struct" || a == "class" || a == "union" but surpass it.

Dmitry, don't you have a trie implementation since your GSOC project? In any case, I'd gladly welcome such a function. I just spent hours trying to find an quick way to search for a string among a handful (set, group, whatever) of strings known at CT, that works at compile-time and is swift at runtime. Having that in Phobos would be very nice. For strings, some ordering and prefix factorisation can probably work, but what Andrei proposes is more general I presume?
Sep 02 2012
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
string a = "class";
if (a in tuple("struct", "class", "union"))
{
     ...
}
Sep 02 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, September 02, 2012 16:22:20 Andrei Alexandrescu wrote:
 I'd like to add a simple function to std called "handful". It would
 return a small, read-only set of which main facility is membership test:
 
 string a = "class";
 if (a in handful("struct", "class", "union"))
 {
      ...
 }
 
 Would it be generally useful, and if so what module does it belong to?

How is this different from if(canFind(["struct", "class", "union"], a) {...} Is it because it can be made more efficient? From a usage standpoint, they're essentially the same.
 Same question about "interval", which is a fair amount more interesting
 if done right. An interval is a pair of values from a type that supports
 inequality comparison. It would have a variety of interval-specific
 operations, of which this would probably be quite popular:
 
 int x;
 ...
 if (x in interval(1, 2))
 {
      ...
 }

I take it that that's a closed interval (opened vs closed would potentially complicate this a bit)? If so, then that's the same as if(x >= 1 && x <= 2) {...} right? That's kind of nice and kind of pointless. It's slightly less verbose, but unless the optimizer does a lot better than it's probably going to do, you're gonig to take a performance hit. The only real advantage there that I see is that it's a bit more idomatic. Though, on thinking about it, it _would_ have the advantage of allowing you to pass around an interval, which doesn't work anywhere near as well with separate values. And if the interval is doing a lot more than in, then that could make it valuable as well. But the example doesn't really do much to show interval's value IMHO. - Jonathan M Davis
Sep 02 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, September 02, 2012 19:12:30 bearophile wrote:
 Is interval() for time intervals too? :-)

We already have those: std.dateteme.Interval std.datetime.PosInfInterval std.datetime.NegInfInterval But if all interval needs to work is the comparison operators, then it would work with the various time point types in std.datetime. - Jonathan M Davis
Sep 02 2012
prev sibling next sibling parent "ixid" <nuaccount gmail.com> writes:
if (a in handful("struct", "class", "union"))

How is this different from

if(canFind(["struct", "class", "union"], a) {...}

It's a lot cleaner without the mess of brackets. You missed a ) on the second one, which, without intending snarkiness, perhaps demonstrates the greater elegance of the former? Though being able to use in on a simple array would be very nice. if(a in ["struct", "class", "union"]) Wouldn't you expect to search an array at O(n) while an associative array would be O(1), making the difference not unintuitive?
Sep 03 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 3 September 2012 at 15:10:46 UTC, ixid wrote:
if (a in handful("struct", "class", "union"))

How is this different from

if(canFind(["struct", "class", "union"], a) {...}

It's a lot cleaner without the mess of brackets.

I find the difference between »a in handful("struct", "class", "union")« and »["struct", "class", "union"].canFind(a)« to be largely a matter of taste – to me, the former introduces too much of a special case just to for a slightly nicer-looking syntax, whereas the other doesn't look bad either and reuses existing constructs. David
Sep 03 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, September 03, 2012 19:52:26 David Nadlinger wrote:
 On Monday, 3 September 2012 at 15:10:46 UTC, ixid wrote:
if (a in handful("struct", "class", "union"))

How is this different from

if(canFind(["struct", "class", "union"], a) {...}


I find the difference between =C2=BBa in handful("struct", "class", "union")=C2=AB and =C2=BB["struct", "class", "union"].canFind(a)=C2=AB=

 largely a matter of taste =E2=80=93 to me, the former introduces too
 much of a special case just to for a slightly nicer-looking
 syntax, whereas the other doesn't look bad either and reuses
 existing constructs.

I agree. If it's purely a matter of aesthetics, then I see no reason to= add=20 anything like handful. There needs to be a practical reason for it. - Jonathan M Davis
Sep 03 2012
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, September 03, 2012 20:29:27 Timon Gehr wrote:
 On 09/03/2012 08:01 PM, David Nadlinger wrote:
 On Monday, 3 September 2012 at 14:04:18 UTC, Andrei Alexandrescu wr=


 A sufficiently smart compiler (tm) could
 optimize this to a efficient string "prefix switch statement" jus=




 well=E2=80=A6

I agree. But then http://c2.com/cgi/wiki?SufficientlySmartCompiler=



=20
 This is exactly my point: My feeling is that the increased complexi=


=20
 What complexity?

He probably means that adding another function to do exactly what an ex= isting=20 function already does is complicating the library. The new function nee= ds to=20 bring enoug to the table to be worth it, and the syntactic change of al= lowing=20 you to do if(value in handful(value1, value2, value3) {} instead of if(canFind([value1, value2, value3], value)) {} isn't worth that.
 by introducing a second syntax resp. a new special case (i.e. among=


 such a simple operation is only worth it if it leaves no reason to
 revert to a hand-written replacement for performance reason,

[ ].canFind( ) allocates on the GC heap without a sufficiently smart compiler.

That's then a performance issue which make may something like handful w= orth=20 it, but Andrei seems to be arguing based on aesthetics rather than=20 performance. And if you're arguing performance, I'd argue that the "in"= =20 solution is a bad one anyway, because it requires constructing and retu= rning a=20 struct, whereas you could just make what you're looking for the first a= rgument.=20 e.g. if(among(value, value1, value2, value3)) {} The syntax is less clear this way, and perhaps the syntactic convenienc= e of=20 the whole in idea outweighs the performcance cost there (particularly s= ince it=20 should still be cheaper than a heap allocation), but the only reason to= argue=20 against canFind that I can see is performance, and if you're arguing=20= performance, then I'm not sure that the in idea is necessarily the way = to go. Regardless, the point is that there needs to be a practical reason for=20= something like handful, not an aesthetic one. - Jonathan M Davis
Sep 03 2012