POV-Ray : Newsgroups : povray.off-topic : My first C++ program Server Time
9 Nov 2026 03:15:06 EST (-0500)
  My first C++ program (Message 100 to 149 of 149)  
<<< Previous 50 Messages Goto Initial 50 Messages
From: Darren New
Subject: Re: A test
Date: 21 Sep 2008 10:20:41
Message: <48d65839$1@news.povray.org>
Warp wrote:
>     foo(a, bar(b, c), d, e)
> 
>   If you wrote that as a Haskell-style no-delimiters function call,
> I suppose it would look like:
> 
>     foo a bar b c d e

>   Exactly how does Haskell decide how many parameters 'bar' takes there
> (and consequently how many of the rest of the parameters are for 'foo')?

It's curried. Each function only takes one.

In your example, I'm pretty certain you *have* to have parens.

foo a (bar b c) d e

>   I can't even begin to imagine how you would write that using the
> "point syntax", seen in many examples posted by Andrew. Perhaps you
> use parentheses to enclose the 'bar' call?

Hmmmm. I don't know you can do it with "point syntax" either. I think 
the a . b . c syntax only works when the result of "c" is the one and 
only argument to "b", and the result of "b" is the one and only argument 
to "a".

So if you wanted a function that returns the sum of the lengths of a 
list of strings, you might write
     length . concat
or something, if "concat" was a function that took a list of strings and 
returned their concatenation.

>   There just is something about the Haskell paradigm and syntax that
> makes it confusing and hard to assimilate.

I think most of the powerful languages have syntax that's confusing and 
hard to assimilate. C and C++ are also very confusing in syntax. (For 
example, I can barely follow the reference-counting pointer code you 
posted, and that only because I am only trying to read it and not write 
it. :-)

Even Tcl, which has exactly 12 rules of syntax, winds up being confusing 
to newbies because it's *too* simple. LISP has too many parentheses, 
even tho the grammar is about 3 lines of BNF.

About the only languages that aren't confusing are the weak ones: BASIC, 
Pascal, etc.

If the language is powerful because it does a lot (like Ada or C++) you 
wind up with lots and lots of syntax and lots of rules about the 
interactions. If the language is powerful because it's simple and 
regular (like LISP or FORTH or Tcl or Haskell) then it's confusing 
because there's no *obvious* way to accomplish the powerful stuff you 
know the language is capable of. (Sort of like Go or Chess or something 
- simple rules but very unobvious combinations.)

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 21 Sep 2008 10:24:36
Message: <48d65924$1@news.povray.org>
Orchid XP v8 wrote:
> Warp wrote:
>>   Wouldn't it be simpler to do it like:
>>
>>     if(number == target) break;
>>     if(number < target) std::cout << "Too low.\n";
>>     else std::cout << "Too high.\n";
> 
> Mmm, I guess that would also work...

The pendant in me wants to have an actual condition as the argument to 
"while". :-)  Or at least

do {
   ....
} while (number != target);

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Orchid XP v8
Subject: Re: A test
Date: 21 Sep 2008 10:26:45
Message: <48d659a5$1@news.povray.org>
Darren New wrote:

> The pendant in me wants to have an actual condition as the argument to 
> "while". :-)  Or at least
> 
> do {
>   ....
> } while (number != target);

Yeah - although that would require "number" to be declared outside the 
while loop so that it actually exists. ;-) More subtly, it would have to 
be initialised to a value that is guaranteed to not equal "target". Ooo, 
*that* could be a nasty bug to try to find...!

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 21 Sep 2008 10:39:10
Message: <48d65c8e@news.povray.org>
Orchid XP v8 wrote:
> Darren New wrote:
> 
>> The pendant in me wants to have an actual condition as the argument to 
>> "while". :-)  Or at least
>>
>> do {
>>   ....
>> } while (number != target);
> 
> Yeah - although that would require "number" to be declared outside the 
> while loop so that it actually exists. ;-)

Yes, I think so.

> More subtly, it would have to 
> be initialised to a value that is guaranteed to not equal "target". Ooo, 
> *that* could be a nasty bug to try to find...!

No, because you're using a "do while" instead of just a "while". That 
like "repeat until" in Pascal (except with a reversed boolean, of course).

And yes, you'd have to initialize the value, but that's all high-school 
programming type stuff. Probably the compiler at this point would warn 
you the variable isn't initialized.

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Mueen Nawaz
Subject: Re: (And in Haskell. Obviously.)
Date: 21 Sep 2008 11:14:46
Message: <48d664e6$1@news.povray.org>
Slime wrote:
>> I have a similar issue with stuff like
>>
>>   while (*x++ = *y++) {}
> 
> FYI, I have an issue with stuff like that too. C and C++ do make it easy to 
> write bad code. This is the second time you've mentioned that example, so I 
> assume someone once showed it to you and thought they were being clever. 
> They weren't! Or maybe it's just a popular example, because I was just 
> reading a book about coding style last night that gave that as a bad 
> example.

	The truth is that there is no shortage of programmers out there who 
write like this. I've literally read a C (or was it C++) book  that 
admitted it was obfuscated, and in the same breath suggesting that the 
reader should become accustomed to it because those constructs are common.

-- 
The meek shall inherit the dearth.


                     /\  /\               /\  /
                    /  \/  \ u e e n     /  \/  a w a z
                        >>>>>>mue### [at] nawazorg<<<<<<
                                    anl


Post a reply to this message

From: Orchid XP v8
Subject: Re: My first C++ program
Date: 21 Sep 2008 12:26:26
Message: <48d675b2@news.povray.org>
Warp wrote:

>   The above example code can thus be written as:
> 
>     while(true)
>     {
>         int value;
>         std::cin >> value; // Try to read an integer
>         if(std::cin.fail()) // If there was no integer in the input
>         {
>             std::cin.clear(); // Clear the error flags
>             std::string s;
>             std::cin >> s; // Read a string
>             if(!std::cin.good()) break;
>             std::cout << "The input was something else: " << s << "\n";
>         }
>         else
>         {
>             std::cout << "The input was an integer: " << value << "\n";
>         }
>     }
> 
>   Thus removing the need for stringstreams.

This doesn't appear to work. It waits for me to type a second token, and 
then works with that. (Either that or my program has some other random 
bug... If I ever figure out how to work VisualStudio's debugger I'll let 
you know!)

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Fredrik Eriksson
Subject: Re: A test
Date: 21 Sep 2008 13:56:48
Message: <op.uhuesyd87bxctx@e6600>
On Sun, 21 Sep 2008 16:24:37 +0200, Darren New <dne### [at] sanrrcom> wrote:
> The pendant in me

Don't worry. It will come out naturally in a few days...



-- 
FE


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 21 Sep 2008 14:10:12
Message: <48d68e04$1@news.povray.org>
Fredrik Eriksson wrote:
> On Sun, 21 Sep 2008 16:24:37 +0200, Darren New <dne### [at] sanrrcom> wrote:
>> The pendant in me
> Don't worry. It will come out naturally in a few days...

Normally, complaining about spelling is silly. In this case, tho...

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Warp
Subject: Re: My first C++ program
Date: 21 Sep 2008 14:26:57
Message: <48d691f1@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> This doesn't appear to work. It waits for me to type a second token, and 
> then works with that.

  It works here. Did you try it with gcc?

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: My first C++ program
Date: 21 Sep 2008 14:36:51
Message: <48d69443$1@news.povray.org>
Warp wrote:
> Orchid XP v8 <voi### [at] devnull> wrote:
>> This doesn't appear to work. It waits for me to type a second token, and 
>> then works with that.
> 
>   It works here. Did you try it with gcc?

Just for completeness, yeah. Also didn't work. Unless I did something 
"else" wrong with the code as well...

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: A test
Date: 21 Sep 2008 15:14:49
Message: <48d69d29$1@news.povray.org>
Orchid XP v8 wrote:

> Now, if it was pretty-printed like THIS:
> 
>   http://hpaste.org/10565
> 
> you wouldn't be as confused. (?) If you have some kind of text editor 
> with syntax-hilighting, this isn't an issue.

