-
-
Notifications
You must be signed in to change notification settings - Fork 706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix 9906: extend unaryFun and binaryFun to recognize function objects #2556
Conversation
|
N.B. please don't merge yet, as a bug/quirk with |
|
what's the problem with non-static opCall? It just means that fun is a function-like object, and should be called directly. |
|
I'd like map/filter to accept arrays and associative arrays, and not just functions: (This is a common idiom in Clojure. Arrays and associative arrays can be seen as functions defined by an enumeration of input-outputs.) |
|
@DmitryOlshansky The problem is that if you have, say, a class |
|
@bearophile That looks like another enhancement request. |
|
Hmm, actually, it may not be that hard to implement after all: |
|
@quickfur: >That looks like another enhancement request. Yes, it's part of Issue 8715, but when the amount of added code is small enough I sometimes suggest to bundle enhancements. |
|
Added |
|
Added |
|
@quickfur: good, with this change I'll shorten/simplify several spots in my codebase. Perhaps unaryFun/binaryFun ddocs or some std.algorithm documentation examples should show the new possibilities. |
|
Updated ddocs. Migrated to ddoc'd unittests. |
|
Looks nice. In the meantime I have opened another small ER: https://issues.dlang.org/show_bug.cgi?id=13546 It's related but it's sufficiently different that I think it's better to not bundle it with this patch. |
|
The "goal" of unaryfun was originally only to allow string lambdas, and to forward everything else. When the passed "fun" was a not a string, the unaryFun is designed to be a no-op. The idea is that if you aren't using string lambdas, then you shouldn't need to use unaryFun. In fact, I think I can think of at least 1 "new" function in std.algorithm that does not provide support for string lambdas, and as such, does not use It seems like this change is trying to bake new functionality into What I mean is that if this passes: void foo(alias fun, T)(T t)
{
static assert(!is(typeof(fun) : string));
unaryFun!fun(t)
}Then this better damn well pass too: void foo(alias fun, T)(T t)
{
static assert(!is(typeof(fun) : string));
fun(t)
}So I'm OK for the static opCall thing, but against the opIndex support. Also, I'm not actually convinced yet that array=>function is a good idea in and out of itself... |
Absolutely awesome thing for lookup tables, but I agreed it better be a separate entity. Agreed on other points. |
Yes, because it's a very compact and general way to introduce new capabilities into all algorithms. Doing the same changes to every algorithm is a lot more work.
Take a look at Clojure code. We should make D more flexible reducing the unnecessary friction between parts. Arrays are a mapping, so this allows you to abstract away the irrelevant detail of the difference between a function and an array. |
|
@DmitryOlshansky: >but I agreed it better be a separate entity What do you mean? We're already able to write a lambda like "k => aa[k]", the point of this change is to shorten the code and make it more clean, hiding an unnecessary difference between arrays and functions. |
Arrays are objects you can get the length of, slice, append to, pop etc. I don't really agree that it's So even though you'd have And I definitively disagree that unary fun should be implicitly indexing RA ranges... especially since those could have (static) However, I think providing an functor-like adaptor is a good compromise. |
|
I'm against adding support for arrays at this level of abstraction, we should stick to the principle of least surprise. I'd much rather see The situation is bad enough as it is with string lambdas, let's not make algorithm predicates even more "special". |
|
@JakobOvrum: >we should stick to the principle of least surprise. I'd much rather see indices.map!(i => range[i]) than indices.map!range in user code - it's not that much longer to type but is much more readable and requires no prior knowledge of special handling hidden away in std.functional. I think the use of arrays as callables is sufficiently natural and avoids some noise:
I agree that in Clojure (and Scala too?) the situation is a little different, because arrays are seen as callables at all abstraction levels. |
|
I am with @JakobOvrum here. Such special case for arrays is very surprising unless you have aready encountered it before. |
Structs or classes with static `opCall` should be recognized as valid function objects.
Per PR discussion.
|
Alright, let's leave the AA/array extensions out of this PR for now. Let's just fix the opCall issue first, then we can discuss the merits of adding the AA/array extensions (or not). |
|
ping @Dicebot |
|
Are objects with no-static |
|
Hmm. Apparently the current code doesn't work with non-static |
|
Heh, actually, this problem is what I originally predicted in my second comment from the top. :) Function objects used to work fine, but this fix broke them because the new static if is too broad; it should only pick up static |
|
Alright, should be fixed now. |
|
Thanks, LGTM |
|
Auto-merge toggled on |
|
Thanks! |
Fix 9906: extend unaryFun and binaryFun to recognize function objects
Structs or classes with static
opCallshould be recognized as validfunction objects.
Fixes: https://issues.dlang.org/show_bug.cgi?id=9906