473,326 Members | 2,168 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

Can I simulate list comprehensions?

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
Jul 22 '05 #1
9 1960
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
Jul 22 '05 #2
// 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


Jul 22 '05 #3
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
Jul 22 '05 #4
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
Jul 22 '05 #5
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
Jul 22 '05 #6
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
Jul 22 '05 #7
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
Jul 22 '05 #8
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
Jul 22 '05 #9
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
Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Elaine Jackson | last post by:
List comprehensions don't work the way you intuitively expect them to work. I realize many people have no intuitions about how list comprehensions 'should' work, so if you recognize yourself in...
24
by: Mahesh Padmanabhan | last post by:
Hi, When list comprehension was added to the language, I had a lot of trouble understanding it but now that I am familiar with it, I am not sure how I programmed in Python without it. Now I...
9
by: Neuruss | last post by:
I have a doubt regarding list comprehensions: According to Mark Lutz in his book Learning Pyhon: "...there is currently a substantial performance advantage to the extra complexity in this case:...
42
by: Alan McIntyre | last post by:
Hi all, I have a list of items that has contiguous repetitions of values, but the number and location of the repetitions is not important, so I just need to strip them out. For example, if my...
23
by: Mike Meyer | last post by:
Ok, we've added list comprehensions to the language, and seen that they were good. We've added generator expressions to the language, and seen that they were good as well. I'm left a bit...
30
by: Steven Bethard | last post by:
George Sakkis wrote: > "Steven Bethard" <steven.bethard@gmail.com> wrote: >> Dict comprehensions were recently rejected: >> http://www.python.org/peps/pep-0274.html >> The reason, of course,...
7
by: Steven Bethard | last post by:
Tom Anderson <twic@urchin.earth.li> wrote: > Sounds good. More generally, i'd be more than happy to get rid of list > comprehensions, letting people use list(genexp) instead. That would >...
6
by: Heiko Wundram | last post by:
Hi all! The following PEP tries to make the case for a slight unification of for statement and list comprehension syntax. Comments appreciated, including on the sample implementation. ===...
6
by: Lonnie Princehouse | last post by:
List comprehensions appear to store their temporary result in a variable named "_" (or presumably "_", "_" etc for nested comprehensions) In other words, there are variables being put into the...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.