Even if you were using a type that could only be mutated, I'm not sure what you think that example illustrates other than bad naming and an insistence on shadowing. An actual readable example would be something more like:
let baseURL = URL()
var oneDirectoryUp = baseURL
oneDirectoryUp.deleteLastPathComponent()
useURL(oneDirectoryUp)
var newPlace = baseURL
newPlace.appendPathComponent("NewPlace")
useURL(newPlace)
That’s fair.
I don’t love my suggestion, it’s just a thought. It’s definitely not any more clear to read.
I’m all for short hand, but let and var declare something and the proposed syntax disregards that. Remove if and it’s nit even a statement. I think it needs a little more clarity. My example is just a suggestion.
Command-clicking the LHS of if let foo = foo doesn't do anything useful because you're already at the point of declaration. Having Xcode behave differently for if let foo { could work, but would be inconsistent.
I don't see how this change could ever allow such shadowing. The identifier used in if let foo has to be valid for a user-declared variable, and $0 is never allowed in declarations. if let $0 = $0 is not a valid way to unwrap an optional unnamed parameter.
Since no one wrote it yet, how about if let? foo {}?
var x: String? = …
if var? x {
// Now x is an alias to var x : String
}
// x is back to var x : String?
if let? x {
// Now x is an alias to let x : String
}
Both let? and var? would point to the same storage, not a copy. (var? only works for var … : …?).
I think using declaration keywords without actual binding doesn't make any sense. Without a new binding, the spelling would be if x or if x? which both are introducing (same) obscurity already described in this thread.
Likely not - it would be if let <label> and not if let <expression>, to declare that you are shadowing the variable with label the foo variable of type Optional<T> with a foo variable of type T within the block.
Optionals are not Booleans, we need to be careful to make the syntax distinct to prevent confusion and ambiguities.
if foo is also somewhat confusing to new developers as it is not constraining the type of foo (as it would in a language with nullable reference types like Javascript or Java), but creating a non-optional, immutable copy.
Leaving aside the brevity is less important than clarity at the point of use principle, which is a core Swift value I'm not looking to challenge, I believe it's not necessary for the new developers, or developers in general to think of this construct as doing a non-optional immutable copy. That's an implementation detail, from the consumer's point of view, you unwrap a value.
Also, taking into consideration the brevity vs clarity principle, I really don't think there's much that can be improved over the current if let. It's 100% in tune with that idea. The only question that might be answered is if there's a point into sacrificing one for the sake of the other.
Regarding foo not being a Boolean. It wouldn't be the first instance where the type would define the behaviour (i.e. custom operators, even overloaded methods). So, there's a precedent even to that.
Again, the more I think about it, the more I realize if let is perfectly in tune with Swift core values and should probably not change.
I personally don't like the suggestions that involve implicit assignment.
Not sure if it has been suggested before, but the following syntax feels explicit and familiar:
if let foo? {
doStuffWithFoo($0)
}
It closely resembles the following, which is valid today:
foo.map {
doStuffWithFoo($0)
}
As well as:
switch foo {
case let foo?:
doStuffWithFoo(foo)
...
}
The downside is it clashes with unnamed closure arguments, but that's already the case with multiple nested closures, so not much of a problem in practice IMO.
I'd prefer if case let foo? { ... } even more but AFAIK this wouldn't allow several optionals to be bound.
Being unable to assign to the value is a big deal, and when a programmer new to swift is unable to do so because the variable is shadowed with an immutable copy it is important to be able to explain it to them
I agree with @Ben_Cohen that this would be a bad place to use $0. Every other use of let, including case let, introduces a new named variable. _ notwithstanding. It would be extremely odd if this shorthand didn't also introduce a new variable.
I agree that there is a problem to solve here, but I don't like the use of if let x { syntax for this.
This is abusing the keyword let, muddying its meaning.
This begs the question of whether if var x { would do the same thing with a mutable copy/rebinding, which then begs more questions when we get to move semantics etc.
This is a fundamentally new concept. If it is important enough to add, it should be important enough to name. Why couldn't we use something like if unwrap x { or some other word for this? That would allow the documentation, explanation, and semantics to all be definable without building on pattern matching, value binding and other things that let carries with it.