Last active
January 25, 2017 16:05
-
-
Save samdmarshall/a7a657c8d1a1634d1e734bb17a11b31a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Intention: query a dictionary for a key-value pair, take the value as a path that needs to be expanded (tilde -> abspath) | |
// and then make it available to use. | |
let path_value = arguments["path"] ?? "" // the `?? ""` makes this a `String` and not an `Any` | |
var path = NSString.init(string:"\(keychain_path_value)") // this will accept an `Any` or a `String` as the type to | |
// subsitute when creating the `NSString` type object | |
if !path.isEqual(to:"") { // "if the string has contents, then expand the path" | |
path = path.expandingTildeInPath as NSString // cast `as NSString` is necessary because it returns a `String` | |
} | |
// | |
// So without the `?? ""` on line 1, if there is no value in the `argument` dictionary for the key `"path"`, that will return | |
// an `Any` object which will case the `NSString` object that is created on line 2 to return as `nil`, not as a valid | |
// `NSString` object. I don't like that the introduction of a single bridge call into Objective-C here makes all following | |
// statements that use that variable contain more risk due to the possibility of the optional value. | |
// | |
// Additionally, with this specific code, you can satisfy the swift (3.0.2) compiler with and without the `?? ""` in line 1 | |
// because of the typing of the code. Which means I could remove it, this could still be seen as "valid" without raising | |
// any warnings and be fundamentally poorly written code for handling the intention properly. Furthermore, the default value | |
// assignment can be removed without making any indication about the type system and implication of the changes as such. | |
// |
this is a wrong program
Good morning! I know I'm missing some of the context in which you want to use this path but I'm tempted to get it like this:
import Foundation
func getPath(_ arguments: [String: Any]) -> String? {
guard let path_value = (arguments["path"] as? String) else { //Using a conditional cast when subscripting into the arguments dictionary lets us avoid the nil-coalescing operator and I think eliminates some of the `Any` type ambiguity when reading the code.
return nil //Using a `guard` (or `if let`) here lets us avoid having to consider `nil` (or `isEqual(to:"")` checks later.
}
let path = NSString(string: path_value).expandingTildeInPath //It is a shame that Swift 3's removal of automatic bridging means we have to be explicit about use of `NSString` here but I guess it also makes our dependence on something outside the Swift standard lib explicit.
return path
}
getPath(["path": "~/.profile"])
getPath(["path": "/etc/hosts"])
getPath(["path": ""])
getPath([:])
Alternately if you don't want the path result to be able to be an optional then you could define it as:
func getPath(_ arguments: [String: Any]) -> String {
guard let path_value = (arguments["path"] as? String) else {
return ""
}
let path = NSString(string: path_value).expandingTildeInPath
return path
}
These satisfy swiftc
(3.0.2) so I hope I've matched your toolchain.
Would do something like
guard let raw_path = arguments["path"] as? String else {fail...}
let path = (raw_path as NSString).expandingTildeInPath
Not exactly your original code, but much more type safe (and dare I say, elegant 😄).
Also, question: Why do you check if the string is empty? Also, str == ""
or even better str.empty
seems prettier.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The problem on line 4 is an intentional design of the language: if something has no value, the programmer has to be explicit about what value they want instead.
String
has free bridging toNSString
, so I'd expect that usingString
on line 5 instead would avoid the cast on line 9, and still work. I can't be 100% sure because I always use the Xcode version :P