POV-Ray : Newsgroups : povray.off-topic : Standard libraries Server Time
6 Sep 2024 13:18:06 EDT (-0400)
  Standard libraries (Message 69 to 78 of 108)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Warp
Subject: Re: Standard libraries
Date: 7 Mar 2009 17:46:46
Message: <49b2f956@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> But C++ syntax is so bad you 
> can't even tell whether a line of code is a type declaration or a variable 
> declaration or a function invocation without reading all the include files. 

  That's also one of the great assets of the language. Consider this:

template<typename F>
void foo()
{
    F(5);
}

  Is that F(5) a function call or is it instantiating a variable of type F?
It's impossible to tell without knowing what F might be.

  However, it doesn't matter! As long as F behaves like a function, that's
just fine. This is used quite a lot in template coding, eg. with functors
and comparators. This gives flexibility and versatility.

  It's not like C++ was the only language which behaves like this.

> To the point where you start getting things like the "typename" keyword 
> (iirc) just to tell the compiler whether you meant to give a type or a 
> variable name at that point.

  Most languages have special keywords to denote what you want to do.
For example, some languages might have a keyword like "function" to denote
that you are starting a function definition, as opposed to starting a
function call. I don't really see the big difference.

> You can't tell me a language with undecidable syntax isn't at least a little 
> sucky, yes?

  When that syntax brings flexibility, I don't consider is such a huge
problem.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: Standard libraries
Date: 7 Mar 2009 17:51:22
Message: <49b2fa6a@news.povray.org>
Nicolas Alvarez <nic### [at] gmailcom> wrote:
> int& foo() {
>    int myNumber = 42;
>    return myNumber;
> }

> Undefined behavior when the caller tries to do something with the reference.

  I think there's a reason why you can't have references to primitive
types in Java.
  (Sometimes this can be a bit limiting, eg. because you can't pass
primitive types by reference to functions, for them to modify the
original values rather than copies.)

-- 
                                                          - Warp


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: Standard libraries
Date: 7 Mar 2009 17:52:37
Message: <49b2fab5@news.povray.org>
Darren New wrote:
> Warp wrote:
>>   Another example: You could give std::sort() a comparator as a lambda
>> function which has access to the variables in the local scope, something
>> which is very laborious to do currently.
> 
> Hmmm. OK, thanks. I can see where something like that could be convenient.
> Most places I've seen that need that sort of thing pass in a "client data"
> sort of opaque pointer to allow it, so I guess this new stuff could
> obviate the need to design that in at the application layer.

In C, the standard qsort() function takes a function pointer and (I think)
a "client data" void pointer. You have to put your state in a struct, send
the pointer as client data, then in your comparator function get the data
through the pointer.

In C++, the standard std::sort template function takes a comparator functor.
Using functors (which can be an instance of a stateful class, or can be a
plain old function) instead of passing a "client data" pointer is quite
common in C++.

Here is a [useless in practice] example where the comparator takes an
initialization parameter (whether to sort descending or ascending), and
also keeps state that can be retrieved later (how many times the comparison
function was called).

struct MyComparator {
    bool reverse_mode;
    int comparison_count;

    MyComparator(bool reverse) {
        reverse_mode = reverse;
        comparison_count = 0;
    }

    bool operator()(int a, int b) {
        comparison_count++;
        if (reverse_mode) {
            return b < a;
        } else {
            return a < b;
        }
    }
};

std::vector<int> list;

MyComparator c(false);
std::sort(list.begin(), list.end(), c);

cout << "Comparator called " << c.comparison_count << " times\n";

If you don't need to retrieve any data after the comparison, you could also
do this:

std::sort(list.begin(), list.end(), MyComparator(false));


With lambdas, you can use "closures" to keep state, so you don't need a
separate class/struct declared elsewhere:

std::vector<int> list;
int comparison_count=0;

std::sort(list.begin(), list.end(), [&comparison_count](int a, int b) {
    comparison_count++;
    return a < b;
});

Even if you don't want to keep any state (and leave the [] empty to use no
closures), it's still useful to declare the comparison code right next to
the std::sort call, instead of in a function/class possibly far away in
the .cpp file. This is the part I said was similar to string literals (you
know how in assembler you need a manually-made list of strings at the
beginning of the program? :P).


Post a reply to this message

From: Warp
Subject: Re: Standard libraries
Date: 7 Mar 2009 17:55:44
Message: <49b2fb70@news.povray.org>
Nicolas Alvarez <nic### [at] gmailcom> wrote:
> for (std::vector<int>::const_iterator i = someList.begin(); i !=
> someList.end(); ++i) {
>     total += *i;
> }

  Maybe not the best of examples because with the next C++ standard you
will also be able to do it like:

    for(auto i = someList.begin(); i != someList.end(); ++i)
        total += *i;

which is not enormously longer than the lambda version.

-- 
                                                          - Warp


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: Standard libraries
Date: 7 Mar 2009 17:58:49
Message: <49b2fc29@news.povray.org>
Warp wrote:
> Nicolas Alvarez <nic### [at] gmailcom> wrote:
>> for (std::vector<int>::const_iterator i = someList.begin(); i !=
>> someList.end(); ++i) {
>>     total += *i;
>> }
> 
>   Maybe not the best of examples because with the next C++ standard you
> will also be able to do it like:
> 
>     for(auto i = someList.begin(); i != someList.end(); ++i)
>         total += *i;
> 
> which is not enormously longer than the lambda version.

Yes, when changing C++ code to C++0x, I'll have to decide which of the two
types of awesome to use.


