Skip to content

Conversation

sk-
Copy link
Contributor

@sk- sk- commented Nov 5, 2020

Operators should be implemented based on their in-place variants, not the other way around. In that way in-place operations won't allocate any new objects.

See #916 for more details.

This PR allows us to reenable the swiftlint rule shorthand_operator. It also refactors other operators to use their in-place variant to reduce code duplication.

Checklist

  • I checked the Contributing Guidelines before creating this request.
  • New extensions are written in Swift 5.0.
  • New extensions support iOS 10.0+ / tvOS 9.0+ / macOS 10.10+ / watchOS 2.0+, or use @available if not.
  • I have added tests for new extensions, and they passed.
  • All extensions have a clear comments explaining their functionality, all parameters and return type in English.
  • All extensions are declared as public.
  • I have added a changelog entry describing my changes.

Operators should be implemented based on their in-place variants, not the other way around. In that way in-place operations won't allocate any new objects.

See SwifterSwift#916 for more details.

This PR allows us to reenable the swiftlint rule shorthand_operator. It also refactors other operators to use their in-place variant to reduce code duplication.
@sk-
Copy link
Contributor Author

sk- commented Nov 5, 2020

I changed all the other operators (except for the ones in NSAttributedString) to be based on the in-place operators. Let me know what you think.

@sk- sk- changed the title refactor: base operators in in-place ones refactor: base operators on in-place ones Nov 5, 2020
@codecov
Copy link

codecov bot commented Nov 5, 2020

Codecov Report

Merging #919 into master will decrease coverage by 0.03%.
The diff coverage is 96.25%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #919      +/-   ##
==========================================
- Coverage   92.84%   92.81%   -0.04%     
==========================================
  Files         100      100              
  Lines        3634     3674      +40     
==========================================
+ Hits         3374     3410      +36     
- Misses        260      264       +4     
Flag Coverage Δ
ios 95.38% <96.25%> (-0.07%) ⬇️
macos 82.94% <73.75%> (-0.22%) ⬇️
tvos 95.48% <96.25%> (-0.07%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
.../SwifterSwift/CoreGraphics/CGPointExtensions.swift 86.66% <83.33%> (-13.34%) ⬇️
...s/SwifterSwift/CoreGraphics/CGSizeExtensions.swift 100.00% <100.00%> (ø)
...SwifterSwift/CoreGraphics/CGVectorExtensions.swift 100.00% <100.00%> (ø)
...s/SwifterSwift/SceneKit/SCNVector3Extensions.swift 100.00% <100.00%> (ø)
...ces/SwifterSwift/Shared/EdgeInsetsExtensions.swift 86.11% <100.00%> (-0.38%) ⬇️
...wifterSwift/SwiftStdlib/DictionaryExtensions.swift 98.41% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b7606e6...5c856ac. Read the comment docs.

@SwifterSwiftBot
Copy link

2 Warnings
⚠️ Consider adding tests for new extensions or updating existing tests for a modified SwifterSwift extension
⚠️ The source files have been modified. Please consider adding a CHANGELOG entry if necessary.
1 Message
📖 Thank you for submitting a pull request to SwifterSwift. The team will review your submission as soon as possible.

Generated by 🚫 Danger

Copy link
Member

@LucianoPAlmeida LucianoPAlmeida left a comment

Choose a reason for hiding this comment

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

Let's just change the places that use -, +, *, /... inside an ...=, which I believe are the ones which the rule applies. The other let's leave as it was before :)

@@ -81,7 +83,9 @@ public extension CGPoint {
/// - rhs: CGPoint to subtract.
/// - Returns: result of subtract of the two given CGPoints.
static func - (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
return CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
Copy link
Member

Choose a reason for hiding this comment

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

TBH I think this is better the way it was ... to me it is simpler :)

@@ -51,7 +51,9 @@ public extension CGPoint {
/// - rhs: CGPoint to add.
/// - Returns: result of addition of the two given CGPoints.
static func + (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
return CGPoint(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
Copy link
Member

Choose a reason for hiding this comment

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

This one too ...

@@ -65,8 +67,8 @@ public extension CGPoint {
/// - lhs: self
/// - rhs: CGPoint to add.
static func += (lhs: inout CGPoint, rhs: CGPoint) {
// swiftlint:disable:next shorthand_operator
lhs = lhs + rhs
Copy link
Member

Choose a reason for hiding this comment

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

Nice!

@@ -110,7 +114,9 @@ public extension CGPoint {
/// - scalar: scalar value.
/// - Returns: result of multiplication of the given CGPoint with the scalar.
static func * (point: CGPoint, scalar: CGFloat) -> CGPoint {
return CGPoint(x: point.x * scalar, y: point.y * scalar)
var result = point
Copy link
Member

Choose a reason for hiding this comment

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

Here too ...

@LucianoPAlmeida
Copy link
Member

Also, don't forget the changelog entry :)

@LucianoPAlmeida LucianoPAlmeida linked an issue Nov 5, 2020 that may be closed by this pull request
Copy link
Contributor

@guykogus guykogus left a comment

Choose a reason for hiding this comment

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

Unfortunately code duplication is inevitable in this project. One of the conditions is that any function should be copyable as-is, without having to copy any other functions*. This means that you can't use the in-place variants.

In some places it's also a lot more inefficient. E.g. in CGPoint.+(lhs:rhs:) instead of creating the new object directly with the added values, you're creating a copy of an object, jumping to another function in order to add the values via a reference and then jump back to return the updated object. It's longer, less efficient code that violates a primary directive of the project.

On the other hand, the updates to the in-place functions, e.g. CGPoint.+=(lhs:rhs:), are much better! I agree that they're more efficient and they also fix the copying issue mentioned.


* In the past this wasn't enforced so it exists in some places, but we don't want it to happen any more**.

** Even though I'm personally not in favour of it.

@LucianoPAlmeida
Copy link
Member

LucianoPAlmeida commented Nov 8, 2020

One of the conditions is that any function should be copyable as-is, without having to copy any other functions*. This means that you can't use the in-place variants.

IMO, non-complex arithmetic operators such + and += can be an exception to this rule because one is always a mutating complement of the other, and people likely copying both anyways. I think that is the reason we allowed this...

In some places it's also a lot more inefficient. E.g. in CGPoint.+(lhs:rhs:)

+1

@guykogus
Copy link
Contributor

guykogus commented Nov 9, 2020

IMO, non-complex arithmetic operators such + and += can be an exception to this rule because one is always a mutating complement of the other, and people likely copying both anyways. I think that is the reason we allowed this...

I'm more than happy to make an exception here. My other points still stand though :)

@sk-
Copy link
Contributor Author

sk- commented Nov 18, 2020

Closing as I don't have the time to address the requirements. Feel free to reuse portions of this PR.

@sk- sk- closed this Nov 18, 2020
@LucianoPAlmeida
Copy link
Member

Closing as I don't have the time to address the requirements. Feel free to reuse portions of this PR.

Hey @sk- , no worries!
But feel free to get back to it when possible in the future :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

shorthand_operator is disabled
4 participants