So I'm guessing either nobody noticed this tucked away here, or it 
doesn't make much difference. (Or nobody even cares anymore... o_O )

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: andrel
Subject: Re: A test
Date: 21 Sep 2008 17:42:39
Message: <48D6C018.10504@hotmail.com>
On 21-Sep-08 6:27, Darren New wrote:
> andrel wrote:
>> Indeed, but only if you assume you have a language that makes that 
>> distinction. 
> 
> That's what I said.
> 
>> Maths does not have 'reserved words'. I.e. for the casual observer 
>> things like '=' and '+' looks as though they are universally defined 
>> and understood the same way. In practice even these are sometimes 
>> redefined to suit a specific field or application in a way that may 
>> even go deeper than overloading. 
> 
> Correct. Except that given the programming language, reserved words are 
> fundamentally different from functions or variables. That's why they're 
> reserved.
> 
> Kind of like parens in math - once you decide you have a grouping 
> operator that's written ( ), you really can't use it to define functions 
> called ( and ).
> 
> The confusion, I think, is that you think maths doesn't have reserved 
> words. It does. They're just outside of the maths.

I definitely think they exist, only that which ones are reserved and 
what they actually mean can vary wildly from field to field. And yes, I 
have seen a serious paper where they redefined '=' in a way that is 
slightly incompatible with standard use (and with a good reason). 
Perhaps you understood me a bit wrong. I am not arguing that you have 
variables, constants, reserved words, functions or whatever in Haskell. 
My only point was that on a fundamental level the difference between the 
categories is so blurred that you should not expect a language to have 
visual clues to distinguish between them. At least not for languages 
based on an abstract concept. For languages designed to just give a 
slightly abstract representation of current hardware and current 
programming techniques that may be quite different.

> For example, the "summation function" is kind of the same as the for 
> loop: start variable and value below the sigma, stop value above the 
> sigma, expression to evaluate to the right of the sigma. The reserved 
> words, in this case, is the English sentence I just wrote describing the 
> functionality.
> 
> Unfortunately, to communicate with the computer about how a compiler 
> works, we need to speak something other than English. That's where the 
> reserved words come in. They're a way for the compiler writer to let the 
> compiler user communicate with the compiler. They are part of the syntax 
> of a language that is implicit in the rules for evaluating the 
> functions, just like (A^A)->C you can do a production to find that A->C 
> because of the rules of pattern matching and substitution. It's 
> virtually impossible (or even utterly impossible) to formalize the 
> productions you use in your formalization.
> 
>> want to model a language on the way mathematics is used, defining 
>> 'reserved words' is something you might want to leave out.
> 
> Granted. But Haskell doesn't model a language on the way mathematics is 
> used. It models a language on one particular mathematics. The reserved 
> words are a syntactic shortcut for a much larger lambda expression, just 
> like "193" is a syntactic shortcut for a big long string of bits in a 
> turing machine.
> 
>>> Knowing what's an argument and what's a function is also pretty 
>>> important for understanding how a given line of code works. 
>>
>> Again absolutely true, for a imperative language. In lambda calculus 
>> and any functional language derived from that this distinction make no 
>> sense at all.
> 
> Except that Haskell is obviously beyond lambda calculus in its 
> implementation and meaning. See any of Andrew's postings about writing 
> "2+2" in lambda calculus.

I did both a course on lambda calculus and one on functional programming 
languages when I was at university. That was 20 years ago, but I don't 
think lambda calculus and functional programming has changed a lot since 
then. The point I was trying to make is that the fact that there is no 
difference in syntax of functions and arguments in lambda calculus is so 
fundamental that it is not a good idea to use these terms to analyse 
Haskell.

>>> If you can't look at the code and figure out which function bodies 
>>> get evaluated, it makes it really rough to work out what's going on, 
>>> even in a functional language.
>>
>> I don't think so. If you have an entity called current_temperature it 
>> should not matter if that is derived by looking at a specific memory 
>> location (a variable), by looking at an index in a circular buffer 
>> (array) or by doing something more complicated like calling a function 
>> of generating an interrupt. OK, it does matter sometimes but only in 
>> an implementation. It should not have any influence on understanding 
>> the code conceptually.
> 
> Sure. And if you have an entity called "o" or "+" or "case" or "start"?

yes?

>> I think you understood that my mean reason for my response was that 
>> Warp is looking with imperative spectacles to lines of code in a 
>> functional language and desperately trying to force it into his own 
>> mindframe.
> 
> I wouldn't go that far, but yes. But if you have a language that defines 
> complex syntax (which Haskell does a little and C++ does a lot) and you 
> can't even parse the syntax tree because you can't distinguish reserved 
> words from variables or functions, then you must admit it's going to be 
> difficult to read the code. Indeed, if you can't even tell where one 
> expression ends and another starts, it can be very difficult to 
> understand the code.

I don't think I ever claimed a program in Haskell or any functional 
language is easy to understand. Nor can I easily understand a paper in 
the field of string theory for that matter. That does not mean however 
that people working in that field or with that language can see the 
structure immediately. I know that, so I won't complain if I don't get 
it myself. Just as that I won't tell a Korean that she should use our 
alphabet because otherwise it won't make sense to me.

(Next time I'll snip unnecessary parts, I promise. Now I am just to tired.)


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 21 Sep 2008 20:19:52
Message: <48d6e4a8$1@news.povray.org>
andrel wrote:
> My only point was that on a fundamental level the difference between th
e 
> categories is so blurred that you should not expect a language to have 

> visual clues to distinguish between them. At least not for languages 
> based on an abstract concept. 

I'm just going to have to disagree here. I think any category that has 
syntax[1] is going to have syntactic equivalents of reserved words.

[1] By which I mean to rule out things like FORTH and Tcl and such, much 

of whose syntax is defined by the code itself rather than the compiler.

> For languages designed to just give a 
> slightly abstract representation of current hardware and current 
> programming techniques that may be quite different.

I don't think it has anything to do with how high-level it is. It has to 

do with whether you can parse the syntax of the language. If "case" is 
allowed to be a variable, and "->" is allowed to be a function, then 
there's no way to write the code in http://hpaste.org/10565 and have it 
make sense.

> The point I was trying to make is that the fact that there is no 
> difference in syntax of functions and arguments in lambda calculus is s
o 
> fundamental that it is not a good idea to use these terms to analyse 
> Haskell.

And can you name a variable λ or . or ) or ( in the lambda calculus?


>> Sure. And if you have an entity called "o" or "+" or "case" or "start"
?
> yes?

How do you distinguish that variable name from the syntactic form that 
"case" currently introduces in Haskell?

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Invisible
Subject: Re: (And in Haskell. Obviously.)
Date: 22 Sep 2008 05:08:46
Message: <48d7609e$1@news.povray.org>
Nicolas Alvarez wrote:

> I understand the C++ one and the Haskell one looks like line noise.

I just found this in the Haskell humour section:

   bos: come on, real programmers use "(((,) <$>) .) . (<*>)"

(It's an IRC quote.)

I wish to point out that I had to actually go look up some of those 
operators just to find out what they do!

   (,) takes two values and returns a 2-element tuple.
   <$> is a generalised version of "map" (not just for lists).
   .   is function composition, as always.
   <*> takes a collection of functions and a collection of values and 
applies one to the other.

So that little expression has the type signature

   (Applicative col) => col (x -> y) -> col x -> col (z -> (y, z))

which more or less tells you what it does (once you realise that "col" 
means "a collection of"). Quite why this particular function would be 
useful for anything is another matter...


Post a reply to this message

From: andrel
Subject: Re: A test
Date: 22 Sep 2008 15:23:29
Message: <48D7F0FA.7070802@hotmail.com>
On 22-Sep-08 2:19, Darren New wrote:
> andrel wrote:
>> My only point was that on a fundamental level the difference between 
>> the categories is so blurred that you should not expect a language to 
>> have visual clues to distinguish between them. At least not for 
>> languages based on an abstract concept. 
> 
> I'm just going to have to disagree here. I think any category that has 
> syntax[1] is going to have syntactic equivalents of reserved words.

I agree totally ;) . The point where we might disagree is that I think 
that there are reserved words that are vital to the language ( e.g. your 
'λ' and '.' and ')' and  '(' of the snipped part below), reserved words 
that are better left untouched because they are too common and it would 
make code incomprehensible if redefined ('for', 'case' and other 
constructs that could be substituted by other constructs) but also 
things that are not reserved but could be (I'd like to have control flow 
'if'/'fi' and 'do'/'od'[1] in C with Dijkstra's non deterministic guards 
and I like them to behave as if they are reserved words). So for me the 
concept of 'reserved words' is too fuzzy to merit special handling.

[1] with probably different names, because 'do' and 'if' already have a 
meaning.

> [1] By which I mean to rule out things like FORTH and Tcl and such, much 
> of whose syntax is defined by the code itself rather than the compiler.

I think that some functional and declarative languages can also be 
included in your list. If we put Haskell on that list, I think we safely 
conclude that we totally agree on everything in this thread.

>> For languages designed to just give a slightly abstract representation 
>> of current hardware and current programming techniques that may be 
>> quite different.
> 
> I don't think it has anything to do with how high-level it is. It has to 
> do with whether you can parse the syntax of the language. If "case" is 
> allowed to be a variable, and "->" is allowed to be a function, then 
> there's no way to write the code in http://hpaste.org/10565 and have it 
> make sense.

Even if you allow total freedom, nothing prevents a community to impose 
restrictions. E.g. on the 1802 all registers are totally equivalent, any 
of the 16 registers can function as a numeric value, a stackpointer or a 
program counter. Nonetheless the programcounter and stackpointer are 
more or less fixed by convention. Indeed to prevent unreadable code.

Another, possibly unrelated, remark. I always though that π (pi) was a 
reserved word throughout mathematics and physics. Until someone 
introduced it as a generalized impulse (with arrow on top, but still). I 
also know that once we had a formula of the energy of a particle in a 
electric field. Something along the lines of:
e=e^(e/..)
where the first e is the energy, but lower case because it is per 
particle. The second e is the conventional constant 2.71... and the 
third is the unit charge 1.6e-19 coulomb (hmm, might have been e^2, it 
is too long ago). Nobody had trouble parsing that.

[I promised to snip something, this part was the most likely candidate]

>>> Sure. And if you have an entity called "o" or "+" or "case" or "start"?
>> yes?
> 
> How do you distinguish that variable name from the syntactic form that 
> "case" currently introduces in Haskell?
> 
you don't. you refrain from using 'case' as a variable by self 
censoring. (and you refrain from introducing new reserved words in 
future versions. Is anybody from Mathworks listening? I repeat, you don't.)


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 22 Sep 2008 16:40:00
Message: <48d802a0@news.povray.org>
andrel wrote:
>> I'm just going to have to disagree here. I think any category that has
 
>> syntax[1] is going to have syntactic equivalents of reserved words.
> 
> I agree totally ;) . The point where we might disagree is that I think 

> that there are reserved words that are vital to the language ( e.g. you
r 
> 'λ' and '.' and ')' and  '(' of the snipped part below), reserved 
words 
> that are better left untouched because they are too common and it would
 
> make code incomprehensible if redefined ('for', 'case' and other 
> constructs that could be substituted by other constructs) but also 
> things that are not reserved but could be (I'd like to have control flo
w 
> 'if'/'fi' and 'do'/'od'[1] in C with Dijkstra's non deterministic guard
s 
> and I like them to behave as if they are reserved words). So for me the
 
> concept of 'reserved words' is too fuzzy to merit special handling.

Sure, I agree. Reserved words should have a meaning that introduces synta
x.

In Tcl, there are what you might think of as "reserved words" like 
braces and dollar signs and whitespace and newlines - things where 
escaping them probably changes the meaning of what you wrote. Then 
there's predefined functions, like "for" and "if" and "proc" (which 
defines new procedures), which you'll wind up breaking everything if you 

change the meaning too much.

But people rewrite things like "proc" all the time, to do things like 
extend the syntax or add tracing or something like that. It's not a 
reserved word if you can use it for something else.

> I think that some functional and declarative languages can also be 
> included in your list. If we put Haskell on that list, I think we safel
y 
> conclude that we totally agree on everything in this thread.

No, because you can't change Haskell syntax, as far as I know. You can't 

name an operator :: and you can't name a function "case". They're 
reserved. As far as I know, you can't make up new syntax for the 
language, and you can't change the syntax it has. I may be wrong about 
that.

>> I don't think it has anything to do with how high-level it is. It has 

>> to do with whether you can parse the syntax of the language. If "case"
 
>> is allowed to be a variable, and "->" is allowed to be a function, 
>> then there's no way to write the code in http://hpaste.org/10565 and 
>> have it make sense.
> 
> Even if you allow total freedom, nothing prevents a community to impose
 
> restrictions.

But that wouldn't be a "reserved word". You can't name a function in C 
with the name "if", because then
    if (x == 5) ;
would change meaning. That's *why* it's a reserved word. Not to avoid 
confusion for the user, but to avoid confusion for the compiler.

> Nobody had trouble parsing that.

Right. Because the words serving the function of reserved words told you 

which variable meant which. In math, those pseudo-reserved words are the 

english telling you what symbols mean. If I just wrote
   e = e ^ ( ... )
and didn't tell you verbally which field of measurements each "e" 
belonged to, you wouldn't be able to understand what the equation means. 

Math is an abbreviation for a whole lot of prose - you can't understand 
a mathematical equation unless the rules are explained outside the 
system of mathematics. The lambda calculus is meaningless until you 
specify how the substitution rules work, and you can't specify that in 
lambda calculus.

Computer programs aren't like that. You don't get to explain in English 
what the compiler should do with your code.

>>>> Sure. And if you have an entity called "o" or "+" or "case" or "star
t"?
>>> yes?
>>
>> How do you distinguish that variable name from the syntactic form that
 
>> "case" currently introduces in Haskell?
>>
> you don't. you refrain from using 'case' as a variable by self 
> censoring. 

OK, maybe I misphrased it. How does the compiler distinguish the 
variable name from the syntactic form that "case" currently introduces 
in Haskell?  If "you don't", then it means your compiler's behavior is 
unspecified when you use the word "case" as a variable. People generally 

don't like compiler behavior to be unspecified for valid programs.

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 22 Sep 2008 16:42:31
Message: <48d80337$1@news.povray.org>
andrel wrote:
> you don't. you refrain from using 'case' as a variable by self 
> censoring. 

Or, to phrase it differently, it's not just a convention of 
self-censoring that you can't name a function ) in the lambda calculus.

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: andrel
Subject: Re: A test
Date: 22 Sep 2008 16:58:20
Message: <48D80735.9060907@hotmail.com>
On 22-Sep-08 22:40, Darren New wrote:
> andrel wrote:
[snip]
>> I think that some functional and declarative languages can also be 
>> included in your list. If we put Haskell on that list, I think we 
>> safely conclude that we totally agree on everything in this thread.
> 
> No, because you can't change Haskell syntax, as far as I know. You can't 
> name an operator :: and you can't name a function "case". They're 
> reserved. As far as I know, you can't make up new syntax for the 
> language, and you can't change the syntax it has. I may be wrong about 
> that.

My point was always the other way around: does Haskell allow you to 
introduce concepts and control structures that from that point on will 
become conceptually 'part of the language' for you? To the extent that 
for you they behave like 'reserved words'. In the sense that overriding 
them will result in mayhem everywhere, not least within your own brain. 
I think it does.

[snip]

>>>>> Sure. And if you have an entity called "o" or "+" or "case" or 
>>>>> "start"?
>>>> yes?
>>>
>>> How do you distinguish that variable name from the syntactic form 
>>> that "case" currently introduces in Haskell?
>>>
>> you don't. you refrain from using 'case' as a variable by self censoring. 
> 
> OK, maybe I misphrased it. How does the compiler distinguish the 
> variable name from the syntactic form that "case" currently introduces 
> in Haskell?  If "you don't", then it means your compiler's behavior is 
> unspecified when you use the word "case" as a variable. People generally 
> don't like compiler behavior to be unspecified for valid programs.

