Syntax for object comprehension?

Discussion in 'Javascript' started by G, Jan 30, 2010.

  1. G

    G Guest

    Not an array comprehension.

    let a = [key for each( key in getKeys() )];

    An object comprehension...

    let o = {key: getValue( key ) for each( key in getKeys() )}; //
    invalid syntax
    let o = [{key: getValue( key )} for each( key in getKeys() )]; //
    valid, but an array of objects instead of an object

    Is it possible to do an 'object comprehension' In JavaScript?

    --
    G
     
    G, Jan 30, 2010
    #1
    1. Advertising

  2. G wrote:

    > Not an array comprehension.
    >
    > let a = [key for each( key in getKeys() )];
    >
    > An object comprehension...
    >
    > let o = {key: getValue( key ) for each( key in getKeys() )}; //
    > invalid syntax
    > let o = [{key: getValue( key )} for each( key in getKeys() )]; //
    > valid, but an array of objects instead of an object
    >
    > Is it possible to do an 'object comprehension' In JavaScript?


    -v please


    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$>
     
    Thomas 'PointedEars' Lahn, Jan 30, 2010
    #2
    1. Advertising

  3. G

    G Guest

    By "-v please", are you asking which version?

    Presumably

    application/javascript;version=1.7

    or

    application/javascript;version=1.8

    because 'object comprehensions' (if such a thing is possible) are
    unlikely to predate array comprehensions.

    --
    G
     
    G, Jan 30, 2010
    #3
  4. G <> writes:

    > By "-v please", are you asking which version?


    He probably meant --verbose, as in: Please give more information (or
    perhaps: please Write in entire sentences).

    Anyway, as far as I know, there is no Object comprehension in JavaScript
    1.7 or 1.8. You might want to look at Generator Expressions, for some
    kind of shorthand.

    /L
    P.S. But remember that it works it Mozilla browsers only.
    --
    Lasse Reichstein Holst Nielsen
    'Javascript frameworks is a disruptive technology'
     
    Lasse Reichstein Nielsen, Jan 30, 2010
    #4
  5. On Jan 30, 4:04 pm, G <> wrote:
    > Not an array comprehension.
    >
    >         let a = [key for each( key in getKeys() )];
    >
    > An object comprehension...
    >
    >         let o = {key: getValue( key ) for each( key in getKeys() )}; //
    > invalid syntax
    >         let o = [{key: getValue( key )} for each( key in getKeys() )]; //
    > valid, but an array of objects instead of an object
    >
    > Is it possible to do an 'object comprehension' In JavaScript?
    >


    Nope, that's not possible. By the syntax rules {key: ...} will be key
    'key' but not dynamic key on each iteration from the getKeys() object.

    But using array comprehension, it's possible to make it in actions
    (define first object, and then fill):

    var o = {};
    [o[key] = value for ([key, value] in Iterator({a: 1, b: 2}))];

    Which actually isn't so different from simple iteration via:

    var o = {};
    for ([key, value] in Iterator({a: 1, b: 2})) {
    o[key] = value;
    }

    Also simple iteration loop is acceptable.

    /ds
     
    Dmitry A. Soshnikov, Jan 30, 2010
    #5
  6. On Jan 30, 8:49 pm, "Dmitry A. Soshnikov" <>
    wrote:

    [...]

    > var o = {};
    > [o[key] = value for ([key, value] in Iterator({a: 1, b: 2}))];
    >
    > Which actually isn't so different from simple iteration via:
    >
    > var o = {};
    > for ([key, value] in Iterator({a: 1, b: 2})) {
    >   o[key] = value;
    >
    > }


    Addition: isn't so different except that in first case additional
    "intermediate" array from array comprehension will be created and
    deleted after that.

    If you put this construction into the round brackets that will be
    generator and not array comprehension. This generator, which generates
    iteration result lazily should be activated via .next method:

    (o[key] = value for ([key, value] in Iterator({a: 1, b: 2}))).next();

    /ds
     
    Dmitry A. Soshnikov, Jan 30, 2010
    #6
  7. G

    G Guest

    D'oh, bitten by {"variablenotallowedhere": "foo"} yet again!

    I was hoping to refactor an 'old style' for loop but, as you point
    out, simple iteration is OK too (and clearer than the alternative
    (s)). Using a generator (with additional tricks, to drive the .next
    ()) would also clutter the code in question (see below), so I'll stick
    with the 'old style' for loop for now (and avoid the intermediate, as
    you also pointed out). Thank you for the suggestions!


    function getStorageDataKeys() {
    let retval = [];
    for( let loop = 0; loop < localStorage.length; ++loop ) {
    retval.push( localStorage.key( loop ) );
    }
    return retval;
    }


    function getStorageData() {
    let retval = {};
    /*
    for each( let key in getStorageDataKeys() ) {
    retval[key] = localStorage.getItem( key );
    }
    */
    [retval[key] = localStorage.getItem( key ) for each( key in
    getStorageDataKeys() )];
    return retval;
    }

    // all that to enable
    for( let [key, val] in Iterator( getStorageData() ) ) {
    // ...

    --
    G
     
    G, Jan 30, 2010
    #7
  8. G

    G Guest

    Ah, wait, __iterator__() to the rescue. No key array needed! Of
    course getStorageData() doesn't really return {} items, but it behaves
    as if it did in for each loops. :)


    function getStorageData() {
    return { "__iterator__": function() {
    let loop = 0;
    while( loop < localStorage.length ) {
    let key = localStorage.key( loop );
    yield [key, localStorage.getItem( key )];
    ++loop;
    }
    throw StopIteration;
    }
    };
    }


    --
    G
     
    G, Jan 30, 2010
    #8
  9. G wrote:

    > By "-v please", are you asking which version?


    No, I meant to enable your --verbose mode ;-)

    IOW, what do you expect the input and output of "Object comprehension" to
    be?


    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$>
     
    Thomas 'PointedEars' Lahn, Jan 30, 2010
    #9
  10. G

    G Guest

    Sorry about that, my default is terse (influenced by Postel's
    conservative:send::liberal:receive, and Strunk/White, and BNF
    (anyway...)).

    I'd like to be able to define 'object comprehensions' like array
    comprehensions, in JavaScript, with key:values ({}) instead of values
    ([]).

    Maybe it's a Python itch?

    As pointed out; because literal keys are required, the object syntax
    might be tricky. While thinking about intermediates (like the key
    array as well as the entire {} being returned (basically a copy of
    localStorage)) and data sizes (localStorage might be 5M or more),
    using __iterator__() seemed like a viable approach (much more on
    demand, limiting data fluff) and is compatible with [key, value] <-
    Iterator( foo ) syntax (behaving like a {} value, on the 'client'
    side). In the __iterator__() code mentioned, I've moved the 'key'
    declaration outside the loop and wrapped the return value in an
    Iterator, which allows for code like for( let [key, val] in
    getLocalStorageKeyValues() ) {...} (the function name was also
    refactored)) on the 'client' side, and am happy now with the
    implementation (and 'client' API). If only localStorage permissions
    (in Firefox 3.6) weren't so quirky... ;)

    https://bugzilla.mozilla.org/show_bug.cgi?id=542730

    --
    G
     
    G, Jan 31, 2010
    #10
  11. On Jan 30, 11:21 pm, G <> wrote:
    > Ah, wait, __iterator__() to the rescue.  No key array needed!  Of
    > course getStorageData() doesn't really return {} items, but it behaves
    > as if it did in for each loops. :)
    >
    > function getStorageData() {
    >         return { "__iterator__": function() {
    >                         let loop = 0;
    >                         while( loop < localStorage.length ) {
    >                                 let key = localStorage.key( loop );
    >                                 yield [key, localStorage.getItem( key )];
    >                                 ++loop;
    >                         }
    >                         throw StopIteration;
    >                 }
    >         };
    >
    > }
    >


    Yeah, __iterator__ (generator-based in your case; also you can you
    special iterator object with .next method) - is a good decision in
    this case. Although, there's still array on exit and you need to
    define first object and then fill it with __iterator__ yielding
    result.

    /ds
     
    Dmitry A. Soshnikov, Jan 31, 2010
    #11
  12. On Jan 31, 9:05 am, G <> wrote:

    [...]

    >
    > Maybe it's a Python itch?
    >


    Yes, array comprehension was borrowed to JavaScript(trade mark) from
    Python, but in Python in difference from JS that's not possible to
    fill some object iteration dictionary via array comprehension:

    [(v, k) for v, k in {'a': 1, 'b': 2}.items()]

    Result: [('a', '1'), ('b', 2)]

    [a[v] = k for v, k in {'a': 1, 'b': 2}.items()] # syntax error

    for v, k in {'a': 1, 'b': 2}.items(): # OK
    a[k] = v

    Also, there's no "object comprehension" in Python.

    /ds
     
    Dmitry A. Soshnikov, Jan 31, 2010
    #12
  13. G

    G Guest

    True, there aren't 'object comprehensions' in Python, but they can be
    faked. :)

    import math
    sintable = dict( ([degree, math.sin( degree )] for degree in range( 0,
    360 )) )
    print sintable

    While it would be nice to have something similar in JavaScript; for
    loops and __iterator__() definitions seem to suffice (I'm not familiar
    with JavaScript internals, so I don't know if comprehensions could be
    optimized). Anyway, thanks for the discussion everyone, it was
    educational!

    Meanwhile, back at the creature feep (in case anyone is interested)...

    function getLocalStorageKeyValues( criteriafunction ) {
    return { "__iterator__": function() {
    let key = undefined;
    let loop = 0;
    while( loop < localStorage.length ) {
    key = localStorage.key( loop );
    if( key && (typeof criteriafunction != 'function' ||
    criteriafunction( key )) ) {
    yield [key, localStorage.getItem( key )];
    }
    ++loop;
    }
    throw StopIteration;
    }
    };
    }

    for( let [key, val] in getLocalStorageKeyValues() ) { //...

    for( let [key, val] in getLocalStorageKeyValues( function( key )
    key.indexOf( 'someprefix' ) === 0 ) ) { //...

    --
    G
     
    G, Jan 31, 2010
    #13
  14. G wrote:

    > Sorry about that,


    About *what*? Learn to post.

    <http://jibbering.com/faq/#posting>

    > [...]
    > I'd like to be able to define 'object comprehensions' like array
    > comprehensions, in JavaScript, with key:values ({}) instead of values
    > ([]).


    {
    key1: value1,
    key2: value2
    }

    > Maybe it's a Python itch?


    Maybe you don't know what you are talking about.

    > As pointed out


    You pointed out nothing. You posted some bogus code without saying what
    you expect from it. Hence my asking.

    > [TLDR]



    PointedEars
    --
    Use any version of Microsoft Frontpage to create your site.
    (This won't prevent people from viewing your source, but no one
    will want to steal it.)
    -- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
     
    Thomas 'PointedEars' Lahn, Jan 31, 2010
    #14
  15. On Jan 31, 4:48 pm, G <> wrote:
    > True, there aren't 'object comprehensions' in Python, but they can be
    > faked. :)
    >
    > import math
    > sintable = dict( ([degree, math.sin( degree )] for degree in range( 0,
    > 360 )) )
    > print sintable
    >


    Hey, completely true, as I practice Python not so often (more
    theoretically) forgot that `dict' callable class can accept array with
    arrays (or tuples) for dictionary items. So result which you have from
    array comprehension can be easily converted to dict-object:

    dict([('a', 1), ('b', 2)]) # {'a': 1, 'b': 2}

    You can create absolutely the same object-builder from passed array of
    arrays as argument in JavaScript function and reuse it then.


    >
    > Meanwhile, back at the creature feep (in case anyone is interested)...
    >
    > function getLocalStorageKeyValues( criteriafunction ) {
    >         return { "__iterator__": function() {
    >                         let key = undefined;
    >                         let loop = 0;
    >                         while( loop < localStorage.length ) {
    >                                 key = localStorage.key( loop );
    >                                 if( key && (typeof criteriafunction != 'function' ||
    > criteriafunction( key )) ) {
    >                                         yield [key, localStorage.getItem( key )];
    >                                 }
    >                                 ++loop;
    >                         }
    >                         throw StopIteration;
    >                 }
    >         };
    >
    > }
    >
    > for( let [key, val] in getLocalStorageKeyValues() ) { //...
    >
    > for( let [key, val] in getLocalStorageKeyValues( function( key )
    > key.indexOf( 'someprefix' ) === 0 ) ) { //...
    >


    Yep, that's interesting implementation, although, all the iterator
    object can be cached (as an optimization for do not create object each
    time) in `getLocalStorageKeyValues' as a static property and reused
    then:

    function getLocalStorageKeyValues(criteriafunction) {

    // set each time new criteriafunction
    getLocalStorageKeyValues.criteriafunction = criteriafunction;

    // but return always the same object
    return getLocalStorageKeyValues.iteratorObject;
    }

    getLocalStorageKeyValues.iteratorObject = {__iterator__: ...};

    and inside the getLocalStorageKeyValues.iteratorObject use:

    if( key && (typeof getLocalStorageKeyValues.criteriafunction !=
    'function' ||
    getLocalStorageKeyValues.criteriafunction( key )) ) {

    There can be difference in `this' value inside the call of
    criteriafunction, but that doesn't heart your case.

    /ds
     
    Dmitry A. Soshnikov, Jan 31, 2010
    #15
  16. On Jan 31, 5:21 pm, "Dmitry A. Soshnikov" <>
    wrote:

    [...]

    > dict([('a', 1), ('b', 2)]) # {'a': 1, 'b': 2}
    >
    > You can create absolutely the same object-builder from passed array of
    > arrays as argument in JavaScript function and reuse it then.
    >


    Small addition: although it's possible to do it in this way (and also
    in JS), there will be additional full iteration inside the `dict'
    function (callable class), first to get array from array
    comprehension, the second one - to create the dictionary from the
    array parameter:

    d = dict([(v, k) for v, k in {'a': 1, 'b': 2}.items()])

    Meanwhile in JS will be only one iteration for that:

    [o[key] = value for ([key, value] in Iterator({a: 1, b: 2}))];

    /ds
     
    Dmitry A. Soshnikov, Jan 31, 2010
    #16
  17. G

    G Guest

    It's comforting to know that USENET hasn't changed much after all
    these years. :)

    --
    G
     
    G, Jan 31, 2010
    #17
  18. G

    G Guest

    Would caching allow multiple interleaved uses, without conflicts? I
    was assuming the present implementation of getLocalStorageKeyValues()
    would allow for multiple interleaved clients, with different filtering
    criteria. For example, I was hoping to use Worker instances and
    localStorage together (assuming Worker instances can access
    localStorage, I haven't experimented with Worker yet). Hmmm, maybe
    Worker scope is isolated, including any potential
    getLocalStorageKeyValues() states...

    In that other language; I should have used the example from the Python
    docs (thought it wasn't as obvious what was going on, perhaps it is
    actually clearer).

    dict( (x, sin( x * pi / 180 )) for x in range( 0, 91 ) )

    That's a generator expression being passed to dict(), a tuple at a
    time. I assume that minimizes the intermediates involved.

    I do like the o = {}; [o[k] = v ...] trick (for JavaScript). Without
    running some benchmarks, I don't know which would be most performant
    (I'd guess for loops, due to the lack of function calls).

    --
    G
     
    G, Jan 31, 2010
    #18
  19. On Jan 31, 7:00 pm, G <> wrote:
    > Would caching allow multiple interleaved uses, without conflicts?  I
    > was assuming the present implementation of getLocalStorageKeyValues()
    > would allow for multiple interleaved clients, with different filtering
    > criteria.  For example, I was hoping to use Worker instances and
    > localStorage together (assuming Worker instances can access
    > localStorage, I haven't experimented with Worker yet).  Hmmm, maybe
    > Worker scope is isolated, including any potential
    > getLocalStorageKeyValues() states...
    >


    Sure if some different objects should use it with own criteria (and
    especially with Workers) it's not acceptable. But in this case would
    be better to put iterator function into the prototype (which means,
    all instances will have their own state, but will share one
    __iterator__ function):

    function getLocalStorageKeyValues(criteriaFn) {
    ...
    this.criteriaFn = criteriaFn;
    ...
    }

    getLocalStorageKeyValues.prototype.__iterator__ = function () {
    if (this.criteriaFn(...)) {
    ...
    }
    };

    var first = new getLocalStorageKeyValues(function () {...});
    var second = new getLocalStorageKeyValues(function () {...});

    But, that's just a suggestion, do in most comfortable way.

    /ds
     
    Dmitry A. Soshnikov, Jan 31, 2010
    #19
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Moosebumps

    List Comprehension Syntax

    Moosebumps, Jul 10, 2004, in forum: Python
    Replies:
    35
    Views:
    861
    David Eppstein
    Jul 22, 2004
  2. Replies:
    2
    Views:
    362
    Tim Peters
    Jul 12, 2004
  3. Gregory Guthrie

    list comprehension syntax..?

    Gregory Guthrie, Aug 1, 2006, in forum: Python
    Replies:
    4
    Views:
    334
    Claudio Grondi
    Aug 1, 2006
  4. Chris Mellon
    Replies:
    2
    Views:
    392
    Dustan
    Jan 18, 2008
  5. Vedran Furac(
    Replies:
    4
    Views:
    331
    Marc 'BlackJack' Rintsch
    Dec 19, 2008
Loading...

Share This Page