-
Notifications
You must be signed in to change notification settings - Fork 75
Should we include “optional property assignment” a?.b = c #18
Comments
Another question is whether this code should evaluate a?.b = c() In CoffeeScript, it skips the evaluation of Skipping the evaluation of Of the 37 examples from #17 (comment), two of them seemed like they might be affected by this:
|
Unless you rely on side-effects – in which case you are responsible to learn exactly if and when evaluation occurs –, you won't see a difference. So, in order to avoid unnecessary work from the engine, I am for skipping the evaluation of the RHS. |
AFAICT, there are five cases where property assignment may occur, and where optional property assignment might be considered:
|
if
then
is quivalent to:
|
This all gets a bit complicated. Do you have concrete use scenarios in mind that justify the complexity? |
@littledan Basically, concrete use cases are from the CoffeeScript samples linked in Comment 0. I’ve not delved deep into them, but here are two excerpts that seem reasonable at first sight: @component?.element.component = null and: modal = $('#create-account-modal').data('bs.modal')
modal?.options?.keyboard = false |
Is it this one, from #17 usage statistics?
|
Yes. |
My experience from dealing with assigning to deeply-nested-possibly-null structures has almost universally been that when there's a null I want to actually create the key and then successfully assign to it. I'm hard pressed to come up with a time when I'd want to skip the assignment entirely. |
Just wondering on the original question: if you leave assignment out, does it corner you? That is, if you completely ignore this feature and get the "read" in, does it prevent you (or make it harder) from ever doing the "write/assignment"? If it doesn't, then it might be smart to de-couple and discuss these features in isolation (the "read" and the "write" separately) and turn this into a sequencing problem (i.e. in which order we bake things into the language, rather if we should or not)? |
Deeply-nested-possibly-null structures are not the unique use-case of optional chaining. Here is a synthetic example. Suppose that I have an element of the DOM. If the element is found inside a <details> section, I want to open that section: elem.closest('details')?.open = true |
@samuelgoto There is no technical problem in postponing the “write” case. If that helps to accept the “read” case more rapidly, it will be indeed postponed. |
OK, seems like there's a rough agreement in this thread not to do the write case in the first iteration. |
We also discussed this question at TC39, and the committee did not seem so interested in adding this feature. |
Somewhat sad, but ok. I've just updated the README, stating that it won’t be supported for now. I'm also going to delete the quite numerous old off-topic comments in this thread, in order to keep this discussion more readable for future reference. (Anyway, thanks to all for the feedback, even for off-topic one.) |
To me the ”read” case is by far the most usable between the two. The ”write” case would be a nice future bonus |
Mark me down as another I'd love to have this feature if such a tally exists. I'm one of the authors of Trix, and am happy to see its usage included in #17 (thanks, @alangpierce!). I don't write much CoffeeScript these days, but do use optional chaining via Babel's plugin. Lack of support for assignment caught me by surprise right off the bat. Here's a snippet of code I attempted to write (extracted from a append({ id, html }) {
const element = document.getElementById(id)
element?.insertAdjacentHTML("beforeend", html)
}
prepend({ id, html }) {
const element = document.getElementById(id)
element?.insertAdjacentHTML("afterbegin", html)
}
replace({ id, html }) {
const element = document.getElementById(id)
element?.outerHTML = html
}
update({ id, html }) {
const element = document.getElementById(id)
element?.innerHTML = html
} Nice and symmetrical, right? Unfortunately, the last two methods are invalid, and require an additional |
Concerning optional/conditional assignment, Id prefer something like element.innerHTML ?= html; You don't need to be granular about it, i.e. any link/node/property in the chain could be missing the result would be the same: no assignment. |
I do want to be granular in absence of good reason for the contrary. It’s way better both for debugging and for understanding the meaning of code you didn’t just write. |
If I wanted to be explicit about it I wouldn't have used a shorthand and just relied on an It would be a perversion to constantly use |
Conciseness without granularity is something I’d personally consider an antipattern anywhere. The goal of the proposal is, for a specific value only, to avoid operating on it if it’s nullish. That does indeed require being granular. |
What I am saying is that I consider this usage a separate matter that doesn't require the granularity. |
@Mouvedia From experience (not restricted to programming), I can say it is very advantageous to be both concise and precise. For this particular example ( |
Honestly, to me That's how I personally intuit that; but let's see how the logic holds up.
IMHO Also if we use |
If |
In case it's not clear in my comment above, I'm not suggesting an alternate syntax like I would just like to see optional property assignment supported (e.g. |
They'll all be added at the same time. https://github.com/tc39/proposal-logical-assignment |
for (a?.b of [1,2,3]) {...}
({x: a?.b} = {});
a?.b ??= d; All these code looks confusing (got new killer questions for js interview 🤯)... I hope we could disallow them if we add optional assignment 😂 |
Optional chains are false for
This makes perfect logical sense ( |
@dantman
Some programmers roughly read it as if (a?.b == null) {
if (a == null) a = {}
a.b = d;
} |
It's too complicated. if (a != null)
a.b.c().d = e; could be tmp = a?.b?.c()
if(tmp != null){
tmp.d = e
} |
Note,
I also think this is the wrong way to do it. Creating the intermediate objects seems like magic. |
I was going say it more energetically: Please, stop discussing
While it would have a well-defined theoretical meaning (although not exactly the one you gave), it is basically taking two unrelated operators and mixing them randomly in a same expression. The fate of such an expression could very well be the same as |
should this be |
Thanks guys! Now instead of writing this
|
First off, I much appreciate the effort that went in to optional chaining and null coalescing functionality. A huge benefit for the community.
In this example, it really sounds like you would like to propose a new feature. This is well within your power to do so. Also, I suppose I should add, if you are calling a function twice like this, you would be better off doing something like:
While it does not address your initial request, it at least limits the function call to a single execution, and also simplifies the code, reducing copy paste errors and the like.
This would improve code clarity, and reduce overly long lines. In any case, I highly encourage you to introduce a proposal via the TC39 processes, and carry it through to completion. Hope this helps in getting new features into the EcmaScript standards. I look forward to seeing your contributions, since this feature could be of value. |
For the most general case illustrating short-circuiting, the instruction:
is equivalent to:
@alangpierce has found real-world usages of that form in CoffeeScript, some of them seem reasonable, including two-level deep chains
a?.b.c = d
:https://gist.github.com/alangpierce/34b7aa40cda51b0a089a44680bdfed7e
Should we include that? In particular, are the semantics clear enough? There are the following subcases:
a?.b = c
a?.b += c
,a?.b >>= c
, etc.a?.b++
,--a?.b
, etc.{ x: a?.b } = c
,[ a?.b ] = c
, etc.for (a?.b in c)
,for (a?.b of c)
The text was updated successfully, but these errors were encountered: