`if let` shorthand

Given how idiomatic Swift operates, I’d go so far as to say that var in general isn’t that common.

After all, value types are (more or less) inherently immutable, such that “mutation” is really just “replacement”. Add lazy method composition, and a lot of Swift might as well be Haskell.

It’s not the syntax that’s the problem it’s the semantic meaning. if var x=x is a special case of if var closureName = someVariableName. That’s syntax that you can use coherently in something like:

if var counter=someVariable{
      [do stuff with the counter here]
       return counter}

*obviously with the counter having a name that is descriptive of how you’re using it in the closure

But I struggle to imagine a situation where creating a mutable shadow makes semantic sense. I’d love to see motivating examples here.

2 Likes

Let's please avoid those kinds of generalisations and disparagements. It's a feature in the language - if people want to use it, they are very well entitled to do so.

It is actually a compiler warning if a var is not mutated, so presumably those cases are still examples of correct use.

7 Likes

My only concern with if let x { and if var x { is that they worsen a situation which is already not ideal.

if let a = foo() { ... } has to be learnt. It is unique to Swift, and I never met anyone who can guess what it does. I have been teaching this Swift construct several times. The answer is usually :roll_eyes: - and then we move on.

if let x = x { ... } adds another difficulty: one has to understand that a variable is shadowed inside the brackets. Again, this is impossible to guess.

In this landscape, if let x { ... } is just another layer of arbitrary syntax that is only obvious for those who can afford such knowledge.

(Aside: the relationship between if let x = x and if case .some(let x) = x, I mean the fact that if let x = x is a form of pattern-matching, has never sounded convincing to me, regardless of the genesis of this syntax: I can't learn if let x = x from other pattern matching syntaxes).

To me, all claims of "obviousness" I read here sound not convincing at all. This is, on the contrary, one of the less obvious part of the language. I don't say it is difficult to learn and use. Swift has excellent support for the Optional concept.

All in all, I don't see at all the necessity of the if let x { sugar. If it ships, I'll use it of course, and even enjoy it, because I am "in the know".

23 Likes

Karl, my comment was based on what I saw on GitHub, you can see it for yourself:

https:// github. com /search?q=%22if+var%22+filename%3A*.swift&type=code (remove spaces)

1 Like

I agree that Optional binding is one of those things you really do need to learn in the first place, but I don’t think there’s much room for improvement there.

In fact, I’d argue that one of the most important things you need to know (that is, things that aren’t fairly easy to pick up on the fly) in Swift is what Optionals are (seeing the actual implementation is quite illuminating), the methods of handling them, and which method to use when.

Things like that are distinguished by being easily overlooked in favor of antipatterns, such that someone may write a considerable amount of Swift code without realizing there are better ways.

1 Like

This frames "uncommon" in terms of the ratio of times var is needed versus let but that's really measuring how incredibly common if let is.

By a different measure, you could describe if var as very common. I've checked over a dozen projects and found it in every one. That includes MovieSwiftUI, NetNewsWire, Apollo, Carthage, Attabench, and the swift standard library, driver, and package manager.

4 Likes

I fully agree with you. The way optionals are handled in the language is great.

1 Like

It bugs me that one's opinion could rely heavily on their naming discipline and codebase convention. The number of characters you save is roughly three + the variable length. So depending on your average variable length, it could either be a blessing or a minor quirk you now need to learn. It's easily a polarizing feature.

Also, names very close to the original variable (foo), such as ones with prefixes (selfFoo) or suffixes (foo1), get absolutely nothing out of it. They are also another group of common cases when you need to differentiate similar variables, add extra information, avoid shadowing, etc. That on its own is not a problem, but one could try to bend their convention to increase the chance of utilizing this. It, in disguise, is blessing a particular group of code conventions.

5 Likes

I don't think if let x = x { is an antipattern. We are not discussing a way to fix a harmful language idiom, here.

2 Likes

This doesn’t give you if var x=x, it gives you if var y=x. Here we’re specifically discussing shadowing. What’s the frequency of if var x= used for shadowing?

It is likely more useful in guard var x = x where you want to ensure you can unwrap a value and then need to mutate the unwrapped value.

But my question was in the context of the whether the existing optional unwrapping to a shadowed variable was a current notable source of confusion or bugs. If it's possible, but rarely used, or has few use cases, then it would rarely have an opportunity to cause bugs or incur a significant cost of confusion.

I tried the quoted repos and found zero "if var" in them ("if var" repo:MovieSwiftUI in search field in GitHub).

My GitHub search fu is not strong enough to find that answer (or the answer to a similar question how many usages of "var param = param" to compensate for a missing "var param: T" feature. If I have to guess I'd say "if let x = x" shadowing is 1/3 of all "if let" usages and "if var x = x" shadowing is probably 1/50 of all "if var" usages. Anyone with strong GitHub search skills please correct me.

I'd rather we didn't delegate the question of whether if var x should be supported to the Github search box.

IMO, if var should be supported because if let is. Any questions about future language features can be litigated if or when those future features arise. We already use let and var for this purpose, both in if let, if case, and other pattern-matching features. This simple shorthand is not doing anything novel which would impede progress on those (unpitched, unscoped, undefined) future features.

6 Likes

That doesn't seem to be the right way to do the search using GitHub (my search was with grep on a local checkout I had) but it's definitely there:

(edit: permalink as current source could change)

(Reposting after deleting my original post, I replied to the wrong person by mistake)

For me, I think introducing a new keyword for this purpose introduces more complexity than it resolves.

If the keyword is only used as a synonym for if let x = x, then it needs to be mixed and matched with if let-style bindings when multiple items are bound in a single statement:

if unwrap user, let defaultAddress = user.shippingAddresses.first { }

This is easily a point of confusion to people new to the language, but it would be a natural question for everyone to ask "Why can't I use unwrap in both cases? Why do I have to use let sometimes and unwrap sometimes?"

It wouldn't seem to make much sense to be able to use unwrap in one case and not the other. To fix this friction, a next step would be to allow unwrap instead of let for optional binding:

if unwrap user, unwrap defaultAddress = user.shippingAddresses.first { }

And, on its own, I think that reads perfectly well.

But, without a source breaking change, if unwrap would always need to exist alongside if let. Some projects will prefer one or the other, essentially creating two dialects of Swift for an incredibly common construct. And to move between codebases, everyone will need to know and understand both syntaxes (and if working on different projects keep track of which project prefers which style).

I think in practice both the "mix and match" style and the "both coexist" style would add a good deal of unwanted complexity over the current state of things and over the proposed solution.

Edit: Fixed Typo

9 Likes

While consistency is used too often on here as a primary justification, I think it's reasonable to say that gratuitous inconsistency without reason should be avoided. If if let x is sugar for if let x = x, then it would be eyebrow raising to learn that you cannot write if var x for IMO unjustified reasons.

And I come back to my counter that this harm is being greatly exaggerated. It just does not seem credible to suggest that anyone will be confused that this specific use of var takes a mutable borrow not a copy, unlike all other uses of var. Likewise, claiming the var in if var x is "nearly invisible" also seems like like hyperbole, and again not materially different from the existing unsugared syntax.

So it seems there are two threads here:

  1. The proposed sugar is unnecessary/not the right sugar.
  2. It might be made less necessary by/clash with some future proposed syntax for borrowing.

My suggestion to is we resolve 1 first, and establish whether or not Swift as it stands today (or is likely to stand in the next major release) would merit this syntax – whether it's the right spelling and whether it's needed at all.

Once that is established, maybe 2 is worth discussing. If point 1 isn't established, point 2 becomes moot. But it should be left to one side for now, otherwise the discussion becomes incoherent.

10 Likes

All this proposal seems to bring to the table is saving a few characters of typing. It doesn't make it possible to do things in Swift that couldn't be done before. It may be sugar but I don't think it's sweet.

The basic fact is that optionals are a pain in the neck. They make my simple, elegant, code complicated and awkward, at times. I think that some proponents of this feature believe it will remove the awkwardness of optionals. I doubt that removing the few characters of extra typing will do that.

I freely admit that I don't have any better suggestions to make optionals more ergonomic or convenient to use. I work with devs that make every effort to use shrtVarNms and I'm sure they would eat this up. Not me.

6 Likes

I was using github stats to back the point of view that if there are not many legitimate usages of "if var x = y", among those there are even fewer "shadowing" usages "if var x = x", then there is no desire among users to walk those paths, and there is nothing to pave.

Indeed, you are right: turns out repository name must be fully qualified when using GitHub search to search in a particular repo.

If you're not in the GitHub Code Search preview (cs.github.com), GH's code search is pretty bad and really shouldn't be used to gather information used to make a decision. Using that system turns up many results.

I'm almost opposed to this feature because I think optionals should be painful, and that pain should encourage developers to properly model things non-optionally. In the vast majority of Swift code I see, optionals are used to quickly deal with things like decoding issues or builds a value over time, when they aren't really the proper solution in many of those situations. So if people find them annoying to deal with, good! Reevaluate your model to see if they're actually necessary.

But this sugar is at least a little helpful, so I'm not opposed.

1 Like