Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a optional value setter ??= #63

Merged
merged 1 commit into from Jan 29, 2016
Merged

Introduce a optional value setter ??= #63

merged 1 commit into from Jan 29, 2016

Conversation

jcampbell05
Copy link
Contributor

Introduce a new operator an "Optional Value Setter". If the optional is set via this operator then the new value is only set if there isn't an already existing value.

Swift-evolution thread: link to the discussion thread for that proposal

@jcampbell05 jcampbell05 changed the title Create 0015-OptionalValueSettier.md Create 0015-OptionalValueSetter.md Dec 16, 2015
@jcampbell05 jcampbell05 changed the title Create 0015-OptionalValueSetter.md Introduce a optional value setter ??= Dec 16, 2015
@kud1ing
Copy link

kud1ing commented Dec 16, 2015

I could imagine it's preferred to squash the commits into one.

@radex
Copy link
Contributor

radex commented Dec 16, 2015

I think it's worth pointing out that there's a (sorta) precedent in other languages, e.g. ||= very popular in Ruby.

@jcampbell05
Copy link
Contributor Author

@radex Definitely, I have mentioned that in my proposal.

@jcampbell05
Copy link
Contributor Author

@dabrahams I updated, is this what you mean't ?

@dabrahams
Copy link
Contributor

@jcampbell05 yes, although you missed a couple of spots. Also I would use something other than [] for the RHS to reduce the possibility of confusion.

@jcampbell05
Copy link
Contributor Author

@dabrahams do you mind providing a better example?

Another local variable ?

@radex
Copy link
Contributor

radex commented Dec 16, 2015

@jcampbell05 I think what Dave meant is that you now have brackets (subscript) on the left-hand side, and brackets (empty array) on the right hand side. How about an empty string?

@jcampbell05
Copy link
Contributor Author

@radex Cool I have updated :)

```
## Impact on existing code

Since this is a new feature, it won't effect existing code and should make code more concise going forward.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor] this should read "won't affect existing code", not "effect"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated this.

@richardjrossiii
Copy link

(Somewhat) relevant stackoverflow discussion, on why GCC's ternary extension in C (?:) doesn't support assignment:

http://stackoverflow.com/questions/16925429/why-doesnt-gccs-ternary-extension-support-assignment

@stephencelis
Copy link
Contributor

I'd like to see more compelling, real-world examples (rather than the foo-like really.long.lvalue[expression]) before this gets considered for review.

I used ||= in Ruby all the time, but that's because Ruby has a nil problem. In Swift, I find the solution usually lies in a different design that avoids optionals entirely. I can't find a single instance where I've written a = a ?? b in Swift.

Can any of you provide real-world examples of where you'd want to use ??= in any of your codebases? Is it something you find yourself reaching for all the time? I think this needs to solve a very common problem to be added to the standard library, and I still don't know if ??= solves a real problem.

@dabrahams
Copy link
Contributor

On Dec 21, 2015, at 8:53 AM, Stephen Celis notifications@github.com wrote:

I'd like to see more compelling, real-world examples (rather than the foo-like really.long.lvalue[expression]) before this gets considered for review.

I used ||= in Ruby all the time, but that's because Ruby has a nil problem. In Swift, I find the solution usually lies in a different design that avoids optionals entirely. I can't find a single instance of writing a = a ?? b in Swift.

In the case of really.long.lvalue[expression] you’d probably write

if really.long.lvalue[expression] == nil {
really.long.lvalue[expression] = /* something else */
}

So looking for “??” isn’t likely to turn up much in this case.

Can any of you provide real-world examples of where you'd want to use ??= in any of your codebases? Is it something you find yourself reaching for all the time? I think this needs to solve a very common problem to be added to the standard library, and I still don't know if ??= solves a real problem.


Reply to this email directly or view it on GitHub #63 (comment).

-Dave

@stephencelis
Copy link
Contributor

On Dec 21, 2015, at 3:22 PM, Dave Abrahams notifications@github.com wrote:

if really.long.lvalue[expression] == nil {
really.long.lvalue[expression] = /* something else */
}

Fair point, though I don't really have any nil-test assignments either :) I seem to have preferred default values.

Stephen

@stephencelis
Copy link
Contributor

On Dec 21, 2015, at 3:27 PM, Stephen Celis stephen.celis@gmail.com wrote:

On Dec 21, 2015, at 3:22 PM, Dave Abrahams notifications@github.com wrote:

if really.long.lvalue[expression] == nil {
really.long.lvalue[expression] = /* something else */
}

Fair point, though I don't really have any nil-test assignments either :) I seem to have preferred default values.

Ah, scratch that, a few dictionary assignments came up. I'll try to see if there are any other common cases.

Stephen

@jcampbell05
Copy link
Contributor Author

When implementing a collection view or table view where I need to reuse a cell (I also have a custom one I have built), I have this:

'''swift
var view = collectionView.dequeueCell(....)

If view == nil
{
view = MyCell()
}

//cell setup code

return cell

'''

With this operator I could do this:

'''swift
var cell = collectionView.dequeueCell(...)
cell ??= MyCell()

//cell setup code

return cell

'''

So I would imagine it would be used a lot for providing defaults in a dictionary when one isn't set or as a way of constructing an object (like above) when a cached instance isn't available.

You could have it all on one line but I think this would be a great operator as some variable names can be long so you have to put it on multiple lines via an if to avoid making a long line but then it isn't as concise.

@jcampbell05 jcampbell05 reopened this Dec 22, 2015
@stephencelis
Copy link
Contributor

@jcampbell05 UICollectionView's dequeue method doesn't return an optional cell. If you mean UITableView's dequeueReusableCellWithIdentifier:, have you tried dequeueReusableCellWithIdentifier:forIndexPath: instead? It's been preferred since iOS 6, and always returns a cell (so no need for the nil-test assignment dance).

Even if these dequeue methods returned optionals, I still prefer using let to avoid accidental mutation later in the method.

let cell = tableView.dequeueReusableCellWithIdentifier(identifier) ?? MyCell()

I am a little afraid that adding ??= to the standard library would encourage mutability where it could easily be avoided.

I'm open to more examples. A dict[key] ??= val seems to be the main common case to me, though in these cases I'm generally interested in whether or not the key was set, which can't be deduced when using ??=.

@jcampbell05
Copy link
Contributor Author

@stephencelis I have built a view that works similar to those views so the ??= would be handy. You're right with the Apple default classes I would avoid the nil dance.

In any case I have noticed there is a proposal for a or pipe operator like so, which I think is a superior option:

let value =| function() where .Some
           |  10

The idea is it will set let with the first case that matches :) so this could be a much more powerful way of expressing ??= or a ?? b or (a) ? a : b or switch (x) ....

So I would happily close this, in favour of that proposal.

@lattner
Copy link
Collaborator

lattner commented Jan 26, 2016

Please squash these commits.

Update and rename 0015-OptionalValueSettier.md to 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Update 0015-OptionalValueSetter.md

Improved spelling, grammar, and formatting.
@jcampbell05
Copy link
Contributor Author

@lattner Squashed :)

@lattner
Copy link
Collaborator

lattner commented Jan 27, 2016

Looks reasonable for review, to @DougGregor to find a review manager.

DougGregor added a commit that referenced this pull request Jan 29, 2016
Introduce a optional value setter `??=`
@DougGregor DougGregor merged commit 7ad80af into apple:master Jan 29, 2016
jckarter pushed a commit that referenced this pull request Mar 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
9 participants