Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #21148 > unrolled thread

(golf-ish) Conditional object property access

Started bykj <no.email@please.post>
First post2013-09-02 20:23 +0000
Last post2013-09-02 23:10 +0200
Articles 7 — 4 participants

Back to article view | Back to comp.lang.javascript


Contents

  (golf-ish) Conditional object property access kj <no.email@please.post> - 2013-09-02 20:23 +0000
    Re: (golf-ish) Conditional object property access Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-09-02 21:52 +0100
      Re: (golf-ish) Conditional object property access Stefan Weiss <krewecherl@gmail.com> - 2013-09-02 23:11 +0200
      Re: (golf-ish) Conditional object property access Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-09-03 00:03 +0200
        Re: (golf-ish) Conditional object property access Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-09-02 23:19 +0100
          Re: (golf-ish) Conditional object property access Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-09-03 01:59 +0200
    Re: (golf-ish) Conditional object property access Stefan Weiss <krewecherl@gmail.com> - 2013-09-02 23:10 +0200

#21148 — (golf-ish) Conditional object property access

Fromkj <no.email@please.post>
Date2013-09-02 20:23 +0000
Subject(golf-ish) Conditional object property access
Message-ID<l02s3s$fdt$1@reader1.panix.com>


(WARNING: This is a "JavaScript golf"-type query, of little practical
import; just for those who get into this sort of thing...)


Quick version
=============

How to shorten the generic JavaScript expression

    o.hasOwnProperty('p') ? o.p : <EXPR>

...while still preserving the *conditional* evaluation of the <EXPR>
clause?  (Here <EXPR> stands for an arbitrary JavaScript
expression.)


----------------------------------------------------------------------

Leisurely version
=================

I'm dealing with JavaScript code where expressions having the form
above appear *all over*.

Given the frequency of this pattern, it would be nice if JS had
some special, and more succinct, syntax for it, e.g., something
like:

    o['p':<EXPR>]

...where the <EXPR> "clause" would be evaluated (and returned as the
value of the whole expression) *only if* o.hasOwnProperty('p') is
false[1].

Absent such syntactic help, how can one shorten the pattern given
above?

The best that my noob-level JS can come up with is to define a helper
function `HAS` (in a suitably restricted scope) to replace the verbose
built-in hasOwnProperty, so that one can at least write:

    HAS(o, 'p') ? o.p : <EXPR>

At the end of this post I give other alternatives I could think of,
but they are all either *more* verbose than what they try to replace,
or have some other weakness (e.g. failure to delay the evaluation of
the <EXPR> clause).

For the more expert JS coders out there: can one do better?

----------------------------------------------------------------------

Below are my various attempts:

    o.hasOwnProperty('p')?o.p:<EXPR>          // the one to beat

    o['p':<EXPR>]                             // hypothetical/theo-
                                              // retical minimum?

    HAS(o,'p')?o.p:<EXPR>                     // my disappointing best

    GET(o,'p',<EXPR>)                         // <EXPR> evaluated
                                              // unconditionally

    GET2(o,'p',function(){return <EXPR>})     // ambiguous when the
                                              // value of o.p may be
                                              // a function

    GET3(o,'p',T(function(){return <EXPR>}))  // T for Thunk


    function HAS(obj, prop) {
      return obj.hasOwnProperty(prop);
    }

    function GET(obj, prop, alt) {
      return HAS(obj, prop) ? obj[prop] : alt;
    }

    function GET2(obj, prop, alt) {
      return HAS(obj, prop) ? obj[prop] : alt();
    }

    function Thunk (fn) { this.fn = fn }
    function T(fn) { return new Thunk(fn) }
    function GET3(obj, prop, alt) {
      return HAS(obj, prop)       ? obj[prop] :
             alt instanceof Thunk ? alt.fn()  : alt;
    }

----------------------------------------------------------------------
[1] The "delayed", or, more precisely, *conditional*, evaluation of
the <EXPR> clause is an important aspect of the original
expression's semantics, and is therefore one that any alternative
formulation should retain.  I point this out because the first
alternative formulation that I came up with, the one using the
helper function `GET`, turns out to fall short in this respect.

[toc] | [next] | [standalone]


#21149

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-09-02 21:52 +0100
Message-ID<0.c54068976de565cd12fc.20130902215206BST.877gezuetl.fsf@bsb.me.uk>
In reply to#21148
kj <no.email@please.post> writes:

> (WARNING: This is a "JavaScript golf"-type query, of little practical
> import; just for those who get into this sort of thing...)
>
>
> Quick version
> =============
>
> How to shorten the generic JavaScript expression
>
>     o.hasOwnProperty('p') ? o.p : <EXPR>
>
> ...while still preserving the *conditional* evaluation of the <EXPR>
> clause?  (Here <EXPR> stands for an arbitrary JavaScript
> expression.)
<snip>
> The best that my noob-level JS can come up with is to define a helper
> function `HAS` (in a suitably restricted scope) to replace the verbose
> built-in hasOwnProperty, so that one can at least write:
>
>     HAS(o, 'p') ? o.p : <EXPR>

