Swift: Chaining String/Substring methods yields 'ambiguous use of' errors. Fix or alternative? - swift

I'm trying to do the most basic string manipulation using Swift. It looks like String provides everything I need, even though it relies on Substring intermediate results. So this works
let myString = "0123456789"
let mySubstring = myString.dropFirst(2)
print(mySubstring.dropLast(2))
It successfully yields "234567" as a Substring.
However, when I attempt to chain the calls...
print(myString.dropFirst(2).dropLast(2))
I get the following error...
9> print(myString.dropFirst(2).dropLast(2))
error: repl.swift:9:7: error: ambiguous use of 'dropFirst'
print(myString.dropFirst(2).dropLast(2))
^
Swift.Collection:39:17: note: found this candidate
public func dropFirst(_ n: Int) -> Self.SubSequence
^
Swift.Sequence:20:17: note: found this candidate
public func dropFirst(_ n: Int) -> AnySequence<Self.Element>
^
So it seems like the compiler is understandably having trouble inferring which dropFirst method to invoke because it is defined twice with different return types.
Is there a way around this? Is this just really poor API design on Apple's part? I'm trying to just get a nice easy to read and concise bit of code. I can also make it work by resorting to NSString but this seems wasteful and even more verbose and obtuse.
UPDATE:
I am able to get a better result by adding as Substring after the chain as in...
print(myString.dropFirst(2).dropLast(2) as Substring)
...since that disambiguates the overloaded methods. I would still love to see a more concise solution. Thanks.

If you define the return type, it has no trouble resolving which function to use. There are a number of ways to do this, such as:
let mySubstring: Substring = myString.dropFirst(2).dropLast(2)
Of course, as you say, you can insert this Substring type within the expression:
let mySubstring = (myString.dropFirst(2) as Substring).dropLast(2)

Surprisingly, it works if you reverse the order and do the dropLast first:
print(myString.dropLast(2).dropFirst(2))

Related

How to Sort Mongo collection in F#

