Skip to content
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

Allow function negation -f to work like !f #55920

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mcabbott
Copy link
Contributor

We have !f === (!)∘f to negate any boolean function. Was there ever discussion of making -f === (-)∘f too? Both are small conveniences to avoid defining x -> op(x). This one would allow for example:

julia> A = reshape(1:16,4,4);

julia> eigvals(A; sortby=-real)  # does not accept rev=true
4-element Vector{ComplexF64}:
     36.209372712298546 + 0.0im
 -4.146487327145629e-17 + 1.9341169324764503e-16im
 -4.146487327145629e-17 - 1.9341169324764503e-16im
     -2.209372712298546 + 0.0im

julia> sum(-log, A; dims=1)  # -sum allocates twice
1×4 Matrix{Float64}:
 -3.17805  -7.42655  -9.38261  -10.6846

This will not change the fact that -f.(xs) means -(f.(xs)), when usually fused @. -f(xs) would be better. (Unless you write (-f).(xs) by hand.)

Needs tests obviously, but RFC?

@giordano giordano added needs tests Unit tests are required for this change kind:feature Indicates new feature / enhancement requests labels Sep 28, 2024
@jariji
Copy link
Contributor

jariji commented Sep 28, 2024

I'm not necessarily opposed to this but I'll raise some downsides.

(1) Defining functionality for functions that doesn't work on general callables means we can't use it in functions that take generic callable argument.

(2) Related, -a is already syntax for AbstractArray while !a isn't, so a callable AbstractArray might have confusing behavior if the -a is different under function application versus indexing. I don't know of any examples like that but there might be some.

(3) I don't like special case syntax: I think it would be better if instead of adding !f and -f to avoid the extra characters in (!)∘f, we could have instead !∘f and -∘f -- without the parentheses -- that would just work and be almost as convenient as the special cases.

This method requires at least Julia 1.12.
"""
-(f::Function) = (-) ∘ f
-(f::ComposedFunction{typeof(-)}) = f.inner #allows -(-f) === f
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method seems fit for an independent PR. I think it'd be merged easier than the feature addition.

@nsajko nsajko added needs docs Documentation for this change is required needs news A NEWS entry is required for this change labels Sep 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:feature Indicates new feature / enhancement requests needs docs Documentation for this change is required needs news A NEWS entry is required for this change needs tests Unit tests are required for this change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants