I disagree: the post is not about shortcuts, it's about the code being cumbersome. Here are the three code blocks from the original post. The first, does not compile due to prefix
returning Substring
:
var body = inResponse.result.value as? String
body = body?.prefix(1024)
The second, does not compile because there is no String.init(_: Substring?)
:
var body = inResponse.result.value as? String
body = String(body?.prefix(1024))
The third, compiles, rejected because "readability suffers":
var body = inResponse.result.value as? String
if let b = body { body = String(b.prefix(1024)) }
The question is whether =>
is clearer than Optional.map
, so let's rewrite the third case to use either.
var body = inResponse.result.value as? String
body = body?.prefix(1024) => String.init
or
var body = inResponse.result.value as? String
body = body?.prefix(1024).map(String.init)
Maybe this is just me, but I don't find either reads more clearly. In fact, I understand the map
code better, though I'm going to choose to dismiss that because if the =>
operator was widely used that familiarity issue would go away.
For my part, the real cumbersome problem here is actually the as?
. That operator is awkward because it forces the use of parentheticals or intermediates in order to chain (you either write (x as? Y)?.foo()
or var z = x as? Y; z.foo()
. When you combine it with the very nested access to the property there is simply no way to write this clearly: any line of code you write is going to be ugly as sin, regardless of whether you use =>
or map
.
Consider, for a moment, if inResponse.result.value
was known to be a String
. Then we'd have this:
let body = String(inResponse.result.value.prefix(1024))
So clear! Even if it was String?
we'd get this:
let body = inResponse.result.value?.prefix(1024).map(String.init)
This is still pretty readable. More importantly, a bunch of the lack of clarity surrounds the Law of Demeter violating inResponse.result.value
, so if we pulled that out to a separate location our life would be easier:
let fullBody = inResponse.result.value
let truncatedBody = fullBody?.prefix(1024).map(String.init)
All of a sudden this looks pretty good to me. So it seems to me that the best code would be to do this:
extension ResponseResult { // I don't know what the original name of this type is
var resultString: String? {
return self.value as? String
}
}
// Elsewhere
let fullBody = inResponse.resultString
let truncatedBody = fullBody?.prefix(1024).map(String.init)
Seems pretty clear to me, and doesn't feel particularly cumbersome IMO.