Post a reply to this message

From: Darren New
Subject: Re: Standard libraries
Date: 7 Mar 2009 20:19:43
Message: <49b31d2f$1@news.povray.org>
Warp wrote:
>   However, it doesn't matter! As long as F behaves like a function, that's
> just fine. This is used quite a lot in template coding, eg. with functors
> and comparators. This gives flexibility and versatility.

Hmm. I never thought of it that way. OK.

>   It's not like C++ was the only language which behaves like this.

Well.... I think it's one of the few languages where you can't tell whether 
something's invoking a function or adding a name to the namespace at compile 
time.  It would seem to make writing parsers and such harder than it needs 
to be.

I'll grant that there are a number of languages where (say) writing "F(5)" 
doesn't tell you whether F is a function, a pointer to a function, or a 
function that returns another function, say.

>   Most languages have special keywords to denote what you want to do.
> For example, some languages might have a keyword like "function" to denote
> that you are starting a function definition, as opposed to starting a
> function call. I don't really see the big difference.

It makes the grammar easier to automate.

>> You can't tell me a language with undecidable syntax isn't at least a little 
>> sucky, yes?
> 
>   When that syntax brings flexibility, I don't consider is such a huge
> problem.

Other languages seem to manage being as flexible without having such complex 
grammars. I'll grant that they trade off runtime efficiency to achieve that.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: Darren New
Subject: Re: Standard libraries
Date: 7 Mar 2009 20:31:38
Message: <49b31ffa$1@news.povray.org>
Nicolas Alvarez wrote:
> This is the part I said was similar to string literals (you
> know how in assembler you need a manually-made list of strings at the
> beginning of the program? :P).

Oh! OK.  I had no idea that's what you were talking about, and I thought you 
were comparing lambda expressions to string literals somehow.

Thanks for the excellent examples.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: Warp
Subject: Re: Standard libraries
Date: 7 Mar 2009 20:34:13
Message: <49b32095@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Well.... I think it's one of the few languages where you can't tell whether 
> something's invoking a function or adding a name to the namespace at compile 
> time.  It would seem to make writing parsers and such harder than it needs 
> to be.

  Who cares if writing a parser is harder? Programs are supposed to help
people, not the other way around. I prefer latex over xml any day, even
though creating a latex parser is way more complicated than creating an
xml parser.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: Standard libraries
Date: 7 Mar 2009 23:29:42
Message: <49b349b6$1@news.povray.org>
Warp wrote:
>   Who cares if writing a parser is harder? 

Well, anyone implementing compilers or interpreters for one. If the compiler 
gave you runtime type information sufficient for everyone's needs, that 
would probably be enough. But if you want to (say) write something that'll 
take a structure and store it in database tables, or serialize something to 
a file or a SOAP message or some such, not having the type information *and* 
not being able to easily parse the header files can be problematic.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: Darren New
Subject: Re: Standard libraries
Date: 8 Mar 2009 00:09:20
Message: <49b35300$1@news.povray.org>
Warp wrote:
>   You still know that I get trolled when someone writes such mocking words
> about C++ as you have done.

You know, I took a couple hours away, then went back and looked at what I'd 
typed. I think if you look at my initial posts here objectively, you'll see 
they weren't mocking, as almost all of it was asking questions about the 
implementation.

What I failed to do was describe the mental process that caused me to ask 
the kinds of apparently-silly questions I was asking. I thought

(( Wow, C++ is getting lambdas. I guess they're standardizing Boost, which 
is ugly. )) "I bet it'll be ugly."

(( No, it actually *looks* not too bad. But I wonder how they implement it, 
then. That's a mess behind the scenes in C#, and in pretty much every 
language I know that keeps variables on the machine stack, so I wonder how 
they're doing closures. I wonder how the closed-over variables survive the 
destruction of the stack frame. ))

"Can you return lambda values from a function?"  (( Because if not, then you 
don't have to worry about the stack frame not being there. Oh, but I'm told 
you can. Cool. Maybe it's going to copy the values from the stack into a 
heap-allocated object. But how would it GC the heap-allocated object, if 
multiple lambdas point to it? Maybe it's doing reference counting. But that 
doesn't work, if you get circular references, which you can't get if you 
can't assign to a variable except a new variable. ))

"Can you assign it to a variable?"  (( Oh, you can do that too. Wow, that's 
really impressive. I can't imagine what they're doing to make closures work.))

"Thanks for the link to wikipedia."  (( Oh, wikipedia says you just randomly 
get hosed if you try to actually use values you thought you closed over when 
you created the lambda, unlike every other language that ever implemented 
the feature called 'lambda expressions'. ))

"Gee, C++ lambdas sure suck compared to everyone else's that actually 
manages to create a closure from lambdas."  (( I wonder what it could be 
useful for, since I can't think of a reason I'd use a lambda that I couldn't 
return from the function in which I created it. ))

"Why not just use a for loop?"  (( Oh, I see. I wasn't thinking like that, 
because I was still thinking in terms of lambdas rather than in terms of 
downward funargs. ))

I can see how if I didn't make clear why I was asking the questions, you 
might leap to the conclusion (perhaps justifiably) that I was simply looking 
for the flaws in order to criticize C++.  In reality, I was looking for the 
flaw in my mental model of how C++ handles memory that would allow the 
memory for the closure to be collected only after the lambda has been 
collected. Or, given that I'm pretty sure I understand how C++ works its 
memory model, I was looking for the cool impressive clever mechanism that 
would let the closure get allocated in a way that would work.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.