Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #30587 > unrolled thread
| Started by | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| First post | 2016-05-31 14:38 +0200 |
| Last post | 2016-06-02 15:51 -0700 |
| Articles | 8 — 3 participants |
Back to article view | Back to comp.lang.javascript
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: not "autovivification", but ...? Stefan Weiss <krewecherl@gmail.com> - 2016-05-31 14:38 +0200
Re: not "autovivification", but ...? "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2016-06-01 08:03 -0700
Re: not "autovivification", but ...? Stefan Weiss <krewecherl@gmail.com> - 2016-06-01 19:49 +0200
Re: not "autovivification", but ...? "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2016-06-01 14:29 -0700
Re: not "autovivification", but ...? Stefan Weiss <krewecherl@gmail.com> - 2016-06-02 01:29 +0200
Re: not "autovivification", but ...? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2016-06-02 02:16 +0200
Re: not "autovivification", but ...? Stefan Weiss <krewecherl@gmail.com> - 2016-06-02 13:20 +0200
Re: not "autovivification", but ...? "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2016-06-02 15:51 -0700
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2016-05-31 14:38 +0200 |
| Subject | Re: not "autovivification", but ...? |
| Message-ID | <nik0k5$8mu$1@news.albasani.net> |
Stefan Ram wrote:
> If Perl's autovivification would exist in JavaScript, this
> would mean that in a new interpreter instance, the evaluation
> of the expression
>
> a.b.c = 1;
>
> would implicitly create the object »a« and »a.b«
> and then assign »1« to the property »c« of »a.b«.
Perl's autovivification is a special case. It looks very user-friendly at
first glance, because it can automatically create intermediate structures
when they're needed - but it also does that on access, not just on
assignment. Examining a value can modify it, which is a common source of bugs:
my %hash;
if (exists $hash{foo}{bar}{baz}) {
say "this statement never executes";
}
Looks innocent enough, but %hash has just been changed from `undef` to
( foo => { bar => {} } )
> We do not have this in JavaScript, but we do have
>
> "use strict"; this.b = 1;
>
> . That is, when »this.b« is a assigned to - even in strict mode -
> a new property »b« is implicitly created. No declaration (with
> »var«, »let«, or »const«) is required.
>
> Is there a name for this »feature« of JavaScript?
> Maybe »semivivification«, because it's like
> autovivification, but not so strong?
I would advise against using the name (auto/semi)vivification, if only to
avoid the negative connotations this feature has in Perl (at least for
experienced programmers).
There is a perfectly good description for this behavior in JavaScript, and
you even used it yourself: implicit property creation.
In both languages, there are ways to prevent this implicit creation: the "no
autovivification" pragma in Perl; strict mode and object sealing or freezing
in JS.
- stefan
[toc] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2016-06-01 08:03 -0700 |
| Message-ID | <1dc7bd11-343d-4cbb-b75d-1db8516666a0@googlegroups.com> |
| In reply to | #30587 |
On Tuesday, May 31, 2016 at 7:38:35 AM UTC-5, Stefan Weiss wrote:
> Stefan Ram wrote:
> > If Perl's autovivification would exist in JavaScript, this
> > would mean that in a new interpreter instance, the evaluation
> > of the expression
> >
> > a.b.c = 1;
> >
> > would implicitly create the object »a« and »a.b«
> > and then assign »1« to the property »c« of »a.b«.
>
> Perl's autovivification is a special case. It looks very user-friendly at
> first glance, because it can automatically create intermediate structures
> when they're needed - but it also does that on access, not just on
> assignment. Examining a value can modify it, which is a common source of bugs:
>
> my %hash;
> if (exists $hash{foo}{bar}{baz}) {
> say "this statement never executes";
> }
>
> Looks innocent enough, but %hash has just been changed from `undef` to
>
> ( foo => { bar => {} } )
>
> > We do not have this in JavaScript, but we do have
> >
> > "use strict"; this.b = 1;
> >
> > . That is, when »this.b« is a assigned to - even in strict mode -
> > a new property »b« is implicitly created. No declaration (with
> > »var«, »let«, or »const«) is required.
> >
> > Is there a name for this »feature« of JavaScript?
> > Maybe »semivivification«, because it's like
> > autovivification, but not so strong?
>
> I would advise against using the name (auto/semi)vivification, if only to
> avoid the negative connotations this feature has in Perl (at least for
> experienced programmers).
>
> There is a perfectly good description for this behavior in JavaScript, and
> you even used it yourself: implicit property creation.
>
> In both languages, there are ways to prevent this implicit creation: the "no
> autovivification" pragma in Perl; strict mode and object sealing or freezing
> in JS.
IME, multi-level implicit creation is a sign that something is wrong with your architecture. It makes me ask: "Why were these undefined in the first place?"
The dual issue for implicit creation is accessing a nested structure where one or more of the intermediate members may not exist. My same question above applies there as well: Why don't these already exist?
I think the lack of desire to revisit the architecture of the application leads to some interesting choices in how people code:
var foo = (((a || {}).b || {}).c || {}).d
and then helper functions to make that less awkward and more general:
Object.walk = (o, path)=>path.split('.').reduce((o,k)=>o && o[k], o);
var foo = Object.walk(a,"a.b.c.d")
and then language feature attempts to make it standard:
<https://esdiscuss.org/topic/the-existential-operator>
...
Where fundamentally people should take a step back and take a moment to think at a higher level about what they are trying to accomplish.
</end-pseudo-rant>
[toc] | [prev] | [next] | [standalone]
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2016-06-01 19:49 +0200 |
| Message-ID | <nin783$9qu$1@news.albasani.net> |
| In reply to | #30594 |
Michael Haufe (TNO) wrote: > IME, multi-level implicit creation is a sign that something is wrong > with your architecture. It makes me ask: "Why were these undefined in the first > place?" > > The dual issue for implicit creation is accessing a nested structure > where one or more of the intermediate members may not exist. My same > question above applies there as well: Why don't these already exist? > > [snip examples of workarounds] > > Where fundamentally people should take a step back and take a moment to > think at a higher level about what they are trying to accomplish. I sort of agree with this, to a point, but only if I created the data structure myself (or my application did). In many situations we simply don't have that level of control over data. Examples for this would be external APIs, JSON config files, or any other external tree-like structure mapped to nested objects. Are you saying that all data exchange formats with optional components are badly designed, or that at least all known container nodes should be present? I don't think that's a realistic requirement. - stefan
[toc] | [prev] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2016-06-01 14:29 -0700 |
| Message-ID | <d7cf47ca-3871-46e0-8434-b17ec1fe1440@googlegroups.com> |
| In reply to | #30596 |
On Wednesday, June 1, 2016 at 12:50:01 PM UTC-5, Stefan Weiss wrote:
> I sort of agree with this, to a point, but only if I created the data
> structure myself (or my application did). In many situations we simply don't
> have that level of control over data. Examples for this would be external
> APIs, JSON config files, or any other external tree-like structure mapped to
> nested objects.
> Are you saying that all data exchange formats with optional components are
> badly designed,
No. Nothing like that at all.
> or that at least all known container nodes should be
> present? I don't think that's a realistic requirement.
Nor this either.
Let me try to approach this another way to try and clarify my meaning:
<script>
var someObject = JSON.parse(foo);
</script>
If I could rely on the structure of someObject, I could use a definite access pattern:
<script>
var target = someObject.left.right.right.left.value
</script>
We know that's unrealistic in reality and we'd want to do some checking.
We could apply one of the patterns in my last message:
<script>
target = Object.walk(someObject,"someObject.left.right.right.left.value")
</script>
or let's assume the elvis operator was available in the language:
<script>
target = someObject?.left?.right?.right?.left?.value
</script>
Another example with the DOM:
<script>
var target2 = document.body.firstChild.nextSibling.lastChild
</script>
and again with the suggested operator as a more robust alternative:
<script>
target2 = document?.body?.firstChild?.nextSibling?.lastChild
</script>
I assume these two examples strike you as ridiculous, or at least suspect in what it is doing In your own applications, and many you've no doubt run across, you see such a thing not all on one line, but instead spread across methods and function calls as a parameter:
<script>
foo(someObject)
function foo(obj) {
if(obj && obj.left) {
// ...
bar(obj.left)
}
}
function bar(obj) {
if(obj && obj.right) {
//...
baz(obj.right)
}
}
function baz(obj) {
if(el && obj.right) {
//etc...
}
}
</script>
It's the same issue, but less obvious as it's spread across the program.
Now let's backup and look at the DOM example.
Instead of the above, you'd no doubt avoid such probing to find the element you want and would instead use a search of the data structure:
<script>
target2 = document.getElementById("targetNode")
</script>
But you generally don't see this being exercised against arbitary objects (with the exception of JSONPath users and such)
Partly this is due to the lack of such a general facility in JS, but also due to a different mindset when it comes to the DOM vs. JS objects.
If you are able to recognize the objects you deal with as being an instance of one of the well known data structures you can leverage such functionality as searching.
Even if you aren't provided such a structure you could use the Decorator Pattern to wrap that 3rd party structure and provide something more useful for your own portion of the application:
<script>
var data = new MyTreeConstructor(
someThirdPartyObject
);
var results = data.find("something")
result.forEach(...)
</script>
For simpler objects you can use the Decorator Pattern to provide sensible defaults just once.
[toc] | [prev] | [next] | [standalone]
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2016-06-02 01:29 +0200 |
| Message-ID | <ninr5k$gee$1@news.albasani.net> |
| In reply to | #30597 |
Michael Haufe (TNO) wrote: > On Wednesday, June 1, 2016 at 12:50:01 PM UTC-5, Stefan Weiss wrote: > >> I sort of agree with this, to a point, but only if I created the data >> structure myself (or my application did). In many situations we simply don't >> have that level of control over data. Examples for this would be external >> APIs, JSON config files, or any other external tree-like structure mapped to >> nested objects. > >> Are you saying that all data exchange formats with optional components are >> badly designed, > > No. Nothing like that at all. > >> or that at least all known container nodes should be >> present? I don't think that's a realistic requirement. > > Nor this either. > > Let me try to approach this another way to try and clarify my meaning: [summarized ways to access nested properties, if I understood correctly:] a) rely on the structure: someObject.left.right.right.left.value b) use a custom walk() method (or similar) c) use a specialized operator (like `?.`) d) spread across multiple functions e) use an alternate identifier (id attributes in the DOM) f) use something like JSONPath g) use a decorator to provide the search/path feature While this is a very useful list of techniques, I'm even more confused now... These are all used when we don't know if a certain branch (or path component) exists in a nested object. I thought your earlier point was that this situation shouldn't be allowed to occur in a well-designed application, but I'm probably misunderstanding something here: Michael Haufe (TNO) wrote: >>> The dual issue for implicit creation is accessing a nested structure >>> where one or more of the intermediate members may not exist. My same >>> question above applies there as well: Why don't these already exist? >>> >>> I think the lack of desire to revisit the architecture of the >>> application leads to some interesting choices in how people code [...] I'm not trying to make a case for implicitly *creating* multiple levels in a nested structure - even where that is supported, I usually go out of my way to avoid it. See the Perl example in my first reply. But accessing such a structure is very common and often cannot be avoided. Which of the mentioned techniques is used to solve this is a matter of preference, IMO. - stefan PS, a little off-topic: PHP is probably the worst language to work with in this regard. It will happily allow implicit multi-level creation in arrays - // ($foo is unused up to this point) $foo["bar"][13]["baz"] = "qux"; - but will emit E_NOTICE (a type of error) if we try to read a nonexistent index ($foo["x"]). Only with the relatively recent release of PHP7 did it get a null-coalescing operator: $x = $foo["baz"][14]["bar"] ?? "qux"; And when objects are involved... best not to think about it.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2016-06-02 02:16 +0200 |
| Message-ID | <6429329.X1ROTxqqWj@PointedEars.de> |
| In reply to | #30598 |
Stefan Weiss wrote:
> PS, a little off-topic: PHP is probably the worst language to work with in
> this regard. It will happily allow implicit multi-level creation in arrays
> -
>
> // ($foo is unused up to this point)
> $foo["bar"][13]["baz"] = "qux";
This is so very useful. (No sarcasm.)
> - but will emit E_NOTICE (a type of error)
A common misonception. It is a kind of debug message instead and can be
suppressed in various ways.
> if we try to read a nonexistent index ($foo["x"]).
^^^^^
The proper term is _key_, and if you write
@$foo["x"]
the notice will go away without any extra configuration.
F'up2 comp.lang.php
--
PointedEars (ZCE PHP)
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2016-06-02 13:20 +0200 |
| Message-ID | <nip4ps$vhs$1@news.albasani.net> |
| In reply to | #30602 |
Thomas 'PointedEars' Lahn wrote: > F'up2 comp.lang.php I don't read comp.lang.php. If you really want to talk about an off-topic remark, do it here. > Stefan Weiss wrote: > >> PS, a little off-topic: PHP is probably the worst language to work with in >> this regard. It will happily allow implicit multi-level creation in arrays >> - >> >> // ($foo is unused up to this point) >> $foo["bar"][13]["baz"] = "qux"; > > This is so very useful. (No sarcasm.) Useful, maybe. It's also more dangerous, because it won't warn you about a typo in one of the keys; PHP will silently build up a parallel structure if you mistype "bar". I would rather get the early warnings. >> - but will emit E_NOTICE (a type of error) > > A common misonception. It is a kind of debug message instead and can be > suppressed in various ways. E_NOTICE is not just emitted for undefined array keys or indices. If you disable or suppress it, you will no longer be warned about mistyped variable names, among other things. It's an important tool, and should enabled during development. > if you write > > @$foo["x"] > > the notice will go away without any extra configuration. And so will the more serious errors. The @ operator suppresses ALL recoverable errors, not just notices. @$fooo["x"] or @$foo[x] will not trigger any warnings. (The @ operator also used to produce a noticable performance overhead in earlier versions, but this is now negligible.) - stefan
[toc] | [prev] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2016-06-02 15:51 -0700 |
| Message-ID | <3c790fb8-db3c-4ce0-a990-9567b84154e6@googlegroups.com> |
| In reply to | #30598 |
On Wednesday, June 1, 2016 at 6:30:01 PM UTC-5, Stefan Weiss wrote: > [summarized ways to access nested properties, if I understood correctly:] > > a) rely on the structure: someObject.left.right.right.left.value > b) use a custom walk() method (or similar) > c) use a specialized operator (like `?.`) > d) spread across multiple functions > e) use an alternate identifier (id attributes in the DOM) > f) use something like JSONPath > g) use a decorator to provide the search/path feature > > While this is a very useful list of techniques, I'm even more confused > now... These are all used when we don't know if a certain branch (or path > component) exists in a nested object. I thought your earlier point was that > this situation shouldn't be allowed to occur in a well-designed application, > but I'm probably misunderstanding something here: I'll try to be more succinct. I didn't have enough time to write a shorter explanation [1]. A: This is what some people do which we probably agree is a bad idea because it is brittle and assumes everything is defined. B, C: To get around the problems of A, helper functions like Object.walk are made and JS language features are proposed. I claim that B and C are just workarounds for a problem that can be avoided completely, hence making B and C irrelevant. The problem is "Probing" [2] D: This is the same problem as B & C but in a different form (if-checks). This is also harder to see as it's spread across the program. If you have a tree/graph like object, you don't have to probe. You can search. E,F are examples of this. for other, simpler objects, you can use G as an approach to provide yourself with more sane data to work with. > Michael Haufe (TNO) wrote: > >>> The dual issue for implicit creation is accessing a nested structure > >>> where one or more of the intermediate members may not exist. My same > >>> question above applies there as well: Why don't these already exist? > >>> > >>> I think the lack of desire to revisit the architecture of the > >>> application leads to some interesting choices in how people code [...] > > > I'm not trying to make a case for implicitly *creating* multiple levels in a > nested structure - even where that is supported, I usually go out of my way > to avoid it. See the Perl example in my first reply. But accessing such a > structure is very common and often cannot be avoided. Which of the mentioned > techniques is used to solve this is a matter of preference, IMO. I think my explanation above subsumes this. HTH [1] "If I Had More Time, I Would Have Written a Shorter Letter" <http://quoteinvestigator.com/2012/04/28/shorter-letter/> [2] Probing: I don't know if I can use this property/method, so I better check to see if it exists first.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web