Roslyn: Negating a function

Created on 19 Jan 2017  Â·  8Comments  Â·  Source: dotnet/roslyn

It would be nice to be able to negate a function when doing this:

.Where(i => !imageBank.Images.Contains(i))

So I only have to write this:

.Where(!imageBank.Images.Contains)
Area-Language Design

Most helpful comment

@bjorn-ali-goransson,

It's important to remember that:
cs .Where(imageBank.Images.Contains)
is not shorthand for:
cs .Where(i => imageBank.Images.Contains(i))
it's shorthand for:
cs .Where(new Func<Image, bool>(imageBank.Images.Contains))
What you are requesting is the auto-creation of lambdas from method groups, which is a different thing.

All 8 comments

Currently, when you write .Where(imageBank.Images.Contains), the compiler follows the rules in §6.6 Method group conversions, from the language specification, So if the compiler can select a method from that group that is compatible with the delegate, D, specified by Where(D), then it substitutes the expression with that method.

What you are requesting would be a whole new conversion, along the lines of: if the expression E (!imageBank.Images.Contains in this case) is formed of ! followed by a method group, then if that group contains a method that both returns a bool and is compatible with the delegate D, then substitute E for a new lambda i => !SelectedMethod(i) and then apply the existing lambda rules to this new expression.

So not impossible, but not a trivial change either.

Yes, actually, having ! in front of a Function<,,, bool> reference could negate it, creating another lambda.

Func<int, bool> zero = i => i == 0;
Func<int, bool> nonZero = !zero;

Converted to:

Func<int, bool> nonZero = i => !zero(i);

So it could be useful to more than method groups.

@bjorn-ali-goransson

Today the following is an assignment:

Func<int, bool> zero = i => i == 0;
Func<int, bool> nonZero = zero;

but what you're proposing is for the following:

Func<int, bool> zero = i => i == 0;
Func<int, bool> nonZero = !zero;

to be a function call?

No, it would create a new function with a negated result of the first one.

2017-01-19 14:26 GMT+01:00 Eyal Solnik notifications@github.com:

@bjorn-ali-goransson https://github.com/bjorn-ali-goransson

So the following would be an assignment:

Func zero = i => i == 0;
Func nonZero = zero;

whereas the following:

Func zero = i => i == 0;
Func nonZero = !zero;

would be a function call?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/roslyn/issues/16613#issuecomment-273775574,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAoyAPS5Nckj1BRXtxL9XtERLHonjDusks5rT2SMgaJpZM4Ln9fB
.

If "Extension Everything" could cover delegates you might be able to define a unary negation operator on the target delegate types.

Having the operator apply to arbitrary method groups seems a little overkill, especially given that the compiler has to work out what !imageBank.Images.Contains means and its expression type before it can concern itself with resolving any specific methods. Also, applying the operator by wrapping the delegate in another delegate which would handle the negation would cause a performance penalty. Seems complicated for something solved so easily already.

Yes, but please remember that once you start utilizing method group
expression substitution ie in Linq, it quickly becomes very addictive.

tors 19 jan. 2017 kl. 15:22 skrev HaloFour notifications@github.com:

If "Extension Everything" could cover delegates you might be able to
define a unary negation operator on the target delegate types.

Having the operator apply to arbitrary method groups seems a little
overkill, especially given that the compiler has to work out what
!imageBank.Images.Contains means and its expression type before it can
concern itself with resolving any specific methods. Also, applying the
operator by wrapping the delegate in another delegate which would handle
the negation would cause a performance penalty. Seems complicated for
something solved so easily already.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/roslyn/issues/16613#issuecomment-273788201,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAoyALKZ7oiZ_6ZGgc78mool4zgLwTFEks5rT3GNgaJpZM4Ln9fB
.

@bjorn-ali-goransson,

It's important to remember that:
cs .Where(imageBank.Images.Contains)
is not shorthand for:
cs .Where(i => imageBank.Images.Contains(i))
it's shorthand for:
cs .Where(new Func<Image, bool>(imageBank.Images.Contains))
What you are requesting is the auto-creation of lambdas from method groups, which is a different thing.

If I need to do something like this I would prefer add this to corefx instead

```C#
public static IEnumerable WithOut(this IEnumerable items,Func func) { ... }
////
list.WithOut(imageBank.Images.Contains);

Or maybe

```C#
list.GroupBy(imageBank.Images.Contains).First((group) => !group.Id);
Was this page helpful?
0 / 5 - 0 ratings