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

unnecessary_lambda_linter() misses '!' when suggesting removing a lambda #2742

Open
MichaelChirico opened this issue Feb 13, 2025 · 5 comments
Labels
false-positive code that shouldn't lint, but does
Milestone

Comments

@MichaelChirico
Copy link
Collaborator

lint(text = "sapply(x, function(xi) !all.equal(xi, y))", linters = unnecessary_lambda_linter())
# <text>:1:11: warning: [unnecessary_lambda_linter] Pass all.equal directly as a symbol to sapply() instead of wrapping it in an unnecessary anonymous function. For example, prefer lapply(DF, sum) to lapply(DF, function(x) sum(x)).
# sapply(x, function(xi) !all.equal(xi, y))
#           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

We could do sapply(x, Negate(all.equal), y), I think, but that's hardly a strict improvement.

@MichaelChirico MichaelChirico added the false-positive code that shouldn't lint, but does label Feb 13, 2025
@MichaelChirico MichaelChirico added this to the 3.3.0 milestone Feb 13, 2025
@AshesITR
Copy link
Collaborator

Is !all.equal(x, y) even well formed, given that all.equal() can return character?

Even so, would !sapply(x, all.equal, y) not work?

@MichaelChirico
Copy link
Collaborator Author

Indeed that usage should be changed to !isTRUE(all.equal(...)). Some one else's code, I promise 😜

I also saw it hitting on !is.null(.) which is more normal.

I think you're right moving the ! out is usually preferable but I couldn't quickly convince myself it's always possible, so I think it makes sense to be conservative and not lint. And presumably it misses other unary operators for the same reason.

@MichaelChirico
Copy link
Collaborator Author

Indeed:

lint(text = "sapply(x, function(xi) -foo(xi))", linters = unnecessary_lambda_linter())
# <text>:1:11: warning: [unnecessary_lambda_linter] Pass foo directly as a symbol to sapply() instead of wrapping it in an unnecessary anonymous function. For example, prefer lapply(DF, sum) to lapply(DF, function(x) sum(x)).
# sapply(x, function(xi) -foo(xi))
#           ^~~~~~~~~~~~~~~~~~~~~

Still - (and even more rarely, unary +) usually should be moved outside...

@AshesITR
Copy link
Collaborator

I would suspect this is only a problem when the unary operations dispatch to different implementations within the loop (say the inner function can return different types with different negation semantics and the sapply() unifies the types)

I'd keep it as a feature unless a real life false positive pops up.

@MichaelChirico
Copy link
Collaborator Author

I would suspect this is only a problem when the unary operations dispatch to different implementations within the loop (say the inner function can return different types with different negation semantics and the sapply() unifies the types)

Right, exactly.

At a minimum, we need to fix the lint message, which is incorrect in this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
false-positive code that shouldn't lint, but does
Projects
None yet
Development

No branches or pull requests

2 participants