Normal scoping rules may apply.


Post a reply to this message

From: andrel
Subject: Re: A test
Date: 22 Sep 2008 17:05:47
Message: <48D808F4.7000401@hotmail.com>
On 22-Sep-08 22:42, Darren New wrote:
> andrel wrote:
>> you don't. you refrain from using 'case' as a variable by self censoring. 
> 
> Or, to phrase it differently, it's not just a convention of 
> self-censoring that you can't name a function ) in the lambda calculus.
> 
no of course not. You can not even define a function '0' or '+" or 
'increment'. i.e. you can define things that behave that way, given some 
interpretation, but you can not name them as such.


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 22 Sep 2008 17:16:22
Message: <48d80b26$1@news.povray.org>
andrel wrote:
> My point was always the other way around: does Haskell allow you to 
> introduce concepts and control structures that from that point on will 
> become conceptually 'part of the language' for you? 

No, I don't think it does. I don't think it's possible to write "case" 
or "let" in Haskell. That's kind of the point.  I think you're taking 
"reserved words" to mean the same as "meaningful concepts."  I'm talking 
from the point of view of someone building a compiler or something, not 
from someone conceptualizing about an application.

> To the extent that 
> for you they behave like 'reserved words'. 

I don't care what it behaves like in my brain. I care what happens when 
it compiles.

>> OK, maybe I misphrased it. How does the compiler distinguish the 
>> variable name from the syntactic form that "case" currently introduces 
>> in Haskell?  If "you don't", then it means your compiler's behavior is 
>> unspecified when you use the word "case" as a variable. People 
>> generally don't like compiler behavior to be unspecified for valid 
>> programs.
> 
> Normal scoping rules may apply.

Then it wouldn't be a reserved word, would it? :-)

I don't know if Haskell actually disallows the use of variables named 
the same as "reserved words", but if it doesn't, then that's a reserved 
word.

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: andrel
Subject: Re: A test
Date: 22 Sep 2008 17:38:18
Message: <48D81094.5040401@hotmail.com>
On 22-Sep-08 23:16, Darren New wrote:
> andrel wrote:
>> My point was always the other way around: does Haskell allow you to 
>> introduce concepts and control structures that from that point on will 
>> become conceptually 'part of the language' for you? 
> 
> No, I don't think it does. I don't think it's possible to write "case" 
> or "let" in Haskell. That's kind of the point.  I think you're taking 
> "reserved words" to mean the same as "meaningful concepts."  I'm talking 
> from the point of view of someone building a compiler or something, not 
> from someone conceptualizing about an application.
> 
>> To the extent that for you they behave like 'reserved words'. 
> 
> I don't care what it behaves like in my brain. I care what happens when 
> it compiles.

OK, so there is where we part. I don't want to think about hardware or 
compiler issues when I am solving a problem. (except when I end up 
writing a compiler of course). I want to express my thoughts in as clear 
a way as possible. If the language does not give me the freedom to 
express myself as I think is the most clear, I'll try to extend the 
language. Just as when I am doing math and I feel that I should need to 
introduce a new syntax. Standard and new syntax will form my new 
framework. Whatever someone else at any one time though were his 
fundamental concepts is immaterial to me.

> 
>>> OK, maybe I misphrased it. How does the compiler distinguish the 
>>> variable name from the syntactic form that "case" currently 
>>> introduces in Haskell?  If "you don't", then it means your compiler's 
>>> behavior is unspecified when you use the word "case" as a variable. 
>>> People generally don't like compiler behavior to be unspecified for 
>>> valid programs.
>>
>> Normal scoping rules may apply.
> 
> Then it wouldn't be a reserved word, would it? :-)
> 
> I don't know if Haskell actually disallows the use of variables named 
> the same as "reserved words", but if it doesn't, then that's a reserved 
> word.
> 

Let me reiterate, I don't even care if Haskell allows it or not. The 
discussion was if Haskell should visually make the distinction or not. 
To which my answer is no, because what is and what isn't a reserved word 
is too arbitrary. i.e. some are legitimate reserved (most of your 
examples are from that stock), some are reserved but a case could be 
made to relieve them of that status and some are not reserved, but might 
be. So fuzziness all over, hence: do not treat them visually different.


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 22 Sep 2008 18:07:18
Message: <48d81716@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> >   There just is something about the Haskell paradigm and syntax that
> > makes it confusing and hard to assimilate.

> I think most of the powerful languages have syntax that's confusing and 
> hard to assimilate. C and C++ are also very confusing in syntax. (For 
> example, I can barely follow the reference-counting pointer code you 
> posted, and that only because I am only trying to read it and not write 
> it. :-)

  OTOH, I assume his code was something relatively simple. Something you
would write when you are creating a simple and straightforward program.

  My reference counting pointer code uses rather advanced techniques
(related to, among other things, how allocators are used and how templates
behave) which are quite unusual in "normal" C++.

  One good thing in C++ is that usually you can *hide* all that overly
complicated and advanced code behind a simple and nice public interface,
so that the code which *uses* that code can be simple, straightforward
and easy to understand.

  With the Haskell examples I often get the feeling that the code which
I have hard time understanding is code which you write normally, when
implementing your main code, not some advanced techniques you hide behind
a nice module interface.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 22 Sep 2008 18:20:42
Message: <48d81a3a@news.povray.org>
Warp wrote:
>   OTOH, I assume his code was something relatively simple. Something you
> would write when you are creating a simple and straightforward program.

It was "guess a number from 1 to 100, and I'll tell you if you're too 
high or too low."  I don't imagine it would be any more straightforward 
in C or C++, really.  Sure, there were a couple of somewhat odd lines 
that you had to rely on English to understand, like
   case compare number target of
But I found that pretty easy to understand given what the rest of the 
program was doing. I might not have been able to write it or tell you if 
it was wrong/buggy, but I could read it OK.

Throw in the syntax of printf() or "cout << std::eoln" or whatever, and 
I think the syntax in something like C++ is certainly something you need 
to learn to read.

There are some languages (like Ada, for example) that do all that C++ 
does and more, but which use spelled-out words. That doesn't help too 
much when you don't know what the words mean. Telling you it's a limited 
tagged access type doesn't really tell you what it means any more than
   void xyz(void) = 0;
is comprehensible without knowing what it means.

>   My reference counting pointer code uses rather advanced techniques
> (related to, among other things, how allocators are used and how templates
> behave) which are quite unusual in "normal" C++.

OK. Question: I think I've figured out what some of your advice means...

When you say "don't use new", are you really saying "use the calls to 
new that are in the libraries, and you shouldn't have to do that 
yourself"? Or are you really saying "C++ programs rarely need to execute 
the 'new' operator"?

The former I can understand. The latter would seem really confusing to 
me, and I've been interpreting it as the latter, methinks.

>   One good thing in C++ is that usually you can *hide* all that overly
> complicated and advanced code behind a simple and nice public interface,
> so that the code which *uses* that code can be simple, straightforward
> and easy to understand.

Welll..... There's still a bunch of syntax. Template instantiation, << 
and >> for I/O, etc.  I mean, compare Haskell add-up-a-list-of-numbers 
to C++'s. Something like
   fold (+) my_list
to something like
   for (j = std::list.begin(); j != std::list.end(); j = j.next())
     i += j.value;
or some such. :-)

>   With the Haskell examples I often get the feeling that the code which
> I have hard time understanding is code which you write normally, when
> implementing your main code, not some advanced techniques you hide behind
> a nice module interface.

Agreed. I just think it's hard for you for a different reason than C++ 
is hard for Andrew. Haskell is hard to read because there's a lot of 
powerful stuff going on without enough syntax. C++ is hard to read 
because there's a lot of powerful stuff going on with too much syntax. 
If you're used to a lot of syntax, C++ might be easier to read than 
Haskell, and vice versa.

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 22 Sep 2008 18:45:55
Message: <48d82023$1@news.povray.org>
andrel wrote:
> OK, so there is where we part. I don't want to think about hardware or 
> compiler issues when I am solving a problem. 

