3

In swift you can unwrap optional values with a guard statement

guard let foo = foo else { return nil }

Is this statement making a copy of foo? In other words, could this statement be potentially expensive if foo is very large?

Devin Haslam
  • 747
  • 2
  • 12
  • 34
  • I'm curious, how would you use this knowledge? Suppose it did cause a copy, what would you do instead? – Alexander Jun 14 '19 at 01:24
  • One example is that there are better ways of unwrapping if it is an expensive operation. In my case, I want to know if I should use a lock around this code since other threads are modifying `foo` – Devin Haslam Jun 14 '19 at 02:59
  • "One example is that there are better ways of unwrapping if it is an expensive operation" like what? – Alexander Jun 14 '19 at 03:07
  • ```foo!``` wouldn't make a copy right? Or maybe it would be better to avoid an optional in the first place. – Devin Haslam Jun 14 '19 at 12:25
  • "`foo!` wouldn't make a copy right?" You don't know that. I mean, it happens not to, and neither does conditional binding, but I don't see that explicitly stated anywhere in the language docs. What would you do if they *did* cause copies? Your hands are kinda tied, you need this functionality, whether it causes copies or not. – Alexander Jun 14 '19 at 14:35
  • Also, it's really rare for objects to very large. The only way a large object could exist, is to either have one object with *lots* of fields (thousands...), or a struct that composes together substructs, whose sizes all sum up. Most "large data" in an app is in dictionaries, arrays and other data structures which aren't stored inline. They're stored by reference, thus the object holding them only uses a machine word of RAM to "store" them. – Alexander Jun 14 '19 at 14:38
  • My main question is whether foo is copied. As I mentioned my real goal is to decide if this statement needs a lock. In swift dictionaries are a value type, so ```let dictCopy = dict``` could be potentially very expensive as you are making a copy. – Devin Haslam Jun 14 '19 at 15:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/194956/discussion-between-alexander-and-devin-haslam). – Alexander Jun 14 '19 at 15:25

4 Answers4

2

Actually this depends on type of foo e.x class type won't create a copy unlike struct type

guard isn't a magic keyword it simply if not presented in 1 word

Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
1
 guard let foo = foo else { return nil }

Could this statement be potentially expensive if foo is very large?

Instead of asking yourself the question that way, ask it this way: what if you had said

if foo != nil {
    let foo = foo!
    // everything else here
}

Was saying foo! to unwrap the Optional "expensive"? Whatever your answer is, it must be exactly the same for guard let foo = foo, because they both do exactly the same thing: they test for nil and, if safe, they unwrap the Optional. And that is all they both do. The one is merely syntactic sugar for the other.

Community
  • 1
  • 1
matt
  • 515,959
  • 87
  • 875
  • 1,141
0

You have two ways:

1- To only check if this foo does not equal nil
In this case you can check if foo is nil or not

if foo != nil {
    // do you work here
}

2- To get information from foo
In this case, you have to unwrap this optional (with guard-let or if-let statements) and here we have two cases:
- if foo is a class, then it’s a reference type. so there will be no copy and a reference to this instance is created
- if foo is a struct, then it’s a value type. so an entirely new instance is created (copied from the original)
Also you can read this answer to see should you choose struct or class in swift

0

If the property you're unwrapping is a reference type (e.g. a class) then no it will not make a copy, it will just create a new property with a reference to the original instance.

If the property you're unwrapping is a value type (e.g. struct) then it will make a copy.

Gsp
  • 401
  • 5
  • 10