Does swift have standard (scope) functions like in Kotlin? - swift

In Kotlin we have a list of standard (scope) functions (e.g. let, apply, run, etc)
Example of usage below
val str : String? = "123"
str?.let{ print(it) }
This makes the code looks more succinct without need to have if (str != null)
In swift, I code it as below
let str: String? = "123"
if str != nil { print(str!) }
I have to have if str != nil. Is there a let provided by default that I could use (without me writing my own)?
FYI, I'm new to Swift, and check around doesn't seems to find it.

if you like if, extend the functionality of Optional
extension Optional {
func `let`(do: (Wrapped)->()) {
guard let v = self else { return }
`do`(v)
}
}
var str: String? = "text"
str.let {
print( $0 ) // prints `text`
}
str = nil
str.let {
print( $0 ) // not executed if str == nil
}

You could use Optional.map :
let str1 : String? = "123"
str1.map { print($0) }
prints 123.
let str2 : String? = nil
str2.map { print($0) }
Doesn't print anything.
So if an optional is not nil, it is unwrapped and used as a parameter to the map closure. if not, the closure won't be called.
A more idiomatic approach in swift would be to use optional binding :
var str: String? = "123"
if let s = str {
print(s)
}

Apparently the Swift way of doing the nil check
let str: String? = "123"
if let strUnwrapped = str { print(strUnwrapped) }
And if really want to ensure it is not nil, use guard (thanks #CouchDeveloper for pointing out)
let str: String? = "123"
guard let strUnwrapped = str else { return }
I know this didn't explicitly answer the question of having scoping function or not, but it provides me my original intent of finding the Swift way of checking nil or non nil I was looking for like the let of Kotlin being used.

Related

Swift string from optional Double

Is there a shortcut to specify placeholder text when the value is nil in Swift?
Right now I do:
let myText:String!
if myDouble != nil{
myText = "\(myDouble!)"
}else{
myText = "Value not provided"
}
That works, but it's very annoying to have to do that all the time. Is there a way to do something like
let myText:String = "\(myDouble ?? "Value no provided")"
That fails because it wants a default Double value, but I really want a String value.
You can use map and nil-coalescing:
let myText = myDouble.map { String($0) } ?? "Value not provided"
If myDouble is nil, the result of map is nil and the result is the value after the ??.
If myDouble is not nil, the result is the output of the map which creates a string from the Double.
For more details, please see the documentation for the map function of the Optional enumeration in the Swift standard library.
It seems reasonable to do
let myDouble: Double? = Double(3.0)
let myText = myDouble?.description ?? "Value not provided"
If myDouble is nil, then myText is "Value not provided". If myDouble is not nil, it's assigned the string representation of the number.
I think good approach to this is to make Extension to optional where Double is the Wrapped element:
extension Optional where Wrapped == Double {
var stringValue: String {
guard let me = self else { return "No Value Provided" }
return "\(me)"
}
}
// Use it like this:
myDouble.stringValue
Another approach could be making your custom operator like this:
public func ??(rhd: Double?, lhd: String) -> String {
if let unwrapped = rhd {
return String(unwrapped)
} else {
return lhd
}
}
And now your line let myText:String = "\(myDouble ?? "Value no provided")" works.
Please let me now if you don' understand anything.
This should work:
let myText = myDouble != nil ? String(myDouble!) : "Value not provided"

unable to infer complex closure return type

unable to build swift project because of this error.
// showing error with inputs.flatmap
fileprivate func makeShippingAddressDictWith(inputs: [TextFieldData]) -> [String: String] {
var shippingDict: [String: String] = [:]
let _ = inputs.flatMap { input in
if let shippingFieldType = input.type as? ShippingDictKeyable.Type {
shippingDict[shippingFieldType.shippingDictKey] = input.text
}
return nil
}
// FIXME: these empty values are the result of a poorly designed request in GDKECommerce
shippingDict["email"] = ""
shippingDict["second_name"] = ""
shippingDict["suffix"] = ""
shippingDict["title"] = ""
shippingDict["salutation"] = ""
shippingDict["company_name"] = ""
return shippingDict
}
}
You could use .forEach instead of .flatMap. Then you would not have to worry about a return type that you are ignoring anyway (with let _ =).
Combining this with a filter would produce a cleaner functional statement if that's what you're after:
inputs.map{ ( $0.text, $0.type as? ShippingDictKeyable.Type) }
.filter{ $1 != nil }
.forEach{ shippingDict[$1!.shippingDictKey] = $0 }
// FIXME: these empty values are the result of a poorly designed request in GDKECommerce
let blankAttributes = ["email", "second_name", "suffix", "title", "salutation", "company_name"]
blankAttributes.forEach{ shippingDict[$0] = "" }
Or use a for loop as suggested by Hamish.
If performance is a factor, the compiler will produce faster code with the for loop than with map/filter/forEach.
Note that, if you want to go crazy with functional style, Swift 4 will let you return the whole dictionary in a single line:
return [String:String]( uniqueKeysWithValues:
inputs.map{ ($0.type as? ShippingDictKeyable.Type, $0.text) }
.filter{ $0.0 != nil }
.map{($0!.shippingDictKey,$1)}
+ ["email", "second_name", "suffix", "title", "salutation", "company_name"]
.map{($0,"")}
)
This may only work in the playground though cause real projects tend to complain about expressions being too complex more often.

