Can I simulate list comprehensions?

Discussion in 'C++' started by seguso, Dec 20, 2004.

  1. seguso

    seguso Guest

    Hello,

    For the sake of efficiency, I have chosen C++ as the language for a
    "Free Adventure Construction Kit" I am developing (http://fack.sf.net).

    I am looking for a way to simulate list comprehensions a-la
    Haskell/Python, in order to make the logic of my code more readable.
    Any way to do that would be welcome, even if this means to use macros.

    Here is the code I would like to make more readable (the line marked
    with ***):

    list<pt<layer_lit> >
    perform_lighting ( const list<pt<layer_unlit_0> > unlit_layers,
    const set<string> & on_lights,
    const map<set<string>, rational_number >& precomputed_factors)
    {
    // BEGIN grouping declarations here to keep the logic readable
    list<pt<layer_unlit_0> >::const_iterator iter;
    pt<layer_unlit_0> u;
    list<light>::const_iterator iter2;
    light l;
    list<pt<layer_surf> > li;
    list<pt<layer_unlit_1> > unlit1;
    list<pt<layer_unlit_1> >::const_iterator iter3;
    pt<layer_unlit_1> u2;
    map<set<string>, rational_number>::const_iterator norm_factor;
    pt<layer_surf> sum;
    list<pt<layer_lit> > ret;
    // END

    foreach3(u, unlit_layers, iter){

    // BEGIN *** li = [ l.surf for l in u->on_and_off_lights
    // if contains(on_lights, l.name) ]
    li.clear();
    foreach3(l, u->on_and_off_lights, iter2){
    if (contains(on_lights, l.name) ){
    li.push_back(l.surf); }}
    // END

    u2 = pt<layer_unlit_1>(new layer_unlit_1(li, u->y_walkbehind));
    unlit1.push_back(u2);}

    norm_factor = precomputed_factors.find(on_lights);

    //assert(norm_factor != on_lights.end()); // @@ why doesn't this
    compile?

    foreach3(u2, unlit1, iter3){
    sum = sum_each_pixel( u2->on_lights);
    normalize_layer(*sum, norm_factor->second);
    ret.push_back( pt<layer_lit>(new layer_lit(sum,
    u2->y_walkbehind) )); }
    return ret;
    }

    For reference, here are the auxiliary functions and macros I am using:

    #define foreach3(i, l,iter) for((iter) = (l).begin(), i = *iter; \\
    (iter) != (l).end(); (iter)++, i = *iter)

    #define pt shared_ptr // boost::shared_ptr

    /// test whether a set of X contains a given X.
    template<class Set>
    bool
    contains(Set s,
    typename Set::key_type i)
    {
    // BEGIN decl
    typename Set::const_iterator x;
    // END

    x = s.find(i);
    return x != s.end();
    }


    Thanks for any hint,

    ---
    Maurizio Colucci
    http://onefinger.sf.net
     
    seguso, Dec 20, 2004
    #1
    1. Advertising

  2. seguso wrote:
    > Hello,
    >
    > For the sake of efficiency, I have chosen C++ as the language for a
    > "Free Adventure Construction Kit" I am developing (http://fack.sf.net).
    >
    > I am looking for a way to simulate list comprehensions a-la
    > Haskell/Python, in order to make the logic of my code more readable.
    > Any way to do that would be welcome, even if this means to use macros.
    >
    > Here is the code I would like to make more readable (the line marked
    > with ***):
    >
    > list<pt<layer_lit> >
    > perform_lighting ( const list<pt<layer_unlit_0> > unlit_layers,
    > const set<string> & on_lights,
    > const map<set<string>, rational_number >& precomputed_factors)
    > {


    Do you know about typedefs?

    > // BEGIN grouping declarations here to keep the logic readable
    > list<pt<layer_unlit_0> >::const_iterator iter;
    > pt<layer_unlit_0> u;
    > list<light>::const_iterator iter2;
    > light l;
    > list<pt<layer_surf> > li;
    > list<pt<layer_unlit_1> > unlit1;
    > list<pt<layer_unlit_1> >::const_iterator iter3;
    > pt<layer_unlit_1> u2;
    > map<set<string>, rational_number>::const_iterator norm_factor;
    > pt<layer_surf> sum;
    > list<pt<layer_lit> > ret;
    > // END


    <snip>

    Humm.. you think that's readable? To understand the logic, we need to
    understand the types of the objects involved and that doesn't help. The
    rest of the code is unreadble.

    Learn to use typedefs and don't use macros. Programmers are used to
    certain constructs, such as for_each and and for loops with iterators.
    Hiding them in macros only make the code less readable since we are
    stuck with things we don't know about. Showing the definitions does not
    help.

    Start by rewriting the code using standard constructions, eliminate
    macros, use typedefs and fragment your code into smaller functions.
    Using typedefs will allow you to merge the variables definitions with
    the code, making their usage more clear.


    Jonathan
     
    Jonathan Mcdougall, Dec 20, 2004
    #2
    1. Advertising

  3. seguso

    Howard Guest


    >
    >> // BEGIN grouping declarations here to keep the logic readable
    >> list<pt<layer_unlit_0> >::const_iterator iter;
    >> pt<layer_unlit_0> u;
    >> list<light>::const_iterator iter2;
    >> light l;
    >> list<pt<layer_surf> > li;
    >> list<pt<layer_unlit_1> > unlit1;
    >> list<pt<layer_unlit_1> >::const_iterator iter3;
    >> pt<layer_unlit_1> u2;
    >> map<set<string>, rational_number>::const_iterator norm_factor;
    >> pt<layer_surf> sum;
    >> list<pt<layer_lit> > ret;
    >> // END

    >


    One other minor suggestion: better variable names might also help. The
    lower-case l (L) is about the worst name for a variable I know. In the font
    I use, it's indistinguishable from the upper-case I (i) and also closely
    resembles the number one (1). And it has no inherent meaning. Longer names
    take a little longer to type, but it's much easier to understand
    'lightSource" or "theLight" than simply "l" when looking at code, don't you
    think?

    -Howard
     
    Howard, Dec 20, 2004
    #3
  4. seguso

    seguso Guest

    Jonathan Mcdougall wrote:
    > seguso wrote:
    >
    >> Hello,
    >>
    >> For the sake of efficiency, I have chosen C++ as the language for a
    >> "Free Adventure Construction Kit" I am developing (http://fack.sf.net).
    >>
    >> I am looking for a way to simulate list comprehensions a-la
    >> Haskell/Python, in order to make the logic of my code more readable.
    >> Any way to do that would be welcome, even if this means to use macros.
    >>
    >> Here is the code I would like to make more readable (the line marked
    >> with ***):
    >>
    >> list<pt<layer_lit> >
    >> perform_lighting ( const list<pt<layer_unlit_0> > unlit_layers,
    >> const set<string> & on_lights,
    >> const map<set<string>, rational_number >& precomputed_factors)
    >> {

    >
    >
    > Do you know about typedefs?
    >
    >> // BEGIN grouping declarations here to keep the logic readable
    >> list<pt<layer_unlit_0> >::const_iterator iter;
    >> pt<layer_unlit_0> u;
    >> list<light>::const_iterator iter2;
    >> light l;
    >> list<pt<layer_surf> > li;
    >> list<pt<layer_unlit_1> > unlit1;
    >> list<pt<layer_unlit_1> >::const_iterator iter3;
    >> pt<layer_unlit_1> u2;
    >> map<set<string>, rational_number>::const_iterator norm_factor;
    >> pt<layer_surf> sum;
    >> list<pt<layer_lit> > ret;
    >> // END

    >
    >
    > <snip>
    >
    > Humm.. you think that's readable?


    No, and it's not meant to be read :)
    I have grouped declarations on top to allow the reader to skip them (see
    below).

    > To understand the logic, we need to
    > understand the types of the objects involved and that doesn't help.


    I don't want to argue with you, however IMHO type declarations make the
    code heavier to read, while giving little (or no) insight regarding the
    meaning of the code --- because the meaning of a variable is the way it
    is used, not its type.

    For example, knowing that the variable "t" has type "TImeStamp" does not
    tell me much about the meaning of t ("The last 10 times the user pressed
    a button").


    > The
    > rest of the code is unreadble.


    I guess this is only because you don't understand the macros.

    > Learn to use typedefs and don't use macros.


    Thanks for the suggestions, but I don't see the point, since IMHO types
    must not be read.

    Mau
     
    seguso, Dec 20, 2004
    #4
  5. seguso wrote:
    > Jonathan Mcdougall wrote:


    >>To understand the logic, we need to
    >>understand the types of the objects involved and that doesn't help.

    >
    >
    > I don't want to argue with you, however IMHO type declarations make the
    > code heavier to read, while giving little (or no) insight regarding the
    > meaning of the code --- because the meaning of a variable is the way it
    > is used, not its type.
    >
    > For example, knowing that the variable "t" has type "TImeStamp" does not
    > tell me much about the meaning of t ("The last 10 times the user pressed
    > a button").


    That reminds me of Sutter's example :

    int x;
    int y;
    y = x * 3; // might be okay -- who knows?


    typedef int Inches;
    typedef int Dollars;

    Inches x;
    Inches y;
    y = x * 3; // hmmm... ?

    >>Learn to use typedefs and don't use macros.

    >
    > Thanks for the suggestions, but I don't see the point, since IMHO types
    > must not be read.


    As you wish.


    Jonathan
     
    Jonathan Mcdougall, Dec 20, 2004
    #5
  6. seguso

    seguso Guest

    Jonathan Mcdougall wrote:
    > seguso wrote:
    >
    >> Jonathan Mcdougall wrote:

    >
    >
    >>> To understand the logic, we need to understand the types of the
    >>> objects involved and that doesn't help.

    >>
    >>
    >>
    >> I don't want to argue with you, however IMHO type declarations make
    >> the code heavier to read, while giving little (or no) insight
    >> regarding the meaning of the code --- because the meaning of a
    >> variable is the way it is used, not its type.
    >>
    >> For example, knowing that the variable "t" has type "TImeStamp" does
    >> not tell me much about the meaning of t ("The last 10 times the user
    >> pressed a button").

    >
    >
    > That reminds me of Sutter's example :
    >
    > int x;
    > int y;
    > y = x * 3; // might be okay -- who knows?
    >
    >
    > typedef int Inches;
    > typedef int Dollars;
    >
    > Inches x;
    > Inches y;
    > y = x * 3; // hmmm... ?



    The same effect could be achieved without types, by using variable names
    more meaningful than x and y.

    BTW, do you know python or ocaml? In those languages it is custom habit
    to not write types, and few people claim C++ to be more readable than
    those languages.

    Cheers,
    Mau
     
    seguso, Dec 20, 2004
    #6
  7. seguso

    Jeff Flinn Guest

    seguso wrote:
    > Jonathan Mcdougall wrote:
    >> seguso wrote:
    >>
    >>> Hello,
    >>>
    >>> For the sake of efficiency, I have chosen C++ as the language for a
    >>> "Free Adventure Construction Kit" I am developing
    >>> (http://fack.sf.net).
    >>>


    ....

    >> Humm.. you think that's readable?

    >
    > No, and it's not meant to be read :)
    > I have grouped declarations on top to allow the reader to skip them
    > (see below).
    >
    >> To understand the logic, we need to
    >> understand the types of the objects involved and that doesn't help.

    >
    > I don't want to argue with you, however IMHO type declarations make
    > the code heavier to read, while giving little (or no) insight
    > regarding the meaning of the code --- because the meaning of a
    > variable is the way it is used, not its type.


    I hate to burst your bubble also, but in (well designed)C++ type is
    everything.

    Jeff Flinn
     
    Jeff Flinn, Dec 20, 2004
    #7
  8. seguso wrote:
    > Jonathan Mcdougall wrote:
    >
    >>seguso wrote:
    >>
    >>
    >>>Jonathan Mcdougall wrote:

    >>
    >>
    >>>>To understand the logic, we need to understand the types of the
    >>>>objects involved and that doesn't help.
    >>>
    >>>
    >>>
    >>>I don't want to argue with you, however IMHO type declarations make
    >>>the code heavier to read, while giving little (or no) insight
    >>>regarding the meaning of the code --- because the meaning of a
    >>>variable is the way it is used, not its type.
    >>>
    >>>For example, knowing that the variable "t" has type "TImeStamp" does
    >>>not tell me much about the meaning of t ("The last 10 times the user
    >>>pressed a button").

    >>
    >>
    >>That reminds me of Sutter's example :
    >>
    >>int x;
    >>int y;
    >>y = x * 3; // might be okay -- who knows?
    >>
    >>
    >>typedef int Inches;
    >>typedef int Dollars;
    >>
    >>Inches x;
    >>Inches y;
    >>y = x * 3; // hmmm... ?

    >
    >
    >
    > The same effect could be achieved without types, by using variable names
    > more meaningful than x and y.


    I agree that a good combination of type and names makes a program readable.

    > BTW, do you know python or ocaml?


    I don't.

    > In those languages it is custom habit
    > to not write types, and few people claim C++ to be more readable than
    > those languages.


    Few people claim C++ is more readable than BASIC also. Why do you think
    templates are more complicated to read than non-templated code? Because
    suddenly you find yourself with un-typed objects.

    Typeless languages (such as most scripting languages) lack the
    type-safety of e.g. C++ and make, imho, programs less readable. A type
    describes what an object can do much more than its name does. Names can
    be ill-chosen but types cannot. Heck, names can even be avoided
    sometimes, leaving you only with a type.

    Specifically, classes describe an interface and a behavior. A name such
    as "students" obviously represents a list os some kind, but its type
    will show you 1) what operations are allows on that list and 2) how does
    that list behaves. For example,

    std::vector<Student> students;

    and

    std::list<Student> students;

    may share some functions, but will behave differently and will be used
    in different contexts.

    There is much more to a variable than its name!


    Jonathan
     
    Jonathan Mcdougall, Dec 20, 2004
    #8
  9. seguso

    Micha Guest

    seguso wrote:

    >
    > BTW, do you know python or ocaml? In those languages it is custom habit
    > to not write types, and few people claim C++ to be more readable than
    > those languages.


    I know ocaml, it's far more readable than c++ (and yes, maybe because of
    missing type declarations everywhere), type-safer, has an impressive type
    system + OO, generates comparable fast code.
    So, just use ocaml for your project :) If you got into the language, the
    time to develop something (for me) is half the time of writing the thing in
    C++, with code size less then 50% of c++ - code.

    The mix of imperative, functional and oo features with static type checking
    (never a segfault:) ,the fast native code and it's readability is
    unbeatable (just my opinion)

    Michael
     
    Micha, Dec 22, 2004
    #9
  10. seguso

    seguso Guest

    Micha wrote:
    > seguso wrote:
    >
    >
    >>BTW, do you know python or ocaml? In those languages it is custom habit
    >>to not write types, and few people claim C++ to be more readable than
    >>those languages.

    >
    >
    > I know ocaml, it's far more readable than c++ (and yes, maybe because of
    > missing type declarations everywhere), type-safer, has an impressive type
    > system + OO, generates comparable fast code.
    > So, just use ocaml for your project :) If you got into the language, the
    > time to develop something (for me) is half the time of writing the thing in
    > C++, with code size less then 50% of c++ - code.
    >
    > The mix of imperative, functional and oo features with static type checking
    > (never a segfault:) ,the fast native code and it's readability is
    > unbeatable (just my opinion)
    >
    > Michael
    >
    >


    That's the first thing I tried. Unfortunately a custom blitting function
    turned out to be 10 times slower in ocaml than in C++. Thisis due the
    absence of the byte data type in ocaml, I guess. And interoperation
    between C++ and ocaml seems prohibitively difficult to me.

    Cheers

    Mau
     
    seguso, Dec 22, 2004
    #10
    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. Dave Kuhlman

    Re: Style in list comprehensions

    Dave Kuhlman, Aug 15, 2003, in forum: Python
    Replies:
    1
    Views:
    329
    Alex Martelli
    Aug 16, 2003
  2. Frank Millman

    Simple db using list comprehensions

    Frank Millman, Apr 5, 2004, in forum: Python
    Replies:
    1
    Views:
    287
    Paddy McCarthy
    Apr 16, 2004
  3. Elaine Jackson

    list comprehensions

    Elaine Jackson, Apr 7, 2004, in forum: Python
    Replies:
    10
    Views:
    611
  4. David Isaac

    can list comprehensions replace map?

    David Isaac, Jul 27, 2005, in forum: Python
    Replies:
    22
    Views:
    631
    Andrew Dalke
    Jul 29, 2005
  5. Steven Bethard
    Replies:
    7
    Views:
    398
    Rocco Moretti
    Jan 20, 2006
Loading...

Share This Page