Jump to page: 1 2
Thread overview
extend "in" to all array types
Jan 15, 2014
pplantinga
Jan 15, 2014
Adam D. Ruppe
Jan 15, 2014
John Colvin
Jan 15, 2014
Meta
Jan 15, 2014
Ali Çehreli
Jan 15, 2014
H. S. Teoh
Jan 16, 2014
Jakob Ovrum
Jan 16, 2014
Jakob Ovrum
Jan 15, 2014
John Colvin
Jan 15, 2014
Meta
Jan 15, 2014
Tobias Pankrath
Jan 15, 2014
Namespace
Jan 16, 2014
Jakob Ovrum
Jan 15, 2014
Brad Anderson
Jan 16, 2014
luka8088
Jan 16, 2014
Jakob Ovrum
January 15, 2014
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
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
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
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
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
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
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
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
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
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

« First   ‹ Prev
1 2