1

I'm making the transition from learning Ruby to Swift and trying to make any useful associations in order to get a better understanding of similar concepts from both programming languages. I noticed in Swift there are optionals which either have or don't have a value assigned to variables.

var optinalString: String? = "This is optional"

In Ruby we have ||= which from what I understand does something very similar where if the user doesn't assign a value to this variable, then it will use the predefined one that's already been set.

optionalString ||= "This is optional"

Am I on the right track with this assumption? Overall what makes these concepts similar/different?

Carl Edwards
  • 13,826
  • 11
  • 57
  • 119

1 Answers1

3

These two concepts are not equivalent.

In your Swift example, you're creating a variable of type String? and assigning it the value of a string literal. In the Ruby example, you're assigning a string literal to your optionalString variable if optionalString is undefined, nil, or evaluates false (more info).

In Swift, when you create a variable of optional type, all you're doing is specifying that the variable is allowed to be nil, so a closer representation of your Ruby example might look like this:

var optionalString: String?
optionalString = optionalString ?? "This is optional"

Which uses Swift's nil coalescing operator and is equivalent to the following usage of the ternary conditional operator, where optionalString is assigned the unwrapped value of optionalString if it isn't nil, or a fallback value of "This is optional" if it isn't.

optionalString = optionalString != nil ? optionalString! : "This is optional"

Note that by doing this, your variable will still have an optional type and need to be unwrapped to be used, and since you're fallback value is a string literal that won't ever be nil, you can confidently forcibly unwrap the optional with the ! operator.

But even though this can be used to set a variable with a fallback value, it still isn't entirely the same as your Ruby example since all it's doing is checking the nilness of the variable, and not whether it evaluates false or is undefined.

In Swift, you can't test the falseness of variables by sticking them into conditions unless they are instances of a type that conforms to the BooleanType protocol. This means that if you wanted to achieve something similar with a type that supports a falseness check, you could implement something like this:

var optionalBool: Bool? = false
optionalBool = optionalBool != nil ? (!optionalBool! ? true : optionalBool!) : true

Which will assign a fallback value of true to the optionalBool variable if the variable is either nil or evaluates to false. (optionalBool will still need to be unwrapped for most uses)

But this still leaves a difference with undefined variables, and as far as I know, there isn't any way to achieve the equivalence to Ruby's ||= in this regard in Swift without inlining the nilness checks in the instantiation of a variable based on a fallback value and the value of some other variable.

var optionalString: String?
var nonOptionalString = optionalString ?? "This is not optional"

Note, there's no point in nonOptionalString being optional here, since it will always have a value.

Community
  • 1
  • 1
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281