## digitalmars.D - either

Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
```I wrote a simple helper, in spirit with some recent discussions:

// either
struct Either(Ts...)
{
Tuple!Ts data_;
bool opEquals(E)(E e)
{
foreach (i, T; Ts)
{
if (data_[i] == e) return true;
}
return false;
}
}

auto either(Ts...)(Ts args)
{
return Either!Ts(tuple(args));
}

unittest
{
assert(1 == either(1, 2, 3));
assert(4 != either(1, 2, 3));
assert("abac" != either("aasd", "s"));
assert("abac" == either("aasd", "abac", "s"));
}

Turns out this is very useful in a variety of algorithms. I just don't
know where in std this helper belongs! Any ideas?

Andrei
```
Jan 09 2011
=?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench robertmuench.de> writes:
```On 2011-01-09 19:42:22 +0100, Andrei Alexandrescu said:

I wrote a simple helper, in spirit with some recent discussions:

Hi, EITHER normaly means: This or that, so it's more like an IF/ELSE.
How about ANY? IMO

1==any(1, 2, 3)

describes pretty good what is meant.

--
Robert M. Münch
http://www.robertmuench.de
```
Jan 09 2011
Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
```I think "any" is used in Python IIRC, so I'll have to go +1 with Robert here.
```
Jan 09 2011
bearophile <bearophileHUGS lycos.com> writes:
```Andrej Mitrovic:

I think "any" is used in Python IIRC, so I'll have to go +1 with Robert here.

any() and all() in Python have a different purpose, the first is true if one or
more than the given items is true, and the second is true if they all true:

all([1, 2, 4])

True
all(["", None, 0])

False
all(["", None, 1])

False
any(["", None, 1])

True
any([1, 2, 4])

True
any(["", None, 0])

False

Bye,
bearophile
```
Jan 09 2011
Daniel Gibson <metalcaedes gmail.com> writes:
```Am 09.01.2011 19:48, schrieb Robert M. Münch:
On 2011-01-09 19:42:22 +0100, Andrei Alexandrescu said:

I wrote a simple helper, in spirit with some recent discussions:

Hi, EITHER normaly means: This or that, so it's more like an IF/ELSE.
How about ANY? IMO

1==any(1, 2, 3)

describes pretty good what is meant.

I agree.
```
Jan 09 2011
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
```On 1/9/11 1:12 PM, Daniel Gibson wrote:
Am 09.01.2011 19:48, schrieb Robert M. Münch:
On 2011-01-09 19:42:22 +0100, Andrei Alexandrescu said:

I wrote a simple helper, in spirit with some recent discussions:

Hi, EITHER normaly means: This or that, so it's more like an IF/ELSE.
How about ANY? IMO

1==any(1, 2, 3)

describes pretty good what is meant.

I agree.

Problem with any/either is that it encodes the comparison inside the
data. You can do == and !=, but algorithms want to work with general
predicates, and any can't work with arbitrary predicates - unless the
predicates themselves are designed to work with it.

For now I added this to std.algorithm:

/**
Consume all elements from \$(D r) that are equal to one of the elements
\$(D es).
*/
void skipAll(alias pred = "a == b", R, Es...)(ref R r, Es es)
{
loop:
for (; !r.empty; r.popFront())
{
foreach (i, E; Es)
{
if (binaryFun!pred(r.front, es[i]))
{
continue loop;
}
}
break;
}
}

unittest
{
auto s1 = "Hello world";
skipAll(s1, 'H', 'e');
assert(s1 == "llo world");
}

I wonder if it's worthwhile encoding the predicate inside the compared
elements. In that case, any would return a type that also has the
predicate. Something like this:

struct Any(alias pred = "a == b", Es...) { ... }

Then you'd put the predicate by the call to any, not by the call to the
algorithm:

skipAll(r, any!"a > b"(x, y, z));

Then skipAll doesn't need to worry about the predicate - it just uses ==
and !=.

If this paradigm has a landslide advantage over the current structure,
we'd need to rewrite a lot of std.algorithm.

Andrei
```
Jan 09 2011
Mafi <mafi example.org> writes:
```Am 09.01.2011 19:42, schrieb Andrei Alexandrescu:
I wrote a simple helper, in spirit with some recent discussions:

// either
struct Either(Ts...)
{
Tuple!Ts data_;
bool opEquals(E)(E e)
{
foreach (i, T; Ts)
{
if (data_[i] == e) return true;
}
return false;
}
}

auto either(Ts...)(Ts args)
{
return Either!Ts(tuple(args));
}

unittest
{
assert(1 == either(1, 2, 3));
assert(4 != either(1, 2, 3));
assert("abac" != either("aasd", "s"));
assert("abac" == either("aasd", "abac", "s"));
}

Turns out this is very useful in a variety of algorithms. I just don't
know where in std this helper belongs! Any ideas?

Andrei

This is exactly what I did today. In perl 6 it's called any which I
think is a better name. There also 'none', 'all' and 'one'. There seems
to be strange bug with the opEquals. Everything works but if you replace
the opEquals template with it's actual instantiation dmd cry at you. See
http://www.digitalmars.com/d/2.0/operatoroverloading.html#equals  and my
last post.
```
Jan 09 2011
Tomek =?ISO-8859-2?Q?Sowi=F1ski?= <just ask.me> writes:
```Andrei Alexandrescu napisa=B3:

I wrote a simple helper, in spirit with some recent discussions:
=20
// either
struct Either(Ts...)
{
Tuple!Ts data_;
bool opEquals(E)(E e)
{
foreach (i, T; Ts)
{
if (data_[i] =3D=3D e) return true;
}
return false;
}
}
=20
auto either(Ts...)(Ts args)
{
return Either!Ts(tuple(args));
}
=20
unittest
{
assert(1 =3D=3D either(1, 2, 3));
assert(4 !=3D either(1, 2, 3));
assert("abac" !=3D either("aasd", "s"));
assert("abac" =3D=3D either("aasd", "abac", "s"));
}

I really don't dig the whole helper structs with overloaded operators thing=
. It complicates the implementation (more work for compiler to grok and inl=
ine) and you're never really sure what it does unless you read the docs (or=
the complicated implementation).

It should be as simple as this:

bool any(E, Ts...)(E e, Ts args) {
foreach (a; args)
if (a =3D=3D e)
return true;
return false;
}

unittest
{
assert(!"abac".any("aasd", "s"));
assert("abac".any("aasd", "abac", "s"));
// assert(1.any(1,2,3));    // doesn't compile for now, bug 3382
}

Turns out this is very useful in a variety of algorithms.

Very!

I just don't=20
know where in std this helper belongs! Any ideas?

Maybe std.algorithm? It bears vague resemblance to max().

--=20
Tomek
```
Jan 09 2011
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
```On 1/9/11 2:09 PM, Tomek Sowiñski wrote:
I really don't dig the whole helper structs with overloaded operators thing.
It complicates the implementation (more work for compiler to grok and inline)
and you're never really sure what it does unless you read the docs (or the
complicated implementation).

It should be as simple as this:

bool any(E, Ts...)(E e, Ts args) {
foreach (a; args)
if (a == e)
return true;
return false;
}

unittest
{
assert(!"abac".any("aasd", "s"));
assert("abac".any("aasd", "abac", "s"));
// assert(1.any(1,2,3));    // doesn't compile for now, bug 3382
}

Turns out this is very useful in a variety of algorithms.

Very!

I just don't
know where in std this helper belongs! Any ideas?

Maybe std.algorithm? It bears vague resemblance to max().

Aha, so this encodes the predicate in the operation. With a general
predicate, that would be:

if (any!"a != b"(expr, 1, 2, 5)) { ... }

The advantage over

if (expr != 1 || expr != 2 || expr != 5)) { ... }

is terseness and the guarantee that expr is evaluated once (which is
nice at least for my code).

This looks promising and well integrated with the rest of Phobos. Should
I add it? And if I do, is "any" the name?

Andrei
```
Jan 09 2011
Tomek =?ISO-8859-2?Q?Sowi=F1ski?= <just ask.me> writes:
```Andrei Alexandrescu napisa=B3:

Aha, so this encodes the predicate in the operation. With a general=20
predicate, that would be:
=20
if (any!"a !=3D b"(expr, 1, 2, 5)) { ... }
=20
The advantage over
=20
if (expr !=3D 1 || expr !=3D 2 || expr !=3D 5)) { ... }
=20
is terseness and the guarantee that expr is evaluated once (which is=20
nice at least for my code).

Yes.

This looks promising and well integrated with the rest of Phobos. Should=

=20
I add it?

Please do. Oh, thinking about it 10 more minutes, an improvement struck me:

bool any(alias pred =3D "a=3D=3Db", E, Ts...)(E e, Ts args) if(Ts.length > =
1 || !isTuple!Ts) {
foreach (a; args)
if (binaryFun!pred(a, e))
return true;
return false;
}

unittest
{
assert(!"abac".any("s"));
assert(!"abac".any("aasd", "s"));
assert("abac".any("aasd", "abac", "s"));
}

/// Unpacks a single tuple.
bool any(alias pred =3D "a=3D=3Db", E, T)(E e, T t) if(isTuple!T) {
return any!(pred, E, T.Types)(e, t.field);
}

unittest
{
assert(any("abac", tuple("aasd", "abac", "s")));
assert(find!any([5,3,7,9,4,5,7], tuple(2,4,6)) =3D=3D [4,5,7]);    // =
cool!
}

And if I do, is "any" the name?

For a start. We can always vote it to sth more descriptive e.g. 'isAny' in =
case 'any' turns out misleading.

--=20
Tomek
```
Jan 09 2011
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
```On 1/9/11 3:13 PM, Tomek Sowiñski wrote:
Andrei Alexandrescu napisa³:

Aha, so this encodes the predicate in the operation. With a general
predicate, that would be:

if (any!"a != b"(expr, 1, 2, 5)) { ... }

The advantage over

if (expr != 1 || expr != 2 || expr != 5)) { ... }

is terseness and the guarantee that expr is evaluated once (which is
nice at least for my code).

Yes.

This looks promising and well integrated with the rest of Phobos. Should
I add it?

Please do. Oh, thinking about it 10 more minutes, an improvement struck me:

bool any(alias pred = "a==b", E, Ts...)(E e, Ts args) if(Ts.length>  1 ||
!isTuple!Ts) {
foreach (a; args)
if (binaryFun!pred(a, e))
return true;
return false;
}

unittest
{
assert(!"abac".any("s"));
assert(!"abac".any("aasd", "s"));
assert("abac".any("aasd", "abac", "s"));
}

/// Unpacks a single tuple.
bool any(alias pred = "a==b", E, T)(E e, T t) if(isTuple!T) {
return any!(pred, E, T.Types)(e, t.field);
}

unittest
{
assert(any("abac", tuple("aasd", "abac", "s")));
assert(find!any([5,3,7,9,4,5,7], tuple(2,4,6)) == [4,5,7]);    // cool!
}

Hm, I don't see why not asking the owner of the tuple to type .expand.

And if I do, is "any" the name?

For a start. We can always vote it to sth more descriptive e.g. 'isAny' in
case 'any' turns out misleading.

At best we'd minimize such jitter.

Andrei
```
Jan 09 2011
Tomek =?ISO-8859-2?Q?Sowi=F1ski?= <just ask.me> writes:
```Andrei Alexandrescu napisa=B3:

bool any(alias pred =3D "a=3D=3Db", E, Ts...)(E e, Ts args) if(Ts.lengt=

h>  1 || !isTuple!Ts) {
foreach (a; args)
if (binaryFun!pred(a, e))
return true;
return false;
}

unittest
{
assert(!"abac".any("s"));
assert(!"abac".any("aasd", "s"));
assert("abac".any("aasd", "abac", "s"));
}

/// Unpacks a single tuple.
bool any(alias pred =3D "a=3D=3Db", E, T)(E e, T t) if(isTuple!T) {
return any!(pred, E, T.Types)(e, t.field);
}

unittest
{
assert(any("abac", tuple("aasd", "abac", "s")));
assert(find!any([5,3,7,9,4,5,7], tuple(2,4,6)) =3D=3D [4,5,7]);  =

// cool!
} =20

=20
Hm, I don't see why not asking the owner of the tuple to type .expand.

I'd ask the reverse question -- why "abc".any(tuple("cba", "abc")) shouldn'=
t mean "abc".any("cba", "abc") ? It's natural.

The only difficulty I see is behaving well for the degenerate case ("abc".a=
ny("abc") works, so tuple(1,2).any(tuple(1,2)) should work too). That, I be=
lieve, can be solved by additional template constraints on the unpacking ov=
erload.

Another good reason -- this doesn't compile:

assert(find!any([5,3,7,9,4,5,7], tuple(2,4,6).expand) =3D=3D [4,5,7]);

test.d(24): Error: template std.algorithm.find(alias pred =3D "a =3D=3D b",=
R,E) if (isInputRange!(R) && is(typeof(binaryFun!(pred)(haystack.front,need=
le)) : bool)) does not match any function template declaration
test.d(24): Error: template std.algorithm.find(alias pred =3D "a =3D=3D b",=
R,E) if (isInputRange!(R) && is(typeof(binaryFun!(pred)(haystack.front,need=
le)) : bool)) cannot deduce template function from argument types !(any)(in=
t[],int,int,int)
test.d(24): Error: template instance errors instantiating template

--=20
Tomek
```
Jan 09 2011
Jonathan M Davis <jmdavisProg gmx.com> writes:
```On Sunday 09 January 2011 12:28:23 Andrei Alexandrescu wrote:
On 1/9/11 2:09 PM, Tomek Sowi=F1ski wrote:
I really don't dig the whole helper structs with overloaded operators
thing. It complicates the implementation (more work for compiler to grok
and inline) and you're never really sure what it does unless you read
the docs (or the complicated implementation).
=20
It should be as simple as this:
=20
bool any(E, Ts...)(E e, Ts args) {
=20
foreach (a; args)
=20
if (a =3D=3D e)
=20
return true;
=20
return false;
=20
}
=20
unittest
{
=20
assert(!"abac".any("aasd", "s"));
assert("abac".any("aasd", "abac", "s"));
// assert(1.any(1,2,3));    // doesn't compile for now, bug 3382
=20
}
=20
Turns out this is very useful in a variety of algorithms.

=20
Very!
=20
I just don't
know where in std this helper belongs! Any ideas?

=20
Maybe std.algorithm? It bears vague resemblance to max().

=20
Aha, so this encodes the predicate in the operation. With a general
predicate, that would be:
=20
if (any!"a !=3D b"(expr, 1, 2, 5)) { ... }
=20
The advantage over
=20
if (expr !=3D 1 || expr !=3D 2 || expr !=3D 5)) { ... }
=20
is terseness and the guarantee that expr is evaluated once (which is
nice at least for my code).
=20
This looks promising and well integrated with the rest of Phobos. Should
I add it? And if I do, is "any" the name?

Well, I would expect any to be used for testing whether a predicate is true=
for=20
any element in a given range (as discussed in=20
http://d.puremagic.com/issues/show_bug.cgi?id=3D4405 ), which is similar to=
what=20
canFind() already does (though I'd very much like generalized any() and all=
()=20
functions as discussed in that enhancement request).

Here, you are trying to do something similar, but in essence, you're giving=
it=20
the needle first and then variadic lists to make up the haystack. It makes =
me=20
want to try and combine what you're trying to do with any()/canFind(), but =
given=20
that that would entail flipping the predicate, I'm not sure that that would=
work=20
very well.

Actually, I'd wonder if it would make sense to try and give an overload of=
=20
std.algorithm.equal() which does what you're trying to do here. Either that=
or=20
make it equalAny(), since it's using a predicate for equality in the same s=
ense=20
that equal() is.

Regardless, I'd quite like any() to be used for checking whether a predicat=
e is=20
true for any element in a given range (with all() being used to check wheth=
er=20
the predicate is true for all of the elements of a range), and using any() =
for=20
what you're suggesting goes against that, even though it's quite similar.

=2D Jonathan M Davis
```
Jan 09 2011
"Nick Sabalausky" <a a.a> writes:
```"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
news:igcvll\$29k5\$1 digitalmars.com...
I wrote a simple helper, in spirit with some recent discussions:

// either
struct Either(Ts...)
{
Tuple!Ts data_;
bool opEquals(E)(E e)
{
foreach (i, T; Ts)
{
if (data_[i] == e) return true;
}
return false;
}
}

auto either(Ts...)(Ts args)
{
return Either!Ts(tuple(args));
}

unittest
{
assert(1 == either(1, 2, 3));
assert(4 != either(1, 2, 3));
assert("abac" != either("aasd", "s"));
assert("abac" == either("aasd", "abac", "s"));
}

Turns out this is very useful in a variety of algorithms. I just don't
know where in std this helper belongs! Any ideas?

For years I've just been doing this:

if( [1, 2, 3].contains(1) )

Although I think I needed to write a new "contains" to wrap existing
functions when I switched from Tango to Phobos.

Of course, "1 in [1,2,3]" would be much better ;) But whateever. Either way.

But I suppose your "either" avoids an allocation, doesn't it? (And I'd lean
more towards "any" than "either" like the other people).
```
Jan 09 2011
"Nick Sabalausky" <a a.a> writes:
```"Nick Sabalausky" <a a.a> wrote in message
news:igd57p\$2k1k\$1 digitalmars.com...
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
news:igcvll\$29k5\$1 digitalmars.com...
I wrote a simple helper, in spirit with some recent discussions:

// either
struct Either(Ts...)
{
Tuple!Ts data_;
bool opEquals(E)(E e)
{
foreach (i, T; Ts)
{
if (data_[i] == e) return true;
}
return false;
}
}

auto either(Ts...)(Ts args)
{
return Either!Ts(tuple(args));
}

unittest
{
assert(1 == either(1, 2, 3));
assert(4 != either(1, 2, 3));
assert("abac" != either("aasd", "s"));
assert("abac" == either("aasd", "abac", "s"));
}

Turns out this is very useful in a variety of algorithms. I just don't
know where in std this helper belongs! Any ideas?

For years I've just been doing this:

if( [1, 2, 3].contains(1) )

Although I think I needed to write a new "contains" to wrap existing
functions when I switched from Tango to Phobos.

Of course, "1 in [1,2,3]" would be much better ;) But whateever. Either
way.

But I suppose your "either" avoids an allocation, doesn't it? (And I'd
lean more towards "any" than "either" like the other people).

It'd be really cool to have that work for the other comparison operators,
too.
```
Jan 09 2011
Justin Johansson <noreply jj.com> writes:
```On 10/01/11 05:42, Andrei Alexandrescu wrote:
I wrote a simple helper, in spirit with some recent discussions:

// either
struct Either(Ts...)
{
Tuple!Ts data_;
bool opEquals(E)(E e)
{
foreach (i, T; Ts)
{
if (data_[i] == e) return true;
}
return false;
}
}

auto either(Ts...)(Ts args)
{
return Either!Ts(tuple(args));
}

unittest
{
assert(1 == either(1, 2, 3));
assert(4 != either(1, 2, 3));
assert("abac" != either("aasd", "s"));
assert("abac" == either("aasd", "abac", "s"));
}

Turns out this is very useful in a variety of algorithms. I just don't
know where in std this helper belongs! Any ideas?

Despite that it may be very useful as you say, personally I think it is
a fundamental no-no to overload the meaning of "==" in any manner that
does not preserve the generally accepted semantics of equality which
include the notions of reflexivity, symmetry and transitivity**.

**See http://en.wikipedia.org/wiki/Equality_%28mathematics%29

The symmetric and transitive properties of the equality relation imply
that if (a == c) is true and if (b == c) is true then (a == b) is also true.

In this case the semantics of the overloaded "==" operator have the
expressions 1 == either(1, 2, 3) and 2 == either(1, 2, 3) both
evaluating to true and by implication/expectation (1 == 2).

Clearly though, (1 == 2) evaluates to false in terms of the commonly
accepted meaning of equality.

Just my 2 cents and I wonder if there some other way of achieving the
desired functionality of your helper without resorting to overloading
"==" and the consequential violation of the commonly held semantics of
equality.

Cheers,
Justin Johansson
```
Jan 11 2011
KennyTM~ <kennytm gmail.com> writes:
```On Jan 11, 11 17:10, Justin Johansson wrote:
On 10/01/11 05:42, Andrei Alexandrescu wrote:
I wrote a simple helper, in spirit with some recent discussions:

// either
struct Either(Ts...)
{
Tuple!Ts data_;
bool opEquals(E)(E e)
{
foreach (i, T; Ts)
{
if (data_[i] == e) return true;
}
return false;
}
}

auto either(Ts...)(Ts args)
{
return Either!Ts(tuple(args));
}

unittest
{
assert(1 == either(1, 2, 3));
assert(4 != either(1, 2, 3));
assert("abac" != either("aasd", "s"));
assert("abac" == either("aasd", "abac", "s"));
}

Turns out this is very useful in a variety of algorithms. I just don't
know where in std this helper belongs! Any ideas?

Despite that it may be very useful as you say, personally I think it is
a fundamental no-no to overload the meaning of "==" in any manner that
does not preserve the generally accepted semantics of equality which
include the notions of reflexivity, symmetry and transitivity**.

**See http://en.wikipedia.org/wiki/Equality_%28mathematics%29

The symmetric and transitive properties of the equality relation imply
that if (a == c) is true and if (b == c) is true then (a == b) is also
true.

In this case the semantics of the overloaded "==" operator have the
expressions 1 == either(1, 2, 3) and 2 == either(1, 2, 3) both
evaluating to true and by implication/expectation (1 == 2).

Clearly though, (1 == 2) evaluates to false in terms of the commonly
accepted meaning of equality.

Just my 2 cents and I wonder if there some other way of achieving the
desired functionality of your helper without resorting to overloading
"==" and the consequential violation of the commonly held semantics of
equality.

Cheers,
Justin Johansson

We could use in instead of ==

if (1 in oneOf(1, 2, 3)) { ... }
if (4 !in oneOf(1, 2, 3)) { ... }
```
Jan 11 2011
Justin Johansson <noreply jj.com> writes:
```On 12/01/11 06:28, KennyTM~ wrote:
On Jan 11, 11 17:10, Justin Johansson wrote:
On 10/01/11 05:42, Andrei Alexandrescu wrote:
I wrote a simple helper, in spirit with some recent discussions:
unittest
{
assert(1 == either(1, 2, 3));
assert(4 != either(1, 2, 3));
assert("abac" != either("aasd", "s"));
assert("abac" == either("aasd", "abac", "s"));
}

Just my 2 cents and I wonder if there some other way of achieving the
desired functionality of your helper without resorting to overloading
"==" and the consequential violation of the commonly held semantics of
equality.

We could use in instead of ==

if (1 in oneOf(1, 2, 3)) { ... }
if (4 !in oneOf(1, 2, 3)) { ... }

Nice suggestion.

At the end of the day though it basically boils down to having either a
binary operator** or a function for it.

(** preferably excluding "==" and other undesirable operator overloads
of course).
```
Jan 11 2011
Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
```I don't really know what I'm up to, but I ended up making this thing:

https://gist.github.com/776604

I can't figure out how to make two nice templates called anySatisfy
and allSatisfy and make them call find and compare the lengths. So I
just ripped these two from std.typetuple and made them operate on
variadic arguments. Well, at least it's somewhat amusing to look at..
```
Jan 12 2011