I can get a collection in MongoDB using F# No problem using
let draws = db.GetCollection<Draw>("draws").Find(fun _ -> true)
To Sort I would expect it to be:
let draws = db.GetCollection<Draw>("draws").Find(fun _ -> true).Sort(Builders<Draw>.Sort.Descending(d => d.drawDate))
But I am getting the following error. In the intellisense all of the types seem to be recognised all the way through so I am not sure what to do.
A unique overload for method 'Descending' could not be determined based on type information prior to this program point. A type annotation may be needed.
Your second lambda is using C# syntax. I'm not sure if that's what's causing the compiler error, but I think it's easier to do something like this anyway:
let draws =
db.GetCollection<Draw>("draws")
.Find(fun _ -> true)
.SortByDescending(fun d -> d.drawDate :> obj)
(Note that the SortByDescending function requires a result of explicit type object, but it shouldn't cause any problems for you. I think this is because the driver was created with C# clients in mind, where the upcast is implicit.)

Does Safety in Swift affect Performance?

While learning Swift, I have seen many cases of safe code vs. unsafe code. A perfect example of this is
as? and as!
as?, from my understanding tries to type cast, but if it doesn't cast, returns nil.
as!, from my understanding, tries to type cast, and crashes if it fails.
My question, is why does as!, (and other unsafe syntax with safe counterparts, for that matter) exist? Obviously as? is the better choice. The only answer I could come up with is that maybe using as! is faster for the compiler to compile, and therefore is mainly an optimization piece of syntax.
I'm just curious to know I'm right about safe syntax being a bit slower to compile, since performance matters to me a great deal.
Thank you for your time.
This question is based upon a false premise: The primary choice of as? vs as! is not generally one of performance. Sure, as! potentially might be a bit more efficient, but in an optimized build, the difference is generally negligible.
One chooses as! vs as? based upon the context:
If the cast can possibly fail at runtime, then you'd use as?. Of course you add code to check to see whether the cast succeeded or not.
A common example of a cast that could fail would be whenever the source of the data is some external source (e.g. user input or a network request). A user could paste text values into a field in which you were expecting only numeric values. An external web server could be unavailable or it could even return data in an unexpected format. You'd want to use as? to detect these situations and handle it gracefully.
But if the cast can not possibly fail at runtime, you use as!. But you do so less for performance reasons than for reasons of clarity and writing concise code.
A common example of a cast that cannot fail would be when retrieving a cell prototype from a storyboard, where you know the base type was set in Interface Builder, though the Cocoa API cannot know this. It would be ineffiencient to add a lot of code checking to see if the base type was set correctly (especially since this would be a fatal programming error, anyway) and leads to code with a lot of syntactic noise with no benefit. And if you don't do it correctly, you could easily accidentally suppress an error that you really would want to flush out during the testing process, making it harder to find the problem. This is a good use case for as! syntax.
as! is not unsafe unless your code before it has failed to ensure the cast can't fail. Imagine a situation where your code has already verified the object can indeed be cast to a particular protocol. If for whatever reason you find it convenient to not create a new local variable of that type and cast the first variable to it, then using as! can be appropriate.
The same logic goes for implicitly unwrapped optionals. Since when your view controller is instantiated, an IBOutlet property can't be assigned yet (storyboard hasn't loaded yet), the property has to be optional. But it's irksome to have to use the property as an optional throughout the class when you know the storyboard has loaded. In fact, if there is a problem with locating the storyboard element and assigning it, a 100% guaranteed crash is desired so that the developer can always spot and fix the problem.
So returning to as!, this raises a second case of when it's appropriate to use: whenever a crash is the most desirable outcome of the failed cast.
So it's not about compiler speed. It's about code logic convenience. There are appropriate times to use it, and for those times, it's a more compact and easier to read way of representing your logic goals.
As you say, as! should hardly ever be used. There are a few cases, though, where due to legacy issues, the compiler doesn't know what type something should be, even though the developer does. One example of this is the NSCopying protocol. Because Objective-C was not as strict about type safety as Swift, copy() returns an id, which is bridged to Any in Swift. However, when you use copy(), mutableCopy(), and friends, you usually know exactly what type you will get out of it, so as! is typically used to force a cast to the correct type.
let aString: NSAttributedString = ...
let mutableAString = aString.mutableCopy() as! NSMutableAttributedString
You can investigate this question for yourself by compiling something like
func f(a: Any) -> Int {
(a as! Int) + 5
}
vs.
func f(a: Any) -> Int {
((a as? Int) ?? 3) + 5
}
With the Swift 4 compiler, running swiftc -O -emit-assembly on this Swift code produces extremely similar output, which should square with your understanding of how as! works and how we would implement it if it wasn't part of the language:
func forceCast<T>(_ subject: Any) -> T {
return subject as? T ?? fatalError("Could not cast \(subject) to \(T)")
}
It's worth noting, as SmartCat already alluded to, that as! isn't actually "unsafe" in the sense that the Swift compiler authors define that word; because it, like as?, actually specifically checks the type of subject. There is a unsafe-in-the-swift-sense force cast in swift; it's called, unsurprisingly, unsafeBitCast; and is equivalent to a C/Objective-C cast; it doesn't check types and just assumes you knew what you were doing. Will it be faster than as? Without a doubt.
So, to answer your title's question: yes, safety has a cost in Swift. The flip side of the coin is that if you write code that avoids casts and optionality, Swift can (in theory) optimize your code far more aggressively than languages that make less strong safety guarantees.
To answer your actual question; there's no difference between as? and as! in terms of performance.
Other's have already covered why as! exists; it's so you can tell the compiler "I can't explain why to you, but this will always work; trust me".

Is there an objective reason I can't have a single-element tuple with an element label?

