Thread overview | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 15, 2014 extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
In python, I really like the ability to check if an element is in an array: if x in array: # do something D has this, but only for associative arrays. Is there any chance we could extend this to every kind of array? |
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to pplantinga | On Wednesday, 15 January 2014 at 15:30:35 UTC, pplantinga wrote:
> Is there any chance we could extend this to every kind of array?
Probably not, since there's a significant speed difference between in associative array and in regular array. For a regular array, it means potentially looping over every item in the array. As a general rule, D likes to make long loops obvious in some way, like a different function name.
There are functions which do the same thing. Notably, std.algorithm.canFind
import std.algorithm;
if(array.canFind(x)) { /* do something */ }
You could also define your own function In if you wanted to keep the order that way:
bool In(T)(T lookFor, T[] lookIn) {
import std.algorithm;
return lookIn.canFind(lookFor);
}
if(x.In(array)) { /* do something */ }
It is capitalized so it doesn't clash with the keyword, and still uses the dot - it is a function called with dot syntax instead of an operator - but it works.
|
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to pplantinga | On Wednesday, 15 January 2014 at 15:30:35 UTC, pplantinga wrote:
> In python, I really like the ability to check if an element is in an array:
>
> if x in array:
> # do something
>
> D has this, but only for associative arrays. Is there any chance we could extend this to every kind of array?
import std.algorithm: canFind;
if(array.canFind(x))
//do something
alternatively, something like this:
struct InWrapper(T)
{
T unwrapped;
alias unwrapped this;
auto opBinaryRight(string op, T)(T el)
if(op == "in")
{
import std.algorithm : canFind;
return unwrapped.canFind(el);
}
}
unittest
{
InWrapper!(int[]) arr;
arr = [1,2,3,4];
assert(4 in arr);
assert(!(5 in arr));
}
|
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Wednesday, 15 January 2014 at 15:38:19 UTC, Adam D. Ruppe wrote:
> On Wednesday, 15 January 2014 at 15:30:35 UTC, pplantinga wrote:
>> Is there any chance we could extend this to every kind of array?
>
> Probably not, since there's a significant speed difference between in associative array and in regular array. For a regular array, it means potentially looping over every item in the array. As a general rule, D likes to make long loops obvious in some way, like a different function name.
>
> There are functions which do the same thing. Notably, std.algorithm.canFind
>
> import std.algorithm;
> if(array.canFind(x)) { /* do something */ }
>
>
> You could also define your own function In if you wanted to keep the order that way:
>
> bool In(T)(T lookFor, T[] lookIn) {
> import std.algorithm;
> return lookIn.canFind(lookFor);
> }
>
> if(x.In(array)) { /* do something */ }
>
> It is capitalized so it doesn't clash with the keyword, and still uses the dot - it is a function called with dot syntax instead of an operator - but it works.
or:
import std.functional : binaryReverseArgs;
import std.algorithm : canFind;
alias In = binaryReverseArgs!canFind;
|
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Wednesday, 15 January 2014 at 15:51:06 UTC, John Colvin wrote:
> On Wednesday, 15 January 2014 at 15:38:19 UTC, Adam D. Ruppe wrote:
>> On Wednesday, 15 January 2014 at 15:30:35 UTC, pplantinga wrote:
>>> Is there any chance we could extend this to every kind of array?
>>
>> Probably not, since there's a significant speed difference between in associative array and in regular array. For a regular array, it means potentially looping over every item in the array. As a general rule, D likes to make long loops obvious in some way, like a different function name.
>>
>> There are functions which do the same thing. Notably, std.algorithm.canFind
>>
>> import std.algorithm;
>> if(array.canFind(x)) { /* do something */ }
>>
>>
>> You could also define your own function In if you wanted to keep the order that way:
>>
>> bool In(T)(T lookFor, T[] lookIn) {
>> import std.algorithm;
>> return lookIn.canFind(lookFor);
>> }
>>
>> if(x.In(array)) { /* do something */ }
>>
>> It is capitalized so it doesn't clash with the keyword, and still uses the dot - it is a function called with dot syntax instead of an operator - but it works.
>
> or:
>
> import std.functional : binaryReverseArgs;
> import std.algorithm : canFind;
>
> alias In = binaryReverseArgs!canFind;
Programming in D is constantly mind-blowing as you realize how powerful the language is.
|
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Wednesday, 15 January 2014 at 15:48:13 UTC, John Colvin wrote:
> On Wednesday, 15 January 2014 at 15:30:35 UTC, pplantinga wrote:
>> In python, I really like the ability to check if an element is in an array:
>>
>> if x in array:
>> # do something
>>
>> D has this, but only for associative arrays. Is there any chance we could extend this to every kind of array?
>
> import std.algorithm: canFind;
>
> if(array.canFind(x))
> //do something
>
>
> alternatively, something like this:
>
> struct InWrapper(T)
> {
> T unwrapped;
> alias unwrapped this;
>
> auto opBinaryRight(string op, T)(T el)
> if(op == "in")
> {
> import std.algorithm : canFind;
> return unwrapped.canFind(el);
> }
> }
>
> unittest
> {
> InWrapper!(int[]) arr;
> arr = [1,2,3,4];
>
> assert(4 in arr);
> assert(!(5 in arr));
> }
auto inWrap(T)(T[] arr)
{
static struct InWrapper
{
import std.typecons: Nullable;
private T[] payload;
Nullable!size_t opBinaryRight(string op: "in")(T val)
{
Nullable!size_t index;
foreach (i, element; payload)
{
if (element == val)
{
index = i;
return index;
}
}
return index;
}
}
return InWrapper(arr);
}
void main()
{
auto arr = [0, 1, 2, 3, 4];
auto i = 2 in arr.inWrap;
assert(!i.isNull);
assert(i == 2);
}
|
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On Wednesday, 15 January 2014 at 17:13:37 UTC, Meta wrote:
>
> auto inWrap(T)(T[] arr)
> {
> static struct InWrapper
> {
> import std.typecons: Nullable;
>
> private T[] payload;
>
> Nullable!size_t opBinaryRight(string op: "in")(T val)
> {
> Nullable!size_t index;
> foreach (i, element; payload)
> {
> if (element == val)
> {
> index = i;
>
> return index;
> }
> }
>
> return index;
> }
> }
>
> return InWrapper(arr);
> }
>
> void main()
> {
> auto arr = [0, 1, 2, 3, 4];
> auto i = 2 in arr.inWrap;
> assert(!i.isNull);
> assert(i == 2);
> }
The in-operator should return T* for consistency with the build-in ones.
|
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On Wednesday, 15 January 2014 at 17:29:07 UTC, Tobias Pankrath wrote:
> On Wednesday, 15 January 2014 at 17:13:37 UTC, Meta wrote:
>>
>> auto inWrap(T)(T[] arr)
>> {
>> static struct InWrapper
>> {
>> import std.typecons: Nullable;
>>
>> private T[] payload;
>>
>> Nullable!size_t opBinaryRight(string op: "in")(T val)
>> {
>> Nullable!size_t index;
>> foreach (i, element; payload)
>> {
>> if (element == val)
>> {
>> index = i;
>>
>> return index;
>> }
>> }
>>
>> return index;
>> }
>> }
>>
>> return InWrapper(arr);
>> }
>>
>> void main()
>> {
>> auto arr = [0, 1, 2, 3, 4];
>> auto i = 2 in arr.inWrap;
>> assert(!i.isNull);
>> assert(i == 2);
>> }
>
> The in-operator should return T* for consistency with the build-in ones.
That was exactly my thoughts:
----
auto each(T)(T[] arr) pure nothrow {
static struct InWrapper {
private T[] payload;
T* opBinaryRight(string op : "in")(T val) pure nothrow {
foreach (ref T element; payload) {
if (element == val)
return &element;
}
return null;
}
}
return InWrapper(arr);
}
void main() {
int[] arr = [0, 1, 2, 3, 4];
auto i = 2 in arr.each;
assert(i !is null);
assert(*i == 2);
}
----
Something like that should really be in std.array.
|
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On Wednesday, 15 January 2014 at 17:29:07 UTC, Tobias Pankrath wrote:
> On Wednesday, 15 January 2014 at 17:13:37 UTC, Meta wrote:
>>
>> auto inWrap(T)(T[] arr)
>> {
>> static struct InWrapper
>> {
>> import std.typecons: Nullable;
>>
>> private T[] payload;
>>
>> Nullable!size_t opBinaryRight(string op: "in")(T val)
>> {
>> Nullable!size_t index;
>> foreach (i, element; payload)
>> {
>> if (element == val)
>> {
>> index = i;
>>
>> return index;
>> }
>> }
>>
>> return index;
>> }
>> }
>>
>> return InWrapper(arr);
>> }
>>
>> void main()
>> {
>> auto arr = [0, 1, 2, 3, 4];
>> auto i = 2 in arr.inWrap;
>> assert(!i.isNull);
>> assert(i == 2);
>> }
>
> The in-operator should return T* for consistency with the build-in ones.
I was thinking recently it'd be even more convenient if it returned std.typecons.Nullable. Then you get alias this and aren't having to constantly dereference it yourself.
|
January 15, 2014 Re: extend "in" to all array types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On 01/15/2014 07:38 AM, Adam D. Ruppe wrote: > Probably not, since there's a significant speed difference between in > associative array and in regular array. For a regular array, it means > potentially looping over every item in the array. And a specialization for std.range.SortedRange would use binary search: http://dlang.org/phobos/std_range.html#.SortedRange Ali |
Copyright © 1999-2021 by the D Language Foundation