4 ms·
Swift does, but typically for Optional promotion. You see stuff like `guard let delegate = delegate else { return }` inside functions all the time, shadowing a
by favorited 8y ago
Swift does, but typically for Optional promotion. You see stuff like `guard let delegate = delegate else { return }` inside functions all the time, shadowing a property with a local & promoting the type from Optional<T> to T.
It's not the same as the Rust example because you're shadowing an ivar to a local, but since `self.` is implicit you're still shadowing.
- shepmaster 8y ago> for Optional promotion You'll see the same in Rust fn example(name: Option<String>) -> Option<usize> { let name = name?; Some(name.len()) } Or fn example(name: Option<String>) { if let Some(name) = name { println!("{}", name.len()); } } A main difference is the requirement to use `Some`, which allows for the flexibility to apply to any enum. > but since `self.` is implicit To make sure I'm following, do you mean that Rust's `self.` is implicit in Swift?
- mlex 8y agoYeah `self.` is implicit. In Swift: struct S { var string: String func doSomething() { // These two lines are equivalent. print(string) print(self.string) } }
- favorited 8y agoThat all makes sense. I've only done a couple days of Rust, so my recollection is spotty. The shadowing makes sense because if a local variable was moved out, then you're not really shadowing it anymore. Is my understanding of that correct? > do you mean that Rust's `self.` is implicit in Swift? Swift's `self.` is implicit in Swift – in most contexts, to access a property the `self.` is not required. `self.name = "John"` and `name = "John"` are equivalent (assuming self is an object with a name property). There are places where explicit `self.` is required though – when you want to differentiate between a shadowed local and a property (obviously), or when you're inside a closure (to make it clear that the closure is capturing self, not just capturing a reference to the property).
- shepmaster 8y ago> The shadowing makes sense because if a local variable was moved out, then you're not really shadowing it anymore. Is my understanding of that correct? This is kind of a philosophical corner: can you shadow something that isn't there anymore? Once you've moved out of something, if you attempt to use the old name, then you'll get a compiler error different from "no such variable", so it's still there in some sense. Pragmatically, I think you are on the money.
- dcow 8y agoI actually really try to avoid this pattern. For one it pollutes the function scope with a shadowed binding and it's pretty unnecessary boilerplate. Most always you can map across the optional and use the unwrapped version as the block scoped argument identifier, e.g. `$0`. When you can't or you want to handle both cases, I find a simple `if let delegate = delegate {} else {}` is more explicit and scopes the binding to the block instead of polluting the current scope. I'm not saying `guard` is bad, I use it all the time when there are good names to bind things to, but I dislike how much it proliferates and how often it doesn't actually provide value and just lets the program silently fail instead of loudly fail which half the time is worse than a nullpointerexception anyway...