Me neither. But someone has to. If you're using a language with reserved 
words, you're going to have to avoid them.

> Just as when I am doing math and I feel that I should need to 
> introduce a new syntax. Standard and new syntax will form my new 
> framework. Whatever someone else at any one time though were his 
> fundamental concepts is immaterial to me.

Yep. Then you should be using FORTH or LISP or Tcl or something like 
that, right? What language *do* you prefer? There aren't very many that 
let you introduce new syntax to the language.

In any case, you're still going to have to explain the new syntax, which 
means you're going to have to use a language comprehensible to your 
listeners. You can't just make up a new language from scratch and expect 
to be able to communicate with someone else, even if that other person's 
brain is flexible enough to learn it if taught it.

> Let me reiterate, I don't even care if Haskell allows it or not. The 
> discussion was if Haskell should visually make the distinction or not. 
> To which my answer is no, because what is and what isn't a reserved word 
> is too arbitrary. i.e. some are legitimate reserved (most of your 
> examples are from that stock), some are reserved but a case could be 
> made to relieve them of that status and some are not reserved, but might 
> be. So fuzziness all over, hence: do not treat them visually different.

OK. I'd say I'd want them treated differently if they actually are 
reserved. I.e., if I have a variable called "case", I'd want to see the 
statement starting
    case case of
to have two different color words, for example.

I take it you don't like syntax coloring in your editor?

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 22 Sep 2008 19:50:06
Message: <48d82f2e@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> OK. Question: I think I've figured out what some of your advice means...

> When you say "don't use new", are you really saying "use the calls to 
> new that are in the libraries, and you shouldn't have to do that 
> yourself"? Or are you really saying "C++ programs rarely need to execute 
> the 'new' operator"?

> The former I can understand. The latter would seem really confusing to 
> me, and I've been interpreting it as the latter, methinks.

  It was not a generic advice for making C++ programs. It was an advice
for a *complete beginner* who is starting to learn the basics of the
language.

  It is obvious that at some point a C++ programmer will have to deal
with 'new' and memory management. However, IMO that can be left for later.
First get to know the program without the dirty details.

  Of course using managed memory is a good advice for all C++ programmers,
beginners and experts. Even experts should avoid raw pointers and 'new',
unless there's a good reason not to. When you *must* use them, then it's
good to follow certain programming practices.

> >   One good thing in C++ is that usually you can *hide* all that overly
> > complicated and advanced code behind a simple and nice public interface,
> > so that the code which *uses* that code can be simple, straightforward
> > and easy to understand.

> Welll..... There's still a bunch of syntax. Template instantiation, << 
> and >> for I/O, etc.  I mean, compare Haskell add-up-a-list-of-numbers 
> to C++'s. Something like
>    fold (+) my_list
> to something like
>    for (j = std::list.begin(); j != std::list.end(); j = j.next())
>      i += j.value;
> or some such. :-)

  At least the latter states more explicitly what you are doing.
(And by the way, you advance an iterator with the ++ operator.)

  In the haskell case, it's not at all clear what you are doing. In fact,
I don't even think that your haskell example is correct. I can't find the
function "fold", but the closest thing I can find is the (rather unclearly
named): http://www.zvon.org/other/haskell/Outputprelude/foldl1_f.html

  It seems that, as the name clearly implies, the difference between
foldl and foldl1 is that the first one applies the function to the
second parameter and the first element of the list, then applies the
function to the result and the second element of the list, and so on,
while foldl1 there's only a function and a list and the first element
of the list is now in the role of the second parameter to foldl.

  I think it would be perfectly possible to simulate the same thing in C++
with something like:

    int result = foldl1(plus, intContainer);

with proper implementations of the 'foldl1' and 'plus' templates. The
foldl function would be equally easy:

    int result = foldl(plus, 64, intContainer);

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 22 Sep 2008 22:10:50
Message: <48d8502a$1@news.povray.org>
Warp wrote:
>   It was not a generic advice for making C++ programs. It was an advice
> for a *complete beginner* who is starting to learn the basics of the
> language.

Oh, I see. Well, the handling of assignment and copy constructors is the 
only bit that is particularly confusing to me, language-wise. I may not 
be an expert, but conceptually that's the only concepts I don't think I 
have down.

>>    fold (+) my_list
>> to something like
>>    for (j = std::list.begin(); j != std::list.end(); j = j.next())
>>      i += j.value;
>> or some such. :-)
> 
>   At least the latter states more explicitly what you are doing.

Ehn. The call to fold does too, if you know its definition. Just like if 
you don't know what std::list.begin() does, you're not going to 
understand the C++. Basically, the Haskell line is "put plus signs 
between the elements of my_list and evaluate the result."

>   In the haskell case, it's not at all clear what you are doing. In fact,
> I don't even think that your haskell example is correct. I can't find the
> function "fold", but the closest thing I can find is the (rather unclearly
> named): http://www.zvon.org/other/haskell/Outputprelude/foldl1_f.html

Well, "fold" is the mathematical term. If you worry about associativity 
and such, then you need foldl and foldr, and if you worry about what the 
identity for the operator is, then you use the foldl1 and such. I guess 
Haskell, unlike (say) Erlang, doesn't alias "fold" to one of those.

>   It seems that, as the name clearly implies, the difference between
> foldl and foldl1 is that the first one applies the function to the
> second parameter and the first element of the list, then applies the
> function to the result and the second element of the list, and so on,
> while foldl1 there's only a function and a list and the first element
> of the list is now in the role of the second parameter to foldl.

Yep! That's basically it. But in functional languages, things like fold 
and map and apply and such are used so often, they're as much an idiom as
   for (i = 0; i < j; i++)
is in C.

>   I think it would be perfectly possible to simulate the same thing in C++
> with something like:
> 
>     int result = foldl1(plus, intContainer);
> 
> with proper implementations of the 'foldl1' and 'plus' templates. The
> foldl function would be equally easy:
> 
>     int result = foldl(plus, 64, intContainer);

Yep. I think it could very easily be a function in C++, or even C if you 
want to specialize it every time.

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Orchid XP v8
Subject: Re: A test
Date: 23 Sep 2008 02:29:30
Message: <48d88cca$1@news.povray.org>
Warp wrote:

>   In the haskell case, it's not at all clear what you are doing. In fact,
> I don't even think that your haskell example is correct. I can't find the
> function "fold", but the closest thing I can find is the (rather unclearly
> named): http://www.zvon.org/other/haskell/Outputprelude/foldl1_f.html
> 
>   It seems that, as the name clearly implies, the difference between
> foldl and foldl1 is that the first one applies the function to the
> second parameter and the first element of the list, then applies the
> function to the result and the second element of the list, and so on,
> while foldl1 there's only a function and a list and the first element
> of the list is now in the role of the second parameter to foldl.

printf() is short for "print formatted".

foldl is "fold-left", while foldr is "fold-right". Similarly foldl1 and 
foldr1 only work for non-empty lists (and thus don't require a start 
value; foldr returns the start value unaltered in the case of an empty 
list). More subtle is foldl', which causes the subtotal to *actually 
compute* at each step, rather than just building a giant expression 
which is only evaluated right at the end.

The other name for a fold is "catamorphism", but we won't worry about 
that. ;-)

You can use folds for all kinds of interesting things. E.g., "foldr1 
max" finds the highest element of a list, and "foldr (++) []" takes a 
list of lists and returns a flatterned list. A huge number of standard 
list processing functions are or theoretically can be defined as folds. 
For example:

   filter p = foldr (++) [] . map (\x -> if p x then [x] else [])

That is, take a list. For every element where "p" returns true, make a 
1-element list, otherwise make an empty list. Now just the list of lists 
together...

Map itself can be similarly defined, as can reverse and lookup. In fact, 
just about any process that involves linearly traversing a list (i.e., 
almost all list processing!) can be implemented as a fold. This is quite 
possible not the most *efficient* implementation, but it demonstrates 
the power of the abstraction.

Many other Haskell datatypes also have "fold" functions too. It's a 
common idiom.