How to unwrap Optional<Optional<T>> in Swift 1.2

Let's say we have String?? value. Optional of Optional may have 3 states:
let strOptOpt1: String?? = .Some(.Some("actual value"))
let strOptOpt2: String?? = .Some(.None)
let strOptOpt3: String?? = .None
To safely unwrap them to String, in Swift 1.1 we could:
if let str:String = strOptOpt? {
println(str)
}
else {
println("was nil") // `.Some(.None)` or `.None`
}
But it does not work anymore in Swift 1.2:
if let str:String = strOptOpt? {
// ^ [!] error: '?' must be followed by a call, member lookup, or subscript
At the moment, I think, I have to do like this:
if let strOpt = strOptOpt, str = strOpt {
println(str)
}
OR using switch:
switch strOptOpt {
case let .Some(.Some(str)):
println(str)
default:
println("was nil")
}
But, there must be simpler way to do this, I think. Anyone know that?
As of Swift 2, you can use if/case with a pattern, and x? as
a synonym for .Some(x):
if case let str?? = strOptOpt1 {
print(str)
} else {
print("was nil") // `.Some(.None)` or `.None`
}
For me, the best solution I found is using ?? operator in optional binding.
let strOptOpt: String?? = ...
if let str = strOptOpt ?? nil {
println(str) // "actual value"
}
Works for all these cases:
.Some(.Some("actual value"))
.Some(.None)
.None
But, if strOptOpt is String???, you should do:
let strOptOpt: String??? = ...
if let str = (strOptOpt ?? nil) ?? nil {
println(str)
}
I always get double optional in this situation
let field: ChangeField?? = json["field_id"].int.map{ ChangeField(rawValue: $0) }
Instead of map you can use flatMap
let field: ChangeField? = json["field_id"].int.flatMap{ ChangeField(rawValue: $0) }

Why would I use if and let together, instead of just checking if the original variable is nil? (Swift)

In “The Swift Programming Language.” book, Apple mentions using if and let together when accessing an optional variable.
The book gives the following code for example:
var optionalString: String? = "Hello"
optionalString == nil
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
What is the advantage of using if let name = optionalName, rather than if optionalName != nil (and always referring to it as, optionalName)? Is there any difference, or is it simply convention?
Because it also unwraps the optional value, so this code:
if let name = optionalName {
greeting = "Hello, \(name)"
}
is equivalent to:
if optionalName != nil {
let name:String = optionalName!
greeting = "Hello, \(name)"
}
This language sugar is known as Optional Binding in Swift.
Optional Types
In Swift T and T? are not the same types, but the underlying value of an optional T? type can easily be realized by using the ! postfix operator, e.g:
let name:String = optionalName!
Which now can be used where a String is expected, e.g:
func greet(name:String) -> String {
return "Hello, \(name)"
}
greet(name)
Although as its safe to do so, Swift does let you implicitly cast to an optional type:
let name = "World"
let optionalName: String? = name
func greet(optionalName:String?) -> String? {
if optionalName != nil {
return "Hello, \(optionalName)"
}
return nil
}
//Can call with either String or String?
greet(optionalName)
greet(name)
It isn't actually needed in that case. You could just use optionalName in the if. But if optionalName was a calculated property it would have to be calculated in the conditional then again in the body. Assigning it to name just makes sure it is only calculated once.

Grabbing values from a dictionary in a more elegant way

I've been playing with swift and am getting quite tortured! Consider:
var myDict : Dictionary <String, String>
//DO SOME MAGIC TO POPULATE myDict with values
<magic being done>
//Now myDict has values. Let's parse out the values of myDict
//This doesn't work
let title : String = myDict["title"]
//This does
let title : String? myDict["title"]
This is because it isn't known whether the key is in the dictionary. What I want to say, though, is "If the title key is in the dictionary, give me that value, else, just give me an empty string"
I could probably write:
var myTitle : String
if let title : String = myDict["title"] {
myTitle = title
} else {
myTitle = ""
}
I believe that works...BUT...it's quite a lot of code for EACH key of the dictionary. Does anyone have any ideas in the swift world on how this is supposed to be written?
RD
You could write an extension on optional:
extension Optional {
/// Unwrap the value returning 'defaultValue' if the value is currently nil
func or(defaultValue: T) -> T {
switch(self) {
case .None:
return defaultValue
case .Some(let value):
return value
}
}
}
Then you can do:
myDict["title"].or("")
This would also work for all optionals.
Note: I started a module to add common helpers like this or on Optional to swift.
You unwrap the value either explicitly:
let title : String = myDict["title"]!
or implicitly:
let title : String! = myDict["title"]
Note that you still have to check whether title is nil or not unless you are really sure it's there.
Edit:
Here's a sample global operator overload for any optional for type T:
#infix func | <T: Any>(lhs: T?, rhs: T!) -> T! {
if lhs {
return lhs!
}
return rhs
}
var myDict : Dictionary <String, String> = ["a": "b"]
let title1 = (myDict["a"] | "") // "b"
let title2 = (myDict["title"] | "") // ""