If HAS returns o.p when o.hasOwnProperty('p'), then you can avoid the
conditional

  HAS(o, 'p') || <EXPR>

Anything that uses functions to wrap EXPR for delayed execution suffers
from the fact the ECMAScript uses such a long keyword, and that the
syntax requires empty parentheses.  (I take it that one of the rules of
this golf game is that the expression should be short.)

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#21151

FromStefan Weiss <krewecherl@gmail.com>
Date2013-09-02 23:11 +0200
Message-ID<l02uu2$42f$2@news.albasani.net>
In reply to#21149
On 2013-09-02 22:52, Ben Bacarisse wrote:
>   HAS(o, 'p') || <EXPR>

Beat me to it :)

- stefan

[toc] | [prev] | [next] | [standalone]


#21155

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-09-03 00:03 +0200
Message-ID<1513771.HS4XPLjgls@PointedEars.de>
In reply to#21149
Ben Bacarisse wrote:

> kj <no.email@please.post> writes:

Such anti-social address munging leads to at least one killfile entry.

>> (WARNING: This is a "JavaScript golf"-type query, of little practical
>> import; just for those who get into this sort of thing...)
>>
>>
>> Quick version
>> =============
>>
>> How to shorten the generic JavaScript expression
>>
>>     o.hasOwnProperty('p') ? o.p : <EXPR>
>>
>> ...while still preserving the *conditional* evaluation of the <EXPR>
>> clause?  (Here <EXPR> stands for an arbitrary JavaScript
>> expression.)
> <snip>
>> The best that my noob-level JS can come up with is to define a helper
>> function `HAS` (in a suitably restricted scope) to replace the verbose
>> built-in hasOwnProperty, so that one can at least write:
>>
>>     HAS(o, 'p') ? o.p : <EXPR>
> 
> If HAS returns o.p when o.hasOwnProperty('p'), then you can avoid the
> conditional
> 
>   HAS(o, 'p') || <EXPR>

Incorrect.  There is a difference between an object having a property and 
converting the result of a property access to Boolean.  Assuming you meant

  function HAS (o, p)
  {
    if (o.hasOwnProperty(p)) return o[p];
  }

(where “HAS” is a very unwise identifier), if the value of o[p] was a false-
value, the result of

  HAS(o, 'p') || <EXPR>

would be

  <EXPR>

> Anything that uses functions to wrap EXPR for delayed execution suffers
> from the fact the ECMAScript uses such a long keyword, and that the
> syntax requires empty parentheses.  (I take it that one of the rules of
> this golf game is that the expression should be short.)

Harmony (ECMAScript Edition 6) is going to fix that with foo(bar => baz):

<http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax>

That aside, the rules would also have to include that at “o” and “o.p” do 
not hold references to host objects because those objects do not need to 
implement [[HasProperty]] and [[Get]] the standard way (they may even throw 
exceptions, as long-time subscribers should know).

I do not think this expression can be shortened (if you count the called 
function as well), while being value-equivalent, as long as it must be 
*generic*.

The “in” operator could be used if it did not consider inherited properties, 
whereas hasOwnProperty() does not.  So the shorter

  "p" in o?o.p:<EXPR>

must be excluded.  The proprietary, considerably safe

  "p" in o&&!("p" in o.__proto__)?o.p:<EXPR>

would not be shorter than

  o.hasOwnProperty('p')?o.p:<EXPR>

And the “in” operator should be forbidden with host objects because it uses 
[[HasProperty]].

Much depends on what is meant by “JavaScript”:

<http://PointedEars.de/es-matrix>

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#21156

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-09-02 23:19 +0100
Message-ID<0.cf0106c707f704dac5bd.20130902231902BST.87zjruuasp.fsf@bsb.me.uk>
In reply to#21155
Thomas 'PointedEars' Lahn <PointedEars@web.de> writes:

> Ben Bacarisse wrote:
>
>> kj <no.email@please.post> writes:
>
> Such anti-social address munging leads to at least one killfile entry.
>
>>> (WARNING: This is a "JavaScript golf"-type query, of little practical
>>> import; just for those who get into this sort of thing...)
>>>
>>>
>>> Quick version
>>> =============
>>>
>>> How to shorten the generic JavaScript expression
>>>
>>>     o.hasOwnProperty('p') ? o.p : <EXPR>
>>>
>>> ...while still preserving the *conditional* evaluation of the <EXPR>
>>> clause?  (Here <EXPR> stands for an arbitrary JavaScript
>>> expression.)
>> <snip>
>>> The best that my noob-level JS can come up with is to define a helper
>>> function `HAS` (in a suitably restricted scope) to replace the verbose
>>> built-in hasOwnProperty, so that one can at least write:
>>>
>>>     HAS(o, 'p') ? o.p : <EXPR>
>> 
>> If HAS returns o.p when o.hasOwnProperty('p'), then you can avoid the
>> conditional
>> 
>>   HAS(o, 'p') || <EXPR>
>
> Incorrect.  There is a difference between an object having a property and 
> converting the result of a property access to Boolean.  Assuming you meant
>
>   function HAS (o, p)
>   {
>     if (o.hasOwnProperty(p)) return o[p];
>   }
>
> (where “HAS” is a very unwise identifier), if the value of o[p] was a false-
> value, the result of
>
>   HAS(o, 'p') || <EXPR>
>
> would be
>
>   <EXPR>