>   I think it would be perfectly possible to simulate the same thing in C++
> with something like:
> 
>     int result = foldl1(plus, intContainer);
> 
> with proper implementations of the 'foldl1' and 'plus' templates. The
> foldl function would be equally easy:
> 
>     int result = foldl(plus, 64, intContainer);

It sounds plausible to me...

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Mueen Nawaz
Subject: Re: A test
Date: 23 Sep 2008 11:22:57
Message: <48d909d1$1@news.povray.org>
Warp wrote:
>> Welll..... There's still a bunch of syntax. Template instantiation, << 
>> and >> for I/O, etc.  I mean, compare Haskell add-up-a-list-of-numbers 
>> to C++'s. Something like
>>    fold (+) my_list
>> to something like
>>    for (j = std::list.begin(); j != std::list.end(); j = j.next())
>>      i += j.value;
>> or some such. :-)
> 
>   At least the latter states more explicitly what you are doing.
> (And by the way, you advance an iterator with the ++ operator.)

	Yes, but imagine a conversation between two people. One of them says to 
the other:

1. Take a list of numbers.
2. Take the first element.
3. Add it to the variable i.
4. If you're not at the end of the list, take the next number and repeat 
step 3.

	As opposed to what Darren said:

"Take all the numbers, put a plus sign between them, and give me the 
result".

	I think the name functional programming is very apt. The latter is 
placing more emphasis on the "function" that we want (combining all the 
numbers to get a result).

	In Python, we have reduce, which is a simpler form of foldl (and 
perhaps a better name). Guido hates map, filter and reduce, but I love 
them. Sometimes I use a list comprehension or even an explicit for loop. 
But if in my mind it's "obvious" that what I want to do is a map or a 
reduce, then I write it that way.

	The reality is we don't *always* think procedurally. I'm sure even you 
in your head do occasionally think functionally. It's just that you're 
so used to converting that into a procedure that you don't notice it.

-- 
He's got a magnet!!!  Everybody BACKUP!!!!!!!!


                     /\  /\               /\  /
                    /  \/  \ u e e n     /  \/  a w a z
                        >>>>>>mue### [at] nawazorg<<<<<<
                                    anl


Post a reply to this message

From: Invisible
Subject: Re: A test
Date: 23 Sep 2008 11:25:24
Message: <48d90a64$1@news.povray.org>
Mueen Nawaz wrote:

>     In Python, we have reduce, which is a simpler form of foldl (and 
> perhaps a better name).

...except that the result of a fold can be another list. (And possible 
one that's larger than the original.)

>     The reality is we don't *always* think procedurally. I'm sure even 
> you in your head do occasionally think functionally.

Indeed.


Post a reply to this message

From: Fredrik Eriksson
Subject: Re: A test
Date: 23 Sep 2008 14:07:11
Message: <op.uhx4l9fs7bxctx@e6600>
On Tue, 23 Sep 2008 00:20:42 +0200, Darren New <dne### [at] sanrrcom> wrote:
> Welll..... There's still a bunch of syntax. Template instantiation, <<  
> and >> for I/O, etc.  I mean, compare Haskell add-up-a-list-of-numbers  
> to C++'s. Something like
>    fold (+) my_list
> to something like
>    for (j = std::list.begin(); j != std::list.end(); j = j.next())
>      i += j.value;
> or some such. :-)

'fold' (should probably be 'foldl1') is just a library function, not a  
language primitive. The corresponding C++ library function is  
'std::accumulate'.

   std::accumulate( my_list.begin(), my_list.end(), 0 );



-- 
FE


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 23 Sep 2008 14:16:24
Message: <48d93277@news.povray.org>
Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
> 'fold' (should probably be 'foldl1') is just a library function, not a  
> language primitive. The corresponding C++ library function is  
> 'std::accumulate'.

>    std::accumulate( my_list.begin(), my_list.end(), 0 );

  Which got me thinking: Does foldl1 in haskell work for data containers
other than lists? What if you want to apply it to only a sub-range inside
the data container rather than to the entire container? (Can you do it
without copying the sub-range to a separate container?)

-- 
                                                          - Warp


Post a reply to this message

From: andrel
Subject: Re: A test
Date: 23 Sep 2008 15:05:28
Message: <48D93E41.6090509@hotmail.com>
On 23-Sep-08 0:45, Darren New wrote:
> andrel wrote:
>> OK, so there is where we part. I don't want to think about hardware or 
>> compiler issues when I am solving a problem. 
> 
> Me neither. But someone has to. If you're using a language with reserved 
> words, you're going to have to avoid them.
> 
>> Just as when I am doing math and I feel that I should need to 
>> introduce a new syntax. Standard and new syntax will form my new 
>> framework. Whatever someone else at any one time though were his 
>> fundamental concepts is immaterial to me.
> 
> Yep. Then you should be using FORTH or LISP or Tcl or something like 
> that, right? What language *do* you prefer? 

Ahumm, I mostly use Matlab ATM. That does not mean that I like its 
syntax, it is just my swiss army knife. For things that should be 
maintained we use our MWEB system (Knuth's WEB system modified for 
Matlab). That gives a slighly more expressive system. If we want to we 
can use greek variables with subscripts.
I did like FORTH, precisely for this reason.  Did I ever bore you with 
my multitasking FORTH on the C64? You can't use it for things that have 
to be readable for others. Apparently Andy understands reversed polish, 
but you can't count on that for the average modern student.
I liked Prolog and lambda calculus and functional languages. And 
probably not as a surprise, I like Dijkstra's guarded commands, mostly 
because I don't have a compiler for that*. Must check if there is one 
perhaps.

*) Just kidding of course, it is because it is closer to predicate 
calculus that any other imperative language.

> There aren't very many that let you introduce new syntax to the language.

Afraid so. Lots of stupid graphical interfaces but the use of Lexx and 
Yacc seems to be yet another art lost in the mists of time :(
Just as that you have a number of symbolic formula manupilating programs 
but non that I could find that let you apply predicate transformers on 
complicated boolean expressions interactively.
I think I am somewhat out of touch with 'modern' computer science.

> In any case, you're still going to have to explain the new syntax, which 
> means you're going to have to use a language comprehensible to your 
> listeners. You can't just make up a new language from scratch and expect 
> to be able to communicate with someone else, even if that other person's 
> brain is flexible enough to learn it if taught it.

Sure.

>> Let me reiterate, I don't even care if Haskell allows it or not. The 
>> discussion was if Haskell should visually make the distinction or not. 
>> To which my answer is no, because what is and what isn't a reserved 
>> word is too arbitrary. i.e. some are legitimate reserved (most of your 
>> examples are from that stock), some are reserved but a case could be 
>> made to relieve them of that status and some are not reserved, but 
>> might be. So fuzziness all over, hence: do not treat them visually 
>> different.
> 
> OK. I'd say I'd want them treated differently if they actually are 
> reserved. I.e., if I have a variable called "case", I'd want to see the 
> statement starting
>    case case of
> to have two different color words, for example.
> 
> I take it you don't like syntax coloring in your editor?
> 
Of course I do. I just want to be able to add a few things myself. My 
point is still the other way around ;)


Post a reply to this message

From: Orchid XP v8
Subject: Re: A test
Date: 23 Sep 2008 16:06:39
Message: <48d94c4f$1@news.povray.org>
Warp wrote:

>   Which got me thinking: Does foldl1 in haskell work for data containers
> other than lists?

No. The function specified in the language standard works only for lists.

