skip to Main Content

Question 1: in guard let self = self else { return }, first self and second self are same, why it can be compiled successfully? Because normal let self = self will be compiled with errors.

Question 2: Even I found guard let self else { return } in some projects, why it can be compiled successfully?

2

Answers


  1. A few links for your reference:

    1. SE-0079 discusses the use of if let self = self {…} pattern:

      The proposed solution entails allowing self to be upgraded from a weak reference to a strong reference using optional binding.

      That proposal replaces the legacy pattern of …

      if let strongSelf = self { … }
      

      … with something that avoids the confusion of introducing a separate variable name, reducing it to:

      if let self = self { … }
      
    2. The shortening of this syntax is contemplated in SE-0345, which says:

      Optional binding using if let foo = foo { ... }, to create an unwrapped variable that shadows an existing optional variable, is an extremely common pattern. This pattern requires the author to repeat the referenced identifier twice, which can cause these optional binding conditions to be verbose, especially when using lengthy variable names. We should introduce a shorthand syntax for optional binding when shadowing an existing variable:

      let foo: Foo? = ...
      
      if let foo {
          // `foo` is of type `Foo`
      }
      

      The pattern works for self, too, so thus the example in my first point is reduced to:

      if let self { … }
      
    3. FWIW, SE-0365, in its discussion of “implicit self”, shows lots of examples of the the guard pattern:

      guard let self else {…}
      
    Login or Signup to reply.
  2. By writing let self = self you declare a variable self and give it a value of self (i.e., a reference to the instance of the object that the line is called inside).

    Swift allows variable shadowing, so it’s legal to create a local variable self that shadows the identifier self from the outer scope.

    There’s one caveat, though: self is also a special word in Swift and can’t be used as a variable name (the compiler emits the error "Keyword ‘self’ cannot be used as an identifier here")… unless you apply an escaping technique: let `self` = self.

    On the other hand, guard doesn’t require this kind of escaping. I suppose that since the idiom guard let self = self is so common, language developers decided to make an exception for it to avoid some boilerplate code.

    In later versions of the language, they also introduced a shorthand syntax for unwrapping optional values: guard let self. In fact you can use it with any optional variable to unwrap it: guard let anyOptional.

    As for why guard let self else { return } cannot be compiled in some places, it’s impossible to say without more details, but I have two assumptions:

    1. The project might be compiled with a language version earlier than the shorthand syntax was introduced in, therefore the syntax is considered invalid.
    2. self itself might be unavailable in the context (i.e., the code is written outside of an instance of an object, e.g., in the global scope).
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search