ed_me
ed_me

Reputation: 3508

Can swift optionals be mapped to new values?

In java 8, you can do the following: -

Optional<String> foo = Optional.empty(); // or Optional.of("hello");
foo.map(String::toUpperCase).orElse("Empty String")

edit - another example

class Bar {
  public Bar(final String baz) { ... }
}

foo.map(f -> new Bar(f)) // has mapped into an optional Bar

That toUpperCase was a little too simplified; I'm thinking more like being able to specify a lambda or function that can provide a mutated value based on an optional present.

I see that you can do the following in swift: -

guard let foo = optional else { return "Empty String" }

which is massively useful, and also

optional ?? "Empty String"

but is there any way to map a value based on the value being optionally present? i.e. so if a value is present, you can return a mutated value?

This functionality is also available for java/c# collections

Upvotes: 0

Views: 58

Answers (2)

dfrib
dfrib

Reputation: 73196

Say for a given array of optional strings, you can make use of optional chaining within your map operation

let foo: [String?] = ["foo", "bar", nil, "baz"]

let bar = foo.map { $0?.uppercaseString ?? "Empty string" }
print(bar) // ["FOO", "BAR", "Empty string", "BAZ"]

A possibly more useful alternative is to apply a flatMap operation to simply remove nil-valued optional entries from the string array

let foo: [String?] = ["foo", "bar", nil, "baz"]

let bar = foo.flatMap { $0?.uppercaseString }
print(bar) // ["FOO", "BAR", "BAZ"]

W.r.t. your comment, you could e.g. call a failable initializer for, say, some structure Foo, within the flatMap operation, yielding an array of Foo instances given that the initializer succeeds.

struct Foo {
    let foo: String
    init?(bar: String?) {
        guard let foo = bar else {
            return nil
        }
        self.foo = foo
    }
}

let foo: [String?] = ["foo", "bar", nil, "baz"]
let bar = foo.flatMap { Foo(bar: $0) }
print(bar) // [Foo(foo: "foo"), Foo(foo: "bar"), Foo(foo: "baz")]

Upvotes: 3

Rob Napier
Rob Napier

Reputation: 299455

In your example, that's just:

optional?.uppercaseString ?? "EMPTY STRING"

or if you'd prefer to modify after defaulting:

(optional ?? "empty string").uppercaseString

Did you have something more complicated in mind?

(You may be unfamiliar with the ?. operator. It's called optional chaining in Swift, and is similar to map.)

Upvotes: 1

Related Questions