-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Implement hasPrefix and hasSuffix #440
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
Conversation
I think this might be close enough, although inefficient (traverses both strings twice). This change requires tests. We have tests for the Objective-C side in It would make sense to put the tests into |
There’s no claim of efficiency implied, but it could be worse; I’m fairly sure no new memory is allocated.
Thanks for pointing me to those. Guillaume Lessard |
We should be careful with "close enough" implementations because the expectation is that it will behave the same as the Darwin version. |
We have Foundation available on all platforms now. Can we make this use that implementation on all platforms as well? |
@parkera That will create interesting circular dependencies in the build process. |
If the build process is deficient then we should fix that instead of forcing an incompatibility onto clients of the API. |
Or we do the obvious thing and put the implementation in an extension on String in Foundation. |
// FIXME: Implement hasPrefix and hasSuffix without objc | ||
// rdar://problem/18878343 | ||
extension String { | ||
/// Returns `true` iff `self` begins with `prefix`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be just "if" and the same thing below :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"iff" (if-and-only-if) is a stronger statement than "if". It is correct here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I stand corrected. My apologies.
@gribozavr The relevant test is ported from test/1_stdlib/NSStringAPI.swift. Neither the original test nor the ported test are particularly satisfying, since ultimately the operation is tested with a different version of itself. |
@parkera From what I ran into while doing this, I'd advocate to eliminate any way to reach Foundation-based comparisons from Swift.String. If a variable is being used as NSString or CFString, it's okay to use them, but otherwise there is at least one corner case where the Foundation-based comparison is not consistent with the Swift.String model. See https://bugs.swift.org/browse/SR-243 |
If we want to discuss dropping the NSString methods from String, that would be something to discuss on the evolution list. In the meantime, my primary concern is making sure developers don't get different answers for the same methods on Linux vs OS X. |
+1 -Dave |
After porting the corrected test from #629, the Foundation-based calls no longer pass, but the ICU-based calls do. Not sure where to go from here. |
Would you like a consolidated PR with this? |
Incidentally, it turns out that |
-Dave |
@dabrahams I don't see how that's possible. The Swift-native String buffer is a You can also trivially demonstrate that a Swift string is not Cocoa-compatible with the following code: var s = "test"
s += "!" // force it to copy to mutable memory
print(s._core.nativeBuffer)
print(s._core.cocoaBuffer) If it was a Cocoa string, it would print So this all comes back to the question of why String bridges into Obj-C when it has a perfectly functional non-ObjC implementation available. It would make sense to bridge if it already has a Cocoa buffer, but it doesn't test that, it merely tests Incidentally, there's a bit of even more weirdness here. When comparing two strings with |
As far as I can tell, the OSX swift build doesn't link ICU at all. I attempted earlier to bypass the call to |
@glessard, really nice implementation! 👌 I was just wondering which one is more Swift-y at the if prefix.isEmpty { return false } or guard !prefix.isEmpty else { return false } Any thoughts? Same goes for |
@adrfer I'm sure it could be argued both ways, but I think it is a special condition rather than a precondition. If this eventually called into |
@glessard indeed! I'm just trying to see what's more idiomatic. In this case |
Using String._compareDeterministicUnicodeCollation()
…g validation logic.
Foundation-dependent tests are skipped.
Rebased and re-submitted as #1031 |
You know, you can just force-push to your branch and GitHub will update the PR. That way all the previous discussion will be preserved. |
f5a74f4
to
f884997
Compare
Rebased here. Thanks for letting me know this is possible, @kballard |
@glessard Given the current implementation, do you think this pull request is still necessary/relevant? |
@CodaFi Good question. I was considering re-implementing the tests part of this based on the newer work; it would at least illuminate some differences between an ICU-based implementation and the CFString-based one. I think the discussion is still of interest for the (hopefully) forthcoming String rethink. |
Sounds good; we'll always take more tests. To preserve the discussion here, I'm going to close this pull request. Please open another if you decide to cherry pick the tests. |
Using the _compareDeterministicUnicodeCollation method, also used by the == operator.