digitalmars.D - either
- Andrei Alexandrescu (28/28) Jan 09 2011 I wrote a simple helper, in spirit with some recent discussions:
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (8/9) Jan 09 2011 Hi, EITHER normaly means: This or that, so it's more like an IF/ELSE.
- Andrej Mitrovic (1/1) Jan 09 2011 I think "any" is used in Python IIRC, so I'll have to go +1 with Robert ...
- bearophile (10/17) Jan 09 2011 True
- Daniel Gibson (2/8) Jan 09 2011 I agree.
- Andrei Alexandrescu (43/56) Jan 09 2011 Problem with any/either is that it encodes the comparison inside the
- Mafi (7/35) Jan 09 2011 This is exactly what I did today. In perl 6 it's called any which I
- Tomek =?ISO-8859-2?Q?Sowi=F1ski?= (22/53) Jan 09 2011 I really don't dig the whole helper structs with overloaded operators th...
- Andrei Alexandrescu (11/30) Jan 09 2011 Aha, so this encodes the predicate in the operation. With a general
- Tomek =?ISO-8859-2?Q?Sowi=F1ski?= (31/45) Jan 09 2011 =20
- Andrei Alexandrescu (4/43) Jan 09 2011 At best we'd minimize such jitter.
- Tomek =?ISO-8859-2?Q?Sowi=F1ski?= (21/47) Jan 09 2011 // cool!
- Jonathan M Davis (33/85) Jan 09 2011 Well, I would expect any to be used for testing whether a predicate is t...
- Nick Sabalausky (9/36) Jan 09 2011 For years I've just been doing this:
- Nick Sabalausky (4/46) Jan 09 2011 It'd be really cool to have that work for the other comparison operators...
- Justin Johansson (19/46) Jan 11 2011 Despite that it may be very useful as you say, personally I think it is
- KennyTM~ (4/55) Jan 11 2011 We could use in instead of ==
- Justin Johansson (6/25) Jan 11 2011 Nice suggestion.
- Andrej Mitrovic (6/6) Jan 12 2011 I don't really know what I'm up to, but I ended up making this thing:
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
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
I think "any" is used in Python IIRC, so I'll have to go +1 with Robert here.
Jan 09 2011
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:Trueall([1, 2, 4])Falseall(["", None, 0])Falseall(["", None, 1])Trueany(["", None, 1])Trueany([1, 2, 4])False Bye, bearophileany(["", None, 0])
Jan 09 2011
Am 09.01.2011 19:48, schrieb Robert M. Münch:On 2011-01-09 19:42:22 +0100, Andrei Alexandrescu said:I agree.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.
Jan 09 2011
On 1/9/11 1:12 PM, Daniel Gibson wrote:Am 09.01.2011 19:48, schrieb Robert M. Münch: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. AndreiOn 2011-01-09 19:42:22 +0100, Andrei Alexandrescu said:I agree.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.
Jan 09 2011
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? AndreiThis 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
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
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 }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? AndreiTurns 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().
Jan 09 2011
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==20I 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
On 1/9/11 3:13 PM, Tomek Sowiñski wrote:Andrei Alexandrescu napisa³:Hm, I don't see why not asking the owner of the tuple to type .expand.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! }At best we'd minimize such jitter. AndreiAnd 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.
Jan 09 2011
Andrei Alexandrescu napisa=B3:h> 1 || !isTuple!Ts) {bool any(alias pred =3D "a=3D=3Db", E, Ts...)(E e, Ts args) if(Ts.lengt=// cool!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]); =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} =20=20 Hm, I don't see why not asking the owner of the tuple to type .expand.
Jan 09 2011
On Sunday 09 January 2011 12:28:23 Andrei Alexandrescu wrote:On 1/9/11 2:09 PM, Tomek Sowi=F1ski wrote: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 DavisI 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=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?Turns out this is very useful in a variety of algorithms.=20 Very! =20I just don't know where in std this helper belongs! Any ideas?=20 Maybe std.algorithm? It bears vague resemblance to max().
Jan 09 2011
"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> wrote in message news:igd57p$2k1k$1 digitalmars.com..."Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:igcvll$29k5$1 digitalmars.com...It'd be really cool to have that work for the other comparison operators, too.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
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
On Jan 11, 11 17:10, Justin Johansson wrote:On 10/01/11 05:42, Andrei Alexandrescu wrote:We could use in instead of == if (1 in oneOf(1, 2, 3)) { ... } if (4 !in oneOf(1, 2, 3)) { ... }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
On 12/01/11 06:28, KennyTM~ wrote:On Jan 11, 11 17:10, Justin Johansson wrote: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).On 10/01/11 05:42, Andrei Alexandrescu wrote:We could use in instead of == if (1 in oneOf(1, 2, 3)) { ... } if (4 !in oneOf(1, 2, 3)) { ... }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.
Jan 11 2011
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