In Swift up to and including Swift 3, I can't create a single-element tuple where the element is named. So func foo() -> Bar is fine whereas func foo() -> (bar: Bar) produces a compiler error.
I can, however, think of a few possible uses for this pattern, e.g.
func putTaskOnQueue() -> (receipt: CancellableTask)
func updateMyThing() -> (updatedSuccessfully: Bool)
...where the label is used to reduce ambiguity as to what the return value represents.
Obviously there are various ways I could re-design my apis to work around this limitation, but I'm curious as to why it exists.
Is this a compiler limitation? Would allowing element labels on 1-tuples break parsing of some other piece of grammar? Has this been discussed as part of the Swift Evolution system?
To be clear: I am not soliciting opinions as to the correctness of the examples above. I'm after explanations (if they exist) as to why this is not technically possible.
Yes, it's due to limitations in the compiler. There are no one-tuples in Swift at all. Every T is trivially convertible to and from (T). SE-110 and SE-111 should improve things, but I'm not sure it will be enough to make this possible and I don't believe any of the current proposals explicitly do make it possible.
It has been discussed on swift-evolution. It's not a desired feature of the language; it's a result of other choices.
The Swift Evolution process is very open. I highly recommend bringing questions like this to the list (after searching the archives; admittedly not as simple as you would like it to be). StackOverflow can only give hearsay; the list is much more definitive.

What's the rationale of Swift's size methods taking `Int`s?

I've noticed a lot of swift built ins take or return Ints and not UInts:
Here are some examples from Array:
mutating func reserveCapacity(minimumCapacity: Int)
var capacity: Int { get }
init(count: Int, repeatedValue: T)
mutating func removeAtIndex(index: Int) -> T
Given that the language is completely new, and assuming that this design choice was not arbitrary - I'm wondering: Why do swift built ins take Ints and not UInts?
Some notes: Asking because I'm working on a few collections myself and I'm wondering what types I should use for things like reserveCapacity etc. What I'd naturally expect is for reserveCapacity to take a UInt instead.
UInt is a common cause of bugs. It is very easy to accidentally generate a -1 and wind up with infinite loops or similar problems. (Many C and C++ programmers have learned the hard way that you really should just use int unless there's a need for unsigned.) Because of how Swift manages type conversion, this is even more important. If you've ever worked with NSUInteger with "signed-to-unsigned" warnings turned on (which are an error in Swift, not an optional warning like in C), you know what a pain that is.
The Swift Programming Guide explains their specific rationale in the section on UInt:
NOTE
Use UInt only when you specifically need an unsigned integer type with the same size as the platform’s native word size. If this is not the case, Int is preferred, even when the values to be stored are known to be non-negative. A consistent use of Int for integer values aids code interoperability, avoids the need to convert between different number types, and matches integer type inference, as described in Type Safety and Type Inference.
Here is a possible explanation (I am no expert on this subject): Suppose you have this code
let x = 3
test(x)
func test(t: Int) {
}
This will compile without a problem, since the type of 'x' is inferred to be Int.
However, if you change the function to
func test(t: UInt) {
}
The compiler will give you a build error ('Int' is not convertible to 'UInt')
So my guess is that it is just for convenience, because Swift's type safety would otherwise require you to convert them manually each time.

string option to string conversion

How do I convert the string option data type to string in Ocaml?
let function1 data =
match data with
None -> ""
| Some str -> str
Is my implementation error free? Here 'data' has a value of type string option.
To answer your question, yes.
For this simple function, you can easily find it in Option module. For example, Option.default totally fits your purpose:
let get_string data =
Option.default "" data
There are many other useful functions for working with option types in that module, you should check them out to avoid redefine unnecessary functions.
Another point is that the compiler would tell you if there's something wrong. If the compiler doesn't complain, you know that the types all make sense and that you have covered every case in your match expression. The OCaml type system is exceptionally good at finding problems while staying out of your way. Note that you haven't had to define any types yourself in this small example--the compiler will infer that the type of data is string option.
A lot of the problems the compiler can't detect are ones that we can't detect either. We can't tell whether mapping None to the empty string is what you really wanted to do, though it seems very sensible.