However, there *is* an alternate version in one of the libraries that 
does work for any suitable container. (Confusingly, it has the same 
name, even though it's a different function.) Almost all container 
libraries supply their own home-grown fold function, which may or may 
not have the same name and/or type signature.

This is something of a known problem. A container like lists can hold 
*any* type of data, but the Set container can only hold "ordered" data. 
We have yet to reach a concensus about how to encode this into the type 
system. (Dependent types look like the future, but that's an 
experimental new feature that isn't part of any official standard, etc.)

> What if you want to apply it to only a sub-range inside
> the data container rather than to the entire container? (Can you do it
> without copying the sub-range to a separate container?)

Notionally, no.

Physically? Ask the optimiser.

(Remember, your "container" might not actually *exist* in its entirity 
until you try to "do" something with it...)

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 23 Sep 2008 17:38:06
Message: <48d961be@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> > What if you want to apply it to only a sub-range inside
> > the data container rather than to the entire container? (Can you do it
> > without copying the sub-range to a separate container?)

> Notionally, no.

> Physically? Ask the optimiser.

  One thing which bothers me with haskell is the amount of features which
rely solely on the compiler being able to optimize them. For example a
simple thing like "go through this subrange inside this list and calculate
the sum of the elements", which you usually do in-place, becomes something
which at the language level requires copying (needlessly) the subrange just
so that you can traverse it, and hoping that the compiler will be able to
figure out what is it that you are really doing and optimizing the copying
away.

  In other words, you would have to know the internal workings and
capabilities of the specific compiler you are using in order to know
if you can do it or if you have to do it by other more difficult means
(if copying the range of elements would be way too heavy and memory
consuming to be feasible).

  I don't know... This kind of defeats the whole purpose of a high-level
language where you are supposed to not to have to worry about internal
implementation details of the compiler.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 23 Sep 2008 21:36:24
Message: <48d99998$1@news.povray.org>
Warp wrote:
>   I don't know... This kind of defeats the whole purpose of a high-level
> language where you are supposed to not to have to worry about internal
> implementation details of the compiler.

I think you could do it the same way you do it in C, if you need to: 
iterate over the list and add up only the elements you're interested in.

fold goes from yadda.begin() to yadda.end(). If you don't want to do 
that, use a different function. Or write it more iteratively, so to 
speak. Think about your C++ implementation of fold - you would have to 
copy the list there too if you wanted to use that on a subset.

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Invisible
Subject: Re: A test
Date: 24 Sep 2008 05:01:30
Message: <48da01ea$1@news.povray.org>
Warp wrote:

>> Notionally, no.
> 
>> Physically? Ask the optimiser.
> 
>   One thing which bothers me with haskell is the amount of features which
> rely solely on the compiler being able to optimize them.

You're used to C++, where what you tell the computer to do is *exactly* 
what the computer does. (Or very close to it.)

The C++ way means that if you're clever, you can write very performant 
code. The Haskell way means that if the compiler suddenly gets smarter, 
your existing code speeds up. (Although the fact that it's speeding up 
implies that it was slower than necessary before.)

> For example a
> simple thing like "go through this subrange inside this list and calculate
> the sum of the elements", which you usually do in-place, becomes something
> which at the language level requires copying (needlessly) the subrange just
> so that you can traverse it, and hoping that the compiler will be able to
> figure out what is it that you are really doing and optimizing the copying
> away.

In this specific case, I'm particularly confident that the compiler can 
work it out. (But - as you point out - that's because I have some idea 
about how this is working internally.)

>   I don't know... This kind of defeats the whole purpose of a high-level
> language where you are supposed to not to have to worry about internal
> implementation details of the compiler.

To an extent, yes.

I think of it as being somewhat like SQL. If you write some random chunk 
of SQL, you can know what the result will be. But how will this result 
be computed? Well, *that* would depend on exactly which database product 
from which vendor with which configuration settings, what indexes have 
been built, what the size of the tables is, how the optimiser has been 
configured...

Now, if it's your job to make sure certain critical queries run fast, 
you will know the particular database you're using and what to do to the 
query to speed it up. You'll look at query plans to see what the 
database is doing, and what might be worth changing. (GHC allows you to 
do something conceptually similar.)

Does having to rephrase an SQL query to make it faster "defeat the 
purpose of SQL"? Not so much. It's unfortunate that it's necessary, but 
it doesn't stop SQL from being a hugely useful thing.

If you want to write performant code in C++, you had better go learn 
about call-by-name vs call-by-reference and how virtual methods are 
implemented and a whole bunch of stuff if you expect your code to be 
performant. C++ doesn't pretend otherwise. In Haskell, you need to have 
some idea how the abstractions you're playing with are implemented too. 
Typically you don't need a really in-depth technical understanding, but 
you do need to have some clue how the machine is doing this stuff.

I guess if you're writing something where efficiency is the absolute 
maximum priority, Haskell perhaps isn't the best possible choice. But 
for the kind of code *I* write, the program is so complicated 
algorithmically that getting it to *work properly* is the top priority. 
(Ever heard the phrase "implement first, optimise second"?) So maybe 
it's just that you and I write different code. My code tends not to be 
performance-critical.


Post a reply to this message

From: Invisible
Subject: Re: A test
Date: 24 Sep 2008 05:04:04
Message: <48da0284$1@news.povray.org>
Actually, I have a question...

The C++ tutorial I'm reading has a section on how to inline functions. 
Now *clearly* the compiler cannot inline something that it can't *find*. 
So all that stuff about putting code into header files if you want it 
inlined across compilation units is a necessary part of the way a C++ 
compiler works. But does C++ ever inline functions within *the same* 
compilation unit automatically? Or does it literally refuse to inline 
every function that doesn't say "inline" on it?


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 24 Sep 2008 09:11:23
Message: <48da3c7b@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> fold goes from yadda.begin() to yadda.end(). If you don't want to do 
> that, use a different function. Or write it more iteratively, so to 
> speak. Think about your C++ implementation of fold - you would have to 
> copy the list there too if you wanted to use that on a subset.

  Or I could simply make an overloaded version of the fold function which
takes an iterator range.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 24 Sep 2008 09:17:09
Message: <48da3dd5@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> The C++ tutorial I'm reading has a section on how to inline functions. 
> Now *clearly* the compiler cannot inline something that it can't *find*. 
> So all that stuff about putting code into header files if you want it 
> inlined across compilation units is a necessary part of the way a C++ 
> compiler works. But does C++ ever inline functions within *the same* 
> compilation unit automatically? Or does it literally refuse to inline 
> every function that doesn't say "inline" on it?

  Whether the compiler will inline a function (from which it has the
implementation at that point) is unspecified and completely up to the
compiler. The 'inline' keyword doesn't really matter in this. The
compiler may well inline a function which does not have the 'inline'
keyword, and it may well not inline a function which has it. In a way,
the 'inline' keyword is a no-op, at least with respect to actual inlining.

  It's not a no-op keyword overall, because it controls how the linker
behaves with that function. If the linker encounters the same 'inline'
function in more than one object file, it will use only one of them and
make all the code which calls that function to use that one.

  If you put a function implementation in a header file, you must make
it 'inline' to avoid linker errors (if the header file is used in more
than one compilation unit). If you don't make it 'inline', you are
effectively instantiating the same function in more than one compilation
unit, and the linker considers this to be an error (name collision of
two different functions).

  (Btw, template functions are implicitly 'inline', so the keyword doesn't
have to be used with them.)

-- 
                                                          - Warp


Post a reply to this message

From: Invisible
Subject: Re: A test
Date: 24 Sep 2008 09:28:39
Message: <48da4087@news.povray.org>
Warp wrote:

>   Whether the compiler will inline a function (from which it has the
> implementation at that point) is unspecified and completely up to the
> compiler. The 'inline' keyword doesn't really matter in this.

Right. So adding an inline function to a header file means that the 
compiler *could* inline it across compilation units (which would 
otherwise be impossible), but ultimately it's up to the compiler to 
decide what it will or won't inline?

I can certainly see why the standard doesn't mandate anything either 
way. Do you happen to know the "typical" behaviour of any well-known C++ 
compilers? (Presumably it varies depending on the optimisation level you 
select...)

>   (Btw, template functions are implicitly 'inline', so the keyword doesn't
> have to be used with them.)

That makes sense.


Post a reply to this message

From: Invisible
Subject: Re: A test
Date: 24 Sep 2008 09:35:12
Message: <48da4210$1@news.povray.org>
Warp wrote:

>   Or I could simply make an overloaded version of the fold function which
> takes an iterator range.

Now what happens if you want to only process elements having some 
arbitrary property? (E.g., only the odd numbers.) Or what if the 
function you're trying to fold is non-associative, and you want to 
rearrange the list so the elements can be processed in a different order?

The idea behind Haskell's data processing function is that each function 
does *one* job, which makes it possible to combine them in any possible 
way. (This is not unlike the Unix idea of implementing complex 
functionallity by "piping" data between multiple simple utility 
programs, as seen in millions of shell scripts.) As soon as you start 
trying to rely on particular pre-combined functions, you lose that 
flexibility.

With lists in particular, the new stream-fusion library means that most 
if not all common combinations of list processing functions get 
automatically fused together by the compiler.

There used to be a function called "concatMap", which does the same 
thing as "concat . map", but more efficiently. It's actually still there 
for compatibility, but with stream fusion you don't actually need it any 
more [because "concat . map" gets optimised into the same thing].

If you really need killer performance on a critical region of your 
program... well actually, in that case you probably wouldn't be using 
lists anyway, but still... if you really need killer performance 
somewhere, you can manually fuse if the compiler somehow fails to do it 
for you. But otherwise, the code is much more maintainable if you don't.


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 24 Sep 2008 09:42:32
Message: <48da43c8@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> Warp wrote:

> >   Or I could simply make an overloaded version of the fold function which
> > takes an iterator range.

> Now what happens if you want to only process elements having some 
> arbitrary property? (E.g., only the odd numbers.)

  I make the function take a functor which tells which elements to process.
This is a standard technique in C++.

> Or what if the 
> function you're trying to fold is non-associative, and you want to 
> rearrange the list so the elements can be processed in a different order?

  Then rearrange the list as you like and give it to the function?

> If you really need killer performance on a critical region of your 
> program... well actually, in that case you probably wouldn't be using 
> lists anyway, but still...

  There are algorithms for which linked lists are the most efficient
data container. You still don't want to be needlessly copying the elements
around, though.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 24 Sep 2008 09:44:42
Message: <48da4449@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> I can certainly see why the standard doesn't mandate anything either 
> way. Do you happen to know the "typical" behaviour of any well-known C++ 
> compilers? (Presumably it varies depending on the optimisation level you 
> select...)

  Compilers use some kind of heuristic to determine whether it's beneficial
to inline some function or not. What those heuristics are, I don't know.

  From the programmer's point of view, it doesn't really matter. The program
will behave identically in either case (except maybe a small difference in
execution speed).

-- 
                                                          - Warp


Post a reply to this message

From: Invisible
Subject: Re: A test
Date: 24 Sep 2008 09:51:18
Message: <48da45d6$1@news.povray.org>
>> Now what happens if you want to only process elements having some 
>> arbitrary property? (E.g., only the odd numbers.)
> 
>   I make the function take a functor which tells which elements to process.
> This is a standard technique in C++.

Right. And now what if the elements to process depends on the 
surrounding context and you have to make several passes of the list to 
identify them?

We're missing my point though. My point is that you can't write a 
specialised implementation for every possible combination of list 
processing operations. But with stream fusion, the compiler can generate 
those for you - and yet the source code stays easily readable and 
modifiably.

>   There are algorithms for which linked lists are the most efficient
> data container. You still don't want to be needlessly copying the elements
> around, though.

Agreed.

This is why people have spent years doing research and coming up with 
sophisticated optimisation techniques. :-)


Post a reply to this message

From: Invisible
Subject: Re: A test
Date: 24 Sep 2008 09:53:01
Message: <48da463d@news.povray.org>
Warp wrote:

>   Compilers use some kind of heuristic to determine whether it's beneficial
> to inline some function or not. What those heuristics are, I don't know.
> 
>   From the programmer's point of view, it doesn't really matter. The program
> will behave identically in either case (except maybe a small difference in
> execution speed).

Right. Well I guess that more or less answers my question. I was just a 
little worried that maybe if you don't explicitly say "inline", the 
compiler will never attempt to inline it and hence introduce way too 
much overhead. It seems that's not the case...


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 24 Sep 2008 11:33:56
Message: <48da5de4$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> fold goes from yadda.begin() to yadda.end(). If you don't want to do 
>> that, use a different function. Or write it more iteratively, so to 
>> speak. Think about your C++ implementation of fold - you would have to 
>> copy the list there too if you wanted to use that on a subset.
> 
>   Or I could simply make an overloaded version of the fold function which
> takes an iterator range.

Which is what I was suggesting be done with Haskell, when I said "write 
a more iterative version". Pass in a start index and a length, walk down 
the list "start" elements, apply the operator to "length" elements, 
return the result. If you don't want to copy the list, don't separate 
out the function of copying the subset from the function of applying the 
operator. (I don't know, Haskell might even be smart enough to lazily do 
the Right Thing there even if you do it naively.)

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Invisible
Subject: Re: A test
Date: 24 Sep 2008 11:46:04
Message: <48da60bc$1@news.povray.org>
Darren New wrote:

> Which is what I was suggesting be done with Haskell, when I said "write 
> a more iterative version".

Yeah, if it bothers you that much, you could manually say something like

   my_fold fn x0 i0 i1 list
     | x0 > 0 = my_fold fn x0 (i0-1) (i1-1) (tail list)
     | x1 > 0 = fn (head list) (my_fold fn x0 0 (i1-1) (tail list))
     | otherwise = x0

while will skip over list elements until i0 counts down to 0, then it 
starts folding until i1 counts down to zero, then it stops.

> If you don't want to copy the list, don't separate 
> out the function of copying the subset from the function of applying the 
> operator. (I don't know, Haskell might even be smart enough to lazily do 
> the Right Thing there even if you do it naively.)

In Haskell, writing

   list_function_1 . list_function_2 . list_function_3

is an extremely common idiom, and one which the compiler is designed to 
handle well. GHC has had produce/consume fusion for years, but now 
there's the stream-fusion library, which does even better:

   http://www.cse.unsw.edu.au/~dons/papers/CLS07.html

The fundamental idea is to take list-processing functions, remove the 
recursive part, let the compiler inline like hell, wrap the recursion 
around it, and you end up with something like a single for-loop with all 
the work inside it. No copying involved. (And if the thing that produces 
the list can be fused, the list might not actually exist in memory at 
all. It might be kept in CPU registers. Depending on type, obviously.)


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 24 Sep 2008 12:02:18
Message: <48da648a@news.povray.org>
Invisible wrote:

> Right. Well I guess that more or less answers my question.


http://yosefk.com/c++fqa/inline.html#fqa-9.1

(Warp will hate me for quoting that, but it's actually a pretty good 
explanation.  "inline" has nothing to do with inlining functions.)

-- 
Darren New / San Diego, CA, USA (PST)


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: A test
Date: 24 Sep 2008 15:37:41
Message: <48da9705@news.povray.org>
Warp wrote:
> Invisible <voi### [at] devnull> wrote:
>> Now what happens if you want to only process elements having some
>> arbitrary property? (E.g., only the odd numbers.)
> 
> I make the function take a functor which tells which elements to
> process.
> This is a standard technique in C++.

You can even write a custom iterator that, when incremented, skips even
numbers. Then you can use it with the existing fold function.


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 24 Sep 2008 15:44:25
Message: <48da9899@news.povray.org>
Nicolas Alvarez <nic### [at] gmailcom> wrote:
> Warp wrote:
> > Invisible <voi### [at] devnull> wrote:
> >> Now what happens if you want to only process elements having some
> >> arbitrary property? (E.g., only the odd numbers.)
> > 
> > I make the function take a functor which tells which elements to
> > process.
> > This is a standard technique in C++.

> You can even write a custom iterator that, when incremented, skips even
> numbers. Then you can use it with the existing fold function.

  Good point. In fact, you can create iterators which do a lot of fancy
things, like for example one which traverses the container backwards
(a standard such iterator exists), if you need to perform an operation
in reverse order, or whatever you wish. And all this without having to
modify nor copy the data container.

  Well, I assume that when you say in Haskell "reverse the list and then
give it to this function" the compiler might be able to avoid copying the
list to another one with the elements in reverse order.

-- 
                                                          - Warp


Post a reply to this message

<<< Previous 50 Messages Goto Initial 50 Messages

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