Yes, good point.  I've used something similar, but in situations where
this problem would be unlikely.  I was too hasty, though I suppose it's
possible that || works in all the OP's use cases.

>> Anything that uses functions to wrap EXPR for delayed execution suffers
>> from the fact the ECMAScript uses such a long keyword, and that the
>> syntax requires empty parentheses.  (I take it that one of the rules of
>> this golf game is that the expression should be short.)
>
> Harmony (ECMAScript Edition 6) is going to fix that with foo(bar => baz):
>
> <http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax>

Nice.  The return is no longer needed in simple cases too.  It's always
seemed to me that the early designers never expected the wide use that
function expressions would get.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#21159

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-09-03 01:59 +0200
Message-ID<7836422.gBDQCprLM3@PointedEars.de>
In reply to#21156
Ben Bacarisse wrote:

> Thomas 'PointedEars' Lahn <PointedEars@web.de> writes:
>> Ben Bacarisse wrote:
>>> If HAS returns o.p when o.hasOwnProperty('p'), then you can avoid the
>>> conditional
>>> 
>>>   HAS(o, 'p') || <EXPR>
>>
>> Incorrect.  There is a difference between an object having a property and
>> converting the result of a property access to Boolean.  Assuming you
>> meant
>>
>>   function HAS (o, p)
>>   {
>>     if (o.hasOwnProperty(p)) return o[p];
>>   }
>>
>> (where “HAS” is a very unwise identifier), if the value of o[p] was a
>> false- value, the result of
>>
>>   HAS(o, 'p') || <EXPR>
>>
>> would be
>>
>>   <EXPR>
> 
> Yes, good point.  I've used something similar, but in situations where
> this problem would be unlikely.  I was too hasty, though I suppose it's
> possible that || works in all the OP's use cases.

I do not think there is a use-case here.  That is the very nature of code-
golfing, because it is more play than work: trying to find the shortest 
equivalent expression, however unreadable, to solve a *theoretical* problem.  
You would never used golfed code in production: it is probably inefficient, 
likely error-prone, and definitely hard to maintain.
 
>>> Anything that uses functions to wrap EXPR for delayed execution suffers
>>> from the fact the ECMAScript uses such a long keyword, and that the
>>> syntax requires empty parentheses.  (I take it that one of the rules of
>>> this golf game is that the expression should be short.)
>>
>> Harmony (ECMAScript Edition 6) is going to fix that with foo(bar => baz):
>>
>> <http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax>
> 
> Nice.  The return is no longer needed in simple cases too.  It's always
> seemed to me that the early designers never expected the wide use that
> function expressions would get.

ISTM that this particular syntax for lambda expressions was borrowed from 
C#, which in turn might have shortened that of Python.  I learned it when I 
first used LINQ extension methods about a year ago.

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#21150

FromStefan Weiss <krewecherl@gmail.com>
Date2013-09-02 23:10 +0200
Message-ID<l02us6$42f$1@news.albasani.net>
In reply to#21148
On 2013-09-02 22:23, kj wrote:
> How to shorten the generic JavaScript expression
> 
>     o.hasOwnProperty('p') ? o.p : <EXPR>
> 
> ...while still preserving the *conditional* evaluation of the <EXPR>
> clause?  (Here <EXPR> stands for an arbitrary JavaScript
> expression.)

[...]

> The best that my noob-level JS can come up with is to define a helper
> function `HAS` (in a suitably restricted scope) to replace the verbose
> built-in hasOwnProperty, so that one can at least write:
> 
>     HAS(o, 'p') ? o.p : <EXPR>
> 
> At the end of this post I give other alternatives I could think of,
> but they are all either *more* verbose than what they try to replace,
> or have some other weakness (e.g. failure to delay the evaluation of
> the <EXPR> clause).

I think that's about as close as you can get without special syntactic
sugar. If only the value of truthy properties is of interest, this form
could make a shorter alternative:

    HAS(o, 'p') || <EXPR>

    function HAS (obj, prop)
    {
        if (obj.hasOwnProperty(prop)) {
            return obj[prop];
        }
    }

Golf entertainment aspect aside, is the verbosity of hasOwnProperty()
actually bothering you? This method tends to be used more in libraries
than ad-hoc scripts, so the ugliness should stay well hidden most of the
time.

In a misguided attempt to reduce the download size by increasing the
efficiency of minimizers, I once used something like this (not just for
hasOwnProperty):

    // large library with many occurrences of hasOwnProperty etc:
    (function () {

        var _hasOwnProperty = "hasOwnProperty";

        ...

        if (obj[_hasOwnProperty](prop)) {
           ...

    })();

"_hasOwnProperty" can then be minified/obfuscated to something like "a",
which I thought was a good thing at the time. Honestly, the main effect
was to make the code less readable for the dubious benefit of saving a
few bytes. Not recommended.

I suspect that any highly golfed solution you may discover will suffer
from similar readability problems.

- stefan

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web