POV-Ray : Newsgroups : povray.off-topic : My first C++ program Server Time
9 Nov 2026 03:30:34 EST (-0500)
  My first C++ program (Message 50 to 99 of 149)  
<<< Previous 49 Messages Goto Latest 50 Messages Next 50 Messages >>>
From: Orchid XP v8
Subject: Re: My first C++ program
Date: 20 Sep 2008 06:32:41
Message: <48d4d149$1@news.povray.org>
>> Actually, when I want to compile something, I usually just say "make 
>> foo". Otherwise GCC insists on naming it "a.out", which is very irritating.
> 
>   If you don't specify an executable name, how can gcc guess what is it
> that you want? Note that you can write something like:
> 
> g++ file1.cc file2.cc file3.cc

Now there's interesting. I didn't know you could actually compile 
multiple source files together; I was under the impression that in that 
case, you must manually invoke g++ several times, and then manually 
invoke ld to produce the final binary. (Or, more likely, write a 
makefile that does that.)

>   C++ inherits many things from C, good and bad.

Apparently so. ;-)

[I'm currently compiling a list...]

>> So there *is* a way to automate dependency analysis?
> 
>   The -MM option of gcc (which I use in that generic makefile I attached)
> auto-generates makefile dependencies for all the specified source
> files. Makefiles themselves (at least with gnu make) are so versatile
> that this can be used to completely automatize dependency building.

Well, that's a step up from manually writing a makefile, writing it 
wrong, and producing a binary that segfaults because it's built from 
incompatible object files...

>> This whole concept of having to manually write makefiles and manually 
>> write header files and so forth just seems tedious and error-prone.
> 
>   You don't need to manually write makefiles. Just use a generic one.

Has anybody come up with a tool for autogenerating header files yet?

(Presumably you'd need to edit such a file to remove references to 
things that aren't meant to be public, but at least the function names 
and signatures would match.)

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


Post a reply to this message

From: Warp
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 06:44:06
Message: <48d4d3f6@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> I really can't figure out what everybody finds so confusing about 
> Haskell. Is it just that it uses different syntax to other "common" 
> programming languages? (E.g., no curly braces, no function call 
> brackets.) Or is it something deeper?

  There are many things. For example, in what seems to be a common
Haskell style of brevity, the lack of clear delimiters is confusing.
Often everything you see in a line of haskell code looks like this:

    a b c . d e f . g h

and there's no way of visually telling what they are. The role of each
element may be wildly different, and from a layman's point of view,
completely arbitrary. It's often even hard to see where a command or
definition or whatever *ends* and where a new one starts. The lack of
clear delimiters makes it very confusing.

  If it had some clear delimiters, it *might* become a bit easier to grasp
what exactly is going on. For example something like this is much easier
to start thinking about:

a { b(c, d, e); f(g, h); }

  Even without knowing what is a keyword and what is a type or function
name, it's already much easier to even try to understand how the code
is structured, and what might be being executed before what else.

  For example let's take these lines:

     "+" -> binary (+) stack
     "-" -> binary (-) stack

  There's no ending delimiter for those commands. The only way we could
deduce where the commands are supposed to end is by trying to deduce
from the lines being similar. If you had used whitespace completely
differently, it would become very confusing, for example:

     "+" -> binary
     (+) stack "-"
     -> binary
     (-) stack

  I don't know if that's still valid, but I assume it is. Now it's very
hard for a layman to understand what is going on. And the only thing I did
was to add a few newlines and spaces, nothing more. It became an almost
incomprehensible blob of code, with no clear blocks, command ends or
overall structure.

  Moreover, in Haskell, from a layman's point of view, you are not even
guaranteed that you can read from left-to-right and get a concept of how
the code is being executed. Sometimes code is executed left-to-right,
sometimes right-to-left, sometimes in a wilder order, and seemingly very
arbitrarily. It becomes very hard to follow what is going on there.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: My first C++ program
Date: 20 Sep 2008 06:49:48
Message: <48d4d54b@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> Has anybody come up with a tool for autogenerating header files yet?

  I suppose there are programs which can be used for that. However,
it's very difficult for the program to tell what is it that belongs
to the public interface of the module and what isn't.

  You don't want to add *everything* to a header file. You only want
to add the *minimal* public interface which is necessary to use the
module, no more.

  If you had to annotate in your source file what goes to the header and
what doesn't, you might as well just write the header file yourself with
the same effort.

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: My first C++ program
Date: 20 Sep 2008 06:59:09
Message: <48d4d77d$1@news.povray.org>
>> Has anybody come up with a tool for autogenerating header files yet?
> 
>   I suppose there are programs which can be used for that. However,
> it's very difficult for the program to tell what is it that belongs
> to the public interface of the module and what isn't.

Yes, it seems that such a file would need to be edited by hand afterwards...

If I'm understanding this right, C++ at least tells you if your 
function's signature doesn't match what's declared in the header file.

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


Post a reply to this message

From: Orchid XP v8
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 07:32:29
Message: <48d4df4d@news.povray.org>
Warp wrote:
> Orchid XP v8 <voi### [at] devnull> wrote:
>> I really can't figure out what everybody finds so confusing about 
>> Haskell. Is it just that it uses different syntax to other "common" 
>> programming languages? (E.g., no curly braces, no function call 
>> brackets.) Or is it something deeper?
> 
>   There are many things. For example, in what seems to be a common
> Haskell style of brevity, the lack of clear delimiters is confusing.

> It's often even hard to see where a command or
> definition or whatever *ends* and where a new one starts. The lack of
> clear delimiters makes it very confusing.

>   For example let's take these lines:
> 
>      "+" -> binary (+) stack
>      "-" -> binary (-) stack
> 
>   There's no ending delimiter for those commands.

>   Moreover, in Haskell, from a layman's point of view, you are not even
> guaranteed that you can read from left-to-right and get a concept of how
> the code is being executed. Sometimes code is executed left-to-right,
> sometimes right-to-left, sometimes in a wilder order, and seemingly very
> arbitrarily. It becomes very hard to follow what is going on there.

OK, now I see where you're coming from.



In the case alternatives, the line end *is* the delimiter. So if you 
were to "change only the spacing" then you could actually CHANGE THE 
MEANING of the program! (In fact, likely, cause it to no longer 
compile.) This is different from "curly bracket languages" where you use 
"{", "}" to delimit blocks, and ";" as a seperator. In Haskell, 
generally a newline is a seperator, and indentation delimits blocks.

So, this works:

   case foo of
     1 -> bar1
     2 -> bar2
     3 -> bar3

If the expressions are a bit bigger, you can say

   case foo of
     1 ->
       very_long_thing_1
     2 ->
       very_long_thing_2
     3 ->
       very_long_thing_3

And if they're really long, you can say

   case foo of
     1 ->
       multiline1
       multiline2
       multiline3
     2 ->
       another_block_1
       another_block_2
     3 ->
       yet_another_block

or some such. The case expression itself ends when we get to something 
less indented.

I presume it goes without saying that if you nest things too deeply, 
they end up scrolling off the right edge of the screen and/or becoming 
rather hard to visually untangle. Don't do that! But for the post part, 
it's like a normal curly-bracket language, but without the actual 
brackets. (It's normal practise to indent things anyway.)



Expression execution order is more complicated. First, you can say

   fn3 (fn2 (fn1 x))

which does... what you'd think it does. It calls the function fn1, and 
then passes its result to fn2, and finally passes that to fn3. You can 
also write

   fn3 $ fn2 $ fn1 $ x

which does exactly the same thing, but doesn't require you to match up 
the right number of brackets at the other end. Subtley different, you can do

   fn3 . fn2 . fn1

which yields a *function* that will do the same thing as the above, 
*when* you actually give it an argument. (Notice there's no "x" here. 
That's deliberate. This doesn't produce a result, it produces a 
function.) So

   (fn3 . fn2 . fn1) x

would be a needlessly wordy way to do the same thing as the previous two 
examples.

(As an aside, it should now be clear why the functions are listed 
"backwards". If you take a look at the very first expression, this is 
almost valid C or C++.)



I guess uttering

   mapM_ (\(n,v) -> putStrLn $ "[" ++ show n ++ "]: " ++ show v) (zip 
[0..] stack)

*is* pretty crazy. (It doesn't even fit on one line, for example.) But 
other than that, it should be *reasonably* clear that main_loop does... 
whatever the hell that line does, then it does (putStr "Calc> "), then 
it does (cmd <- getLine), and then it does that case expression.



If you've been paying attention, you may have spotted that the very last 
line of the program *does* in fact have some delimiters:

   _      -> do putStrLn "Stack underflow."; main_loop stack

Haskell does in fact permit you to use curly brackets and semicolons if 
you want to. It's just that most programmers don't. (And, in an amusing 
twist, curly brackets are also used for something completely unrelated 
as well, so it's probably best to _only_ use them for that. Less 
confusing that way...)

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


Post a reply to this message

From: Mueen Nawaz
Subject: Re: My first C++ program
Date: 20 Sep 2008 11:34:49
Message: <48d51819$1@news.povray.org>
Warp wrote:
>>         If you DO want to read a whole line, look up the getline function. That 
>> will also take in an "empty" line.
> 
>   The problem with getline() is precisely that it reads an entire line.
> If there are several whitespace-separated things in that line, it will
> still read the entire line.

	Which is not a problem if that's what you want to do.

	I use getline to simulate a pause, where the user has to press Enter to 
continue (there's another function for just reading a character - I 
forget what it was).

-- 
Copywight 1991 Elmer Fudd.  All wights wesewved


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


Post a reply to this message

From: Darren New
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 11:35:59
Message: <48d5185f@news.povray.org>
Warp wrote:
> Often everything you see in a line of haskell code looks like this:
>     a b c . d e f . g h
> and there's no way of visually telling what they are.

Yeah. I find this is where I have big stumbling blocks reading both 
Haskell and ML.

Of course, part of the reason for that is that there really isn't a 
clear separation between functions and "values". You can't really say 
something like Erlang says, where function names start with lower case 
and variable start with upper case. Maybe if there was a heirarchy of 
alphabets/fonts like in math, you could see that (for example) "binary" 
needs to take an operator because it's in bold, or some such.

>   For example let's take these lines:
> 
>      "+" -> binary (+) stack
>      "-" -> binary (-) stack
> 
>   There's no ending delimiter for those commands. 

I think Haskell is line oriented. Commands end at the end of lines. 
Since I use a lot (relatively speaking) of languages like this, that's 
not what's confusing. (Python, Tcl, most macro languages, etc.)

>   Moreover, in Haskell, from a layman's point of view, you are not even
> guaranteed that you can read from left-to-right and get a concept of how
> the code is being executed. 

Or even if it executes at all. :-)

 > Sometimes code is executed left-to-right,
> sometimes right-to-left, sometimes in a wilder order, and seemingly very
> arbitrarily. It becomes very hard to follow what is going on there.

Yet, oddly enough, the most naive complaint about LISP is all the parens 
that completely disambiguate evaluation, and about APL that the 
evaluation order is strictly right to left without parens. :-)

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


Post a reply to this message

From: Darren New
Subject: Re: My first C++ program
Date: 20 Sep 2008 11:43:58
Message: <48d51a3e$1@news.povray.org>
Orchid XP v8 wrote:
> Now there's interesting. I didn't know you could actually compile 
> multiple source files together; I was under the impression that in that 
> case, you must manually invoke g++ several times, and then manually 
> invoke ld to produce the final binary. (Or, more likely, write a 
> makefile that does that.)

That's basically what happens internally. I don't think it's like Java, 
where putting multiple sources on the same line does things that 
compiling them separately can't.  (For example, putting multiple sources 
on the same line is the only way to get Java to compile circular 
dependencies between classes, last I looked.)

> Has anybody come up with a tool for autogenerating header files yet?

Yes. About 20 years ago. :-)  It was editor macros in Teco (aka PMate).

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


Post a reply to this message

From: Orchid XP v8
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 11:53:26
Message: <48d51c76$1@news.povray.org>
Darren New wrote:
> Warp wrote:
>> Often everything you see in a line of haskell code looks like this:
>>     a b c . d e f . g h
>> and there's no way of visually telling what they are.
> 
> Yeah. I find this is where I have big stumbling blocks reading both 
> Haskell and ML.

I have a similar issue with stuff like

   while (*x++ = *y++) {}

Apparently that means "deference y, fetch the result, incriment y, 
deference x, store the result there, incriment x". For no particular 
reason other than the specific operator precidences of C.

Similarly, to parse a Haskell expression, note that brackets rule first, 
then the (.) or ($) operator. (You'd have to be mad to mix the two 
together without some brackets first.) No reason, that's just the 
operator precidence rules.

> Of course, part of the reason for that is that there really isn't a 
> clear separation between functions and "values".

Meaning you can write a function that takes a function and returns a 
function which accepts another function which will return a function 
that takes an integer and returns a Boolean. Or similar. Which, even 
I'll admit, is pretty crazy.

> I think Haskell is line oriented. Commands end at the end of lines.

Indeed. (Though strictly Haskell doesn't have "commands", it has 
expressions.) More exactly, blocks of stuff indented by the same amount 
parse as if they were enclosed in {} (which you can manually do, if it 
makes you feel better). Otherwise, expressions end at the end of the line.

>>   Moreover, in Haskell, from a layman's point of view, you are not even
>> guaranteed that you can read from left-to-right and get a concept of how
>> the code is being executed. 
> 
> Or even if it executes at all. :-)

Well, notionally you can ignore lazy execution while figuring out the 
meaning of the statement, and *then* consider how (if at all) laziness 
affects it afterwards.

>> Sometimes code is executed left-to-right,
>> sometimes right-to-left, sometimes in a wilder order, and seemingly very
>> arbitrarily. It becomes very hard to follow what is going on there.
> 
> Yet, oddly enough, the most naive complaint about LISP is all the parens 
> that completely disambiguate evaluation, and about APL that the 
> evaluation order is strictly right to left without parens. :-)

One of the most common things beginner Haskell programmers do is add 
vast numbers of brackets. ;-) Trust me, beyong a certain point it 
hinders rather than helps.

I think the fact that tuples use regular brackets is rather unhelpful 
here. There's a very subtle visual difference between (sin(x) + sin(y)) 
and (sin(x), sin(y)), but their meanings are quite different. It might 
have been better if we had <sin(x), sin(y)> or something, like POV-Ray 
does...

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


Post a reply to this message

From: Orchid XP v8
Subject: Re: My first C++ program
Date: 20 Sep 2008 11:56:12
Message: <48d51d1c$1@news.povray.org>
Darren New wrote:

> That's basically what happens internally. I don't think it's like Java, 
> where putting multiple sources on the same line does things that 
> compiling them separately can't.  (For example, putting multiple sources 
> on the same line is the only way to get Java to compile circular 
> dependencies between classes, last I looked.)

When I looked, Sun's javac chokes on circular depends, but M$ 
VisualStudio J++ doesn't blink an eyelid. It just compiles.

This was a *long* time ago tho... Maybe Sun have fixed their compiler now?

(Before I get too smug, I gather GHC also doesn't like circular depends 
either. But then, in Haskell, module bounderies are arbitrary and the 
programmer can choose them. In Java, a class goes in a file, and you 
can't just move stuff from class to class at will. Not if you want your 
design to make sense anyway!)

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


Post a reply to this message

From: Warp
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 12:54:30
Message: <48d52ac6@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> I think Haskell is line oriented. Commands end at the end of lines. 

  What happens if the expression is very long? For example, a function
could take a large amount of parameters, all of which are long expressions
using long variable names.

  I think I'm starting to understand *why* Haskell people prefer using
short and cryptic variable names rather than long and clear ones: If they
did the latter, they would run out of space in their limited lines... :P

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 13:41:50
Message: <48d535de$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> I think Haskell is line oriented. Commands end at the end of lines. 
> 
>   What happens if the expression is very long? For example, a function
> could take a large amount of parameters, all of which are long expressions
> using long variable names.

Put each argument on a seperate line, indented further than the function 
name.

   foo
     arg1
     arg2
     arg3

>   I think I'm starting to understand *why* Haskell people prefer using
> short and cryptic variable names rather than long and clear ones: If they
> did the latter, they would run out of space in their limited lines... :P

Heh. Haskell programs *do* tend to end up with pretty long lines, that's 
for sure. ;-)

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


Post a reply to this message

From: Darren New
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 13:55:01
Message: <48d538f5$1@news.povray.org>
Warp wrote:
>   What happens if the expression is very long? For example, a function
> could take a large amount of parameters, all of which are long expressions
> using long variable names.

I don't know. In Tcl, you put a backslash at the end of the line. Just 
like bash or anything else.

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


Post a reply to this message

From: Orchid XP v8
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 14:07:29
Message: <48d53be1$1@news.povray.org>
>>   What happens if the expression is very long? For example, a function
>> could take a large amount of parameters, all of which are long 
>> expressions
>> using long variable names.
> 
> Put each argument on a seperate line, indented further than the function 
> name.

Or... make them local variables.

(That's more usually done if a certain subexpression is needed more than 
once - since, obviously, putting it in a variable makes it only evaluate 
once. But you can also use it to break things up - especially if what 
you're doing is complicated.)

   let
     thing1 = ...
     thing2 = ...
     thing3 = ...
   in foo thing1 thing2 thing3

Notice that, unlike in "normal" languages, let is an *expression*, but a 
*statement*, so it is valid absolutely anywhere an expression is valid. 
That includes absurd constructions like

   (let x = 5 in x) + (let y = 2 in y)

which just means "5 + 2".

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


Post a reply to this message

From: Orchid XP v8
Subject: A test
Date: 20 Sep 2008 14:21:58
Message: <48d53f46@news.povray.org>
Nicolas Alvarez wrote:

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

OK, well how about this:



module Main where

import System.Random

main = do
   target <- randomRIO (1, 100)
   guess target

guess target = do
   putStr "Guess: "
   txt <- getLine
   let number = read txt :: Int

   case compare number target of
     LT -> do putStrLn "Too low.";  guess target
     GT -> do putStrLn "Too high."; guess target
     EQ -> do putStrLn "You win!"



Does that look like line noise to you? Or can you figure out what that does?

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


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 20 Sep 2008 14:31:06
Message: <48d5416a@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
>    case compare number target of

  I think this line illustrates well what I wrote earlier. Just a list
of whitespace-sepaated words. No delimiters, no hints about what might be
a reserved keyword, what might be a variable, what might be a function.

  I'm no at all sure how that should be parsed. Could it, perhaps, be
something like:

    case(compare(number, target)) of

  What would be wrong with a syntax like that?

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 20 Sep 2008 14:38:18
Message: <48d5431a$1@news.povray.org>
Warp wrote:
>     case(compare(number, target)) of
>   What would be wrong with a syntax like that?

All the functions in Haskell are curried. So it's really
   case (compare(number)(target)) of ...

But yes, this is exactly the kind of thing I have trouble with too, in 
these sorts of languages. Especially when it gets a little more complex 
and you get stuff like
    case bump . hither $ yo stuff of ...
or when people start writing binary functions that take values on both 
the left and the right (in SML, not Haskell) and giving them names like 
"o", with functions returning other functions composed by "o", which was 
apparently not unlike the "." in Haskell.

    this o that value
OK, so what's the precidence on that in ML? Yarg.

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


Post a reply to this message

From: andrel
Subject: Re: A test
Date: 20 Sep 2008 14:48:25
Message: <48D545BF.4090003@hotmail.com>
On 20-Sep-08 20:31, Warp wrote:
> Orchid XP v8 <voi### [at] devnull> wrote:
>>    case compare number target of
> 
>   I think this line illustrates well what I wrote earlier. Just a list
> of whitespace-sepaated words. No delimiters, no hints about what might be
> a reserved keyword, what might be a variable, what might be a function.
> 
why would want you distinguish reserved words, variables and functions?
In C(++) they might be implemented quite differently, that does not mean 
however that are fundamentally different on a conceptual level. Haskell 
apparently does not make such arbitrary and implementation driven 
distinctions. I think we can only applaud that.


Post a reply to this message

From: Vincent Le Chevalier
Subject: Re: A test
Date: 20 Sep 2008 15:24:58
Message: <48d54e0a$1@news.povray.org>
Orchid XP v8 a écrit :
>   putStr "Guess: "

>     LT -> do putStrLn "Too low.";  guess target
>     GT -> do putStrLn "Too high."; guess target
>     EQ -> do putStrLn "You win!"
> 
> Does that look like line noise to you? Or can you figure out what that 
> does?

Honestly just from the strings that are being printed one can guess what 
this program is meant to be doing... Should be true of any language. 
Well one where the strings do not have to be somehow encoded of course ;-)

-- 
Vincent


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 20 Sep 2008 15:30:29
Message: <48d54f55$1@news.povray.org>
andrel wrote:
> why would want you distinguish reserved words, variables and functions?
> In C(++) they might be implemented quite differently, that does not mean 
> however that are fundamentally different on a conceptual level.

I'm pretty sure "reserved words" are conceptually quite different from 
variables, yes. Unless you're talking about an extensible language like 
LISP or FORTH or Tcl, the reserved words let you do things that you 
can't do with functions and variables, and vice versa.

Knowing what's an argument and what's a function is also pretty 
important for understanding how a given line of code works. 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.

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


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 20 Sep 2008 15:48:43
Message: <48d5539b@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> module Main where

> import System.Random

> main = do
>    target <- randomRIO (1, 100)
>    guess target

> guess target = do
>    putStr "Guess: "
>    txt <- getLine
>    let number = read txt :: Int

>    case compare number target of
>      LT -> do putStrLn "Too low.";  guess target
>      GT -> do putStrLn "Too high."; guess target
>      EQ -> do putStrLn "You win!"

  Now you'll have to implement the same program in C++. ;)

-- 
                                                          - Warp


Post a reply to this message

From: Slime
Subject: Re: My first C++ program
Date: 20 Sep 2008 15:55:05
Message: <48d55519$1@news.povray.org>
>> What compiler are you using?
>
> GCC, on Linux, running under QEMU. (Because it's what I have to hand.)


Huh. Crazy that it wouldn't give at least a warning for that. Maybe there's 
a switch to give more picky warnings?

 - Slime
 [ http://www.slimeland.com/ ]


Post a reply to this message

From: Slime
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 16:05:30
Message: <48d5578a$1@news.povray.org>
> 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.

That code tries to do too much at once and is difficult to understand. If 
you made a small mistake while writing it, it wouldn't be immediately 
obvious that there's a problem with the logic. It's bad code. Its only use 
is to help you understand operator precedence and the behavior of the 
different operators. It's very possible to write code that does the same 
thing in a clearer way.

C and C++ just require responsibility. =)

 - Slime
 [ http://www.slimeland.com/ ]


Post a reply to this message

From: Slime
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 16:11:31
Message: <48d558f3$1@news.povray.org>
> To me, all that tricky slight of hand with "break" and "continue" seems 
> far less clear then just directly saying exactly what you want to happen, 
> as the Haskell version does.

You can eliminate the "continue" in your example if you write it like this:

    if ( cmd == "^" )
        break;
    else if ( cmd == "+" )
        Add(stack);
    else if ( cmd == "-" )
        Sub(stack);
    else
        stack.push_back(1);


As for the break, it could just as easily be a 'return' like in the haskell 
code, if you didn't want to print "exit" or if you brought the loop into its 
own function.

 - Slime
 [ http://www.slimeland.com/ ]


Post a reply to this message

From: andrel
Subject: Re: A test
Date: 20 Sep 2008 16:14:22
Message: <48D559E7.2000105@hotmail.com>
On 20-Sep-08 21:30, Darren New wrote:
> andrel wrote:
>> why would want you distinguish reserved words, variables and functions?
>> In C(++) they might be implemented quite differently, that does not 
>> mean however that are fundamentally different on a conceptual level.
> 
> I'm pretty sure "reserved words" are conceptually quite different from 
> variables, yes. 

Indeed, but only if you assume you have a language that makes that 
distinction. It is not a concept that is inherently a part of any 
language. 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. Many operators are also 
'reserved words' in certain subfields and not existent in others. If you 
want to model a language on the way mathematics is used, defining 
'reserved words' is something you might want to leave out.

> Unless you're talking about an extensible language like 
> LISP or FORTH or Tcl, the reserved words let you do things that you 
> can't do with functions and variables, and vice versa.

I think that FORTH introduced me to the idea that it makes sense to 
introduce user level control flow mechanisms.

> 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.

> 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.


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. Then 
again, he might just be pulling Andy's legs. I know he does that 
sometimes and I have not followed the entire thread.


Post a reply to this message

From: Orchid XP v8
Subject: Re: My first C++ program
Date: 20 Sep 2008 17:19:11
Message: <48d568cf$1@news.povray.org>
>>> What compiler are you using?
>> GCC, on Linux, running under QEMU. (Because it's what I have to hand.)
> 
> 
> Huh. Crazy that it wouldn't give at least a warning for that. Maybe there's 
> a switch to give more picky warnings?

Yeah. -Wall. Apparently.

-- 
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: 20 Sep 2008 17:24:45
Message: <48d56a1d$1@news.povray.org>
Warp wrote:

>   Now you'll have to implement the same program in C++. ;)

Yes. That'll be harder, of course - I don't know the standard library 
for C++ inside-out yet. ;-)



I know you probably won't care, but take a look at this:

   http://haskell.org/hoogle/

Now, suppose I want a function that takes a String and turns it into an 
Integer. If you type in

   String -> Integer

and hit the search button, the very first result is

   Prelude.read :: (Read a) => String -> a
   (base)

Which tells you that the "Prelude" module (implicitly imported by all 
Haskell modules) contains a function named "read", which will transform 
a String into any type "a" that is a memory of the "Read" class. (And it 
turns out that *all* the basic types are members of this class.)

Similarly, suppose I want to, say, discover whether a given list 
contains a specified element. Well, the function that does that is 
obviously going to take two arguments - a list, and a thing to find. 
Slightly less obviously, you can only do this for types that can be 
compared. In Haskell, that means types that belong to the 
cryptically-named "Eq" class. So we have

   (Eq x) => [x] -> x -> Bool

A quick search, and we get

   Prelude.elem :: (Eq a) => a -> [a] -> Bool
   (base)

Notice how the arguments are actually the other way round, but the 
search still found the function. (You can also search by name - useful 
if you find yourself asking something like "dude, WTF is 'nub' supposed 
to be?!")

You might not care about Haskell, but you gotta admit all of this is 
pretty neat, eh?



Now, the question is... is there a similar resource for C++? Because for 
starters, the first thing I'm gonna want to know is how to choose a 
random number in C++. ;-) (Altough I dare say for *that*, a simple 
Google search will probably answer...)

-- 
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: 20 Sep 2008 17:36:36
Message: <48d56ce4$1@news.povray.org>
Warp wrote:

>>    case compare number target of
> 
>   I think this line illustrates well what I wrote earlier. Just a list
> of whitespace-sepaated words. No delimiters, no hints about what might be
> a reserved keyword, what might be a variable, what might be a function.

Fair point.

The following are reserved keywords in Haskell:

   module, where, import, qualified, hiding, as, case, of, let, in, 
data, type, newtype, class, instance, deriving, do

I'm pretty sure that's the complete list. I count 17 reserved words. (A 
quick Google search indicates that C++ has roughly 90 of 'em.) If you 
see any of these words, it's a keyword.

(It's actually kinda irritating that "in" and "as" are keywords; these 
would make convinient variable names from time to time, e.g., handles 
named "in" and "out". But, alas, no...)

>   I'm no at all sure how that should be parsed. Could it, perhaps, be
> something like:
> 
>     case(compare(number, target)) of
> 
>   What would be wrong with a syntax like that?

You can write

   case (compare number target) of

if you prefer. This is completely valid syntax.

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. (I don't know anything 
about Emacs, but I imagine it can't be hard to program it so that just 
the 17 words above print in a different colour...)

As for why functions aren't called like foo(x, y, z) like in C... that's 
due to function currying. In Haskell, you say "foo x y z" because then 
you can write "foo x y" to mean a function that just accepts "z". (Or 
just "foo x" for one that accepts "y" and "z", or "foo" for the function 
itself, or whatever.)

Note that you *can* write foo (x, y, z) in Haskell, because "(x, y, z)" 
is what Haskell calls a "tuple". This has a different type though. (It's 
like the difference between calling a C++ function with an array verses 
a vector. Same concept, different implementation - and type.) This is a 
so-called "uncurried function", and they aren't used much.

-- 
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: 20 Sep 2008 17:40:13
Message: <48d56dbd$1@news.povray.org>
Vincent Le Chevalier wrote:

> Honestly just from the strings that are being printed one can guess what 
> this program is meant to be doing... Should be true of any language. 

Well, you'd hope so, yes... ;-)

-- 
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: 20 Sep 2008 17:49:16
Message: <48d56fdc$1@news.povray.org>
Orchid XP v8 wrote:

> The following are reserved keywords in Haskell:
> 
>   module, where, import, qualified, hiding, as, case, of, let, in, data, 
> type, newtype, class, instance, deriving, do
> 
> I'm pretty sure that's the complete list. I count 17 reserved words.

WRONG! It's actually 21. I forget if/then/else, and apparently "default" 
is a keyword...? (Ah, yes. The Haskell '98 Language Report explains that 
this very obscure keyword is for adjusting the type defaulting 
mechanism. As if you'd want to...)

> (I don't know anything 
> about Emacs, but I imagine it can't be hard to program it so that just 
> the 17 words above print in a different colour...)

Apparently it's already been done. (SUPRISE!)

http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode

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


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 18:52:58
Message: <48d57eca@news.povray.org>
Orchid XP v8 wrote:
> Nicolas Alvarez wrote:
> 
>> I understand the C++ one and the Haskell one looks like line noise.
> 
> Uh-huh, and let me guess: You already know how to read and write C++
> fluently, but you know nothing about Haskell yet? :-P

Correct.

> Seriously, I am constantly baffled by statements like this.

But you used to say the same in the opposite direction. "That C++ looks SO
unreadable, yet I fully understand this mess of a haskell program".


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: (And in Haskell. Obviously.)
Date: 20 Sep 2008 18:55:07
Message: <48d57f4a@news.povray.org>
Orchid XP v8 wrote:
> In the case alternatives, the line end *is* the delimiter. So if you
> were to "change only the spacing" then you could actually CHANGE THE
> MEANING of the program! (In fact, likely, cause it to no longer
> compile.) This is different from "curly bracket languages" where you use
> "{", "}" to delimit blocks, and ";" as a seperator. In Haskell,
> generally a newline is a seperator, and indentation delimits blocks.
> 
> So, this works:
> 
>    case foo of
>      1 -> bar1
>      2 -> bar2
>      3 -> bar3
> 
> If the expressions are a bit bigger, you can say
> 
>    case foo of
>      1 ->
>        very_long_thing_1
>      2 ->
>        very_long_thing_2
>      3 ->
>        very_long_thing_3
> 
> And if they're really long, you can say
> 
>    case foo of
>      1 ->
>        multiline1
>        multiline2
>        multiline3
>      2 ->
>        another_block_1
>        another_block_2
>      3 ->
>        yet_another_block
> 
> or some such. The case expression itself ends when we get to something
> less indented.

Just like Python, then :)


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: A test
Date: 20 Sep 2008 18:58:25
Message: <48d58011@news.povray.org>
Orchid XP v8 wrote:
> Does that look like line noise to you? Or can you figure out what that
> does?

Looks understandable, but what the hell does 'guess' do??


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 20 Sep 2008 19:35:55
Message: <48d588db@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> Because for starters, the first thing I'm gonna want to know is how to
> choose a random number in C++. ;-)

  C++ itself doesn't have a random number library (something which will
be fixed in the next C++ standard), but <cstdlib> does have a rand()
function. Rather unusually for a C function, the usage of rand() is
simple and safe: You simply call it, and it returns a random integer
value between 0 and RAND_MAX.

  A simple way of getting a value so that 0 <= value < n, is:

    int value = std::rand() % n;

  Of course it will always return the same values every time you run the
program. If you want it to return different values, you'll have to seed
it with a clock value. Again, no time functions in C++, but the C versions
are also unusually easy and safe to use (at least in this case). Include
<ctime> and then you can seed the rng at the beginning of your program:

    std::srand(std::time(0));

  And by the way, no, this will probably not work correctly:

    int value = std::rand() * n / RAND_MAX;

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: A test
Date: 21 Sep 2008 00:27:22
Message: <48d5cd2a@news.povray.org>
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.

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.

>> 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"?

> 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.

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


Post a reply to this message

From: Orchid XP v8
Subject: Re: (And in Haskell. Obviously.)
Date: 21 Sep 2008 03:51:28
Message: <48d5fd00$1@news.povray.org>
Nicolas Alvarez wrote:
> Orchid XP v8 wrote:
>> In Haskell,
>> generally a newline is a seperator, and indentation delimits blocks.
> 
> Just like Python, then :)

Probably. ;-)

-- 
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 03:53:37
Message: <48d5fd81$1@news.povray.org>
Nicolas Alvarez wrote:

> Looks understandable, but what the hell does 'guess' do??

What, you can't guess?

*rimshot*




Sorry, couldn't resist that... ;-)

-- 
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 04:15:09
Message: <48d6028d$1@news.povray.org>
>> module Main where
> 
>> import System.Random
> 
>> main = do
>>    target <- randomRIO (1, 100)
>>    guess target
> 
>> guess target = do
>>    putStr "Guess: "
>>    txt <- getLine
>>    let number = read txt :: Int
> 
>>    case compare number target of
>>      LT -> do putStrLn "Too low.";  guess target
>>      GT -> do putStrLn "Too high."; guess target
>>      EQ -> do putStrLn "You win!"
> 
>   Now you'll have to implement the same program in C++. ;)

This appears to work:



#include <iostream>
#include <sstream>
#include <cstdlib>
#include <ctime>

void guess(const int target)
{
   while (true)
   {
     std::cout << "Guess: ";
     std::string  txt;
     std::cin  >> txt;

     std::istringstream iss(txt);
     int number;
     iss >> number;

     if (number < target) {std::cout << "Too low."  << std::endl; continue;}
     if (number > target) {std::cout << "Too high." << std::endl; continue;}
     break;
   }

   std::cout << "You win!" << std::endl;
}

int main()
{
   std::srand(std::time(0));
   const int target = std::rand() % 99 + 1;
   guess(target);
}



A few missing semicolons, a few missing std:: qualifiers, and then it 
basically ran first time.

(It is unclear to me whether I could have thrown in a few more "const" 
keywords, but for such a short example it probably doesn't matter.)

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


Post a reply to this message

From: Orchid XP v8
Subject: Re: (And in Haskell. Obviously.)
Date: 21 Sep 2008 04:28:32
Message: <48d605b0$1@news.povray.org>
Slime wrote:

> 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.

More like, "it's the only bit of C that I know". (I'd use an example of 
printf() or something, but first I'd have to find an example that's 
actually *correct*...)

Both C and C++ are positively *bursting* with features that are subtle, 
counter-intuitive and cryptic. This isn't exactly news. C++ at least 
appears to be something of an improvement in this regard...

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


Post a reply to this message

From: Orchid XP v8
Subject: Re: (And in Haskell. Obviously.)
Date: 21 Sep 2008 04:29:02
Message: <48d605ce$1@news.povray.org>
Nicolas Alvarez wrote:

> But you used to say the same in the opposite direction. "That C++ looks SO
> unreadable, yet I fully understand this mess of a haskell program".

Beauty is in the eye of the beholder?

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


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 21 Sep 2008 04:41:06
Message: <48d608a2@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
>      std::string  txt;
>      std::cin  >> txt;

>      std::istringstream iss(txt);
>      int number;
>      iss >> number;

  I think you misunderstood the reason to use stringstreams. Recycling the
user input through the stringstream above is basically a no-op (except that
it's needlessly inefficient). You could have read the value directly from
std::cin:

    int number
    std::cin >> number;

  Why I suggested using stringstreams in your original program was because
you wanted to read either a string or an integer. This can be done by
reading a string, and then trying to parse it as an integer with a
stringstream (which also allows you to check if the parsing succeeded).

  However, here you are simply always reading an integer. There's no need
to use stringstreams.

>      if (number < target) {std::cout << "Too low."  << std::endl; continue;}
>      if (number > target) {std::cout << "Too high." << std::endl; continue;}
>      break;

  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";

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: A test
Date: 21 Sep 2008 04:43:06
Message: <48d6091a$1@news.povray.org>
Warp wrote:
> Orchid XP v8 <voi### [at] devnull> wrote:
>>      std::string  txt;
>>      std::cin  >> txt;
> 
>>      std::istringstream iss(txt);
>>      int number;
>>      iss >> number;
> 
>   I think you misunderstood the reason to use stringstreams.

Er, yeah, good point...

>>      if (number < target) {std::cout << "Too low."  << std::endl; continue;}
>>      if (number > target) {std::cout << "Too high." << std::endl; continue;}
>>      break;
> 
>   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...

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


Post a reply to this message

From: Warp
Subject: Re: A test
Date: 21 Sep 2008 04:56:28
Message: <48d60c3c@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Warp wrote:
> >     case(compare(number, target)) of
> >   What would be wrong with a syntax like that?

> All the functions in Haskell are curried. So it's really
>    case (compare(number)(target)) of ...

  How does Haskell distinguish where a nested (possibly curried) function
call ends, and the outer one continues? Assume that you would want to
write (here in C++ style) something like:

    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')?

  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?

  (Btw, I think this demonstrates one problem with Haskell. I'm an
experienced programmer, and I do have a moderate understanding of the
functional paradigm, and I have been seeing quite many example programs
posted by Andrew during the last years. Yet I'm still completely unable
to figure out or deduce how you could write that in Haskell. It must be
simple, but I just don't know, even though I have seen many examples of
small Haskell programs.
  There just is something about the Haskell paradigm and syntax that
makes it confusing and hard to assimilate.)

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: A test
Date: 21 Sep 2008 05:29:04
Message: <48d613e0$1@news.povray.org>
Warp wrote:

>   How does Haskell distinguish where a nested (possibly curried) function
> call ends, and the outer one continues? Assume that you would want to
> write (here in C++ style) something like:
> 
>     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')?

You'd have to throw in some brackets to disambiguate.

If you change every "foo(x, y, z)" into "(foo x y z)", you'll get a 
valid expression. In this case, we have

   foo a (bar b c) d e

If you wrap the whole thing in brackets, then the following rule 
applies: the first token after each "(" is the function being called; 
everything else is arguments.

What may be a little confusing is that a function's arguments may be 
functions themselves - even standard library functions. This is very 
useful from a programming perspective (indeed, the whole paradigm is 
based on it), but perhaps rather unhelpful for anybody trying to read 
the thing.

Where this starts to go wrong is where you start using operators. 
Obviously "2 + 7" means... well... two plus seven. It would be tedious 
(though perhaps more consistent) to write this as "(+) 2 7".

To understand how to parse an expression involving operators, you must 
know (or take a reasonable stab at) operator precidences. For arithmetic 
operators, it's the usual stuff. Function application has a higher 
precidence than anything else in the language - so "foo x + bar y" 
parses as "(foo x) + (bar y)" and not "foo (x + bar) y".

And that leads us neatly on to...

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

You can't. Because the nested expression isn't the final argument in the 
argument list. (Haskell programmers are very fussy about what order to 
put function arguments in for just this reason.)

>   (Btw, I think this demonstrates one problem with Haskell. I'm an
> experienced programmer, and I do have a moderate understanding of the
> functional paradigm, and I have been seeing quite many example programs
> posted by Andrew during the last years. Yet I'm still completely unable
> to figure out or deduce how you could write that in Haskell. It must be
> simple, but I just don't know, even though I have seen many examples of
> small Haskell programs.
>   There just is something about the Haskell paradigm and syntax that
> makes it confusing and hard to assimilate.)

The following are all equivilent:

   function1 (function2 (function3 (function4 (function5 x))))

   function1 $ function2 $ function3 $ function4 $ function5 $ x

   function1 $ function2 $ function3 $ function4 $ function5 x

   (function1 . function2 . function3 . function4 . function5) x

The last one creates a function by chaining several functions together, 
and then passes x as the argument to that function. Normally you 
wouldn't do that; you'd only use (.) if you wanted to pass a function as 
an argument or something:

   map (reverse . toUpper)

(Takes a list of strings, converts each string to upper case, and then 
reverses it.)

Where this starts to get crazy is if you have functions that take more 
than one argument. Because functions are curried, you may write

   function2args x $ function4args a b c $ function1arg j

or something.



So, between recognising language keywords, bracketed expressions, ($) 
and (.), and infix operators, I guess there *is* quite a bit to be 
getting on with.

It's interesting to me that most people seem confused not by curried 
functions or monads or high-order functions, but by the basics of 
parsing Haskell's syntax. I guess I'm so used to it be now that I take 
it for granted - but obviously, if you can't read the language syntax, 
you don't stand much chance of getting very far. I'll go have a think 
about that...

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


Post a reply to this message

From: Warp
Subject: Re: My first C++ program
Date: 21 Sep 2008 07:21:26
Message: <48d62e33@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
>   What you can do is this:

>     std::string s;
>     while(true)
>     {
>         std::cin >> s;
>         if(!std::cin.good()) break;

>         int value;
>         std::istringstream iss(s);
>         iss >> value;
>         if(!iss.fail())
>             std::cout << "The input was an integer: " << value << "\n";
>         else
>             std::cout << "The input was something else: " << s << "\n";
>     }

  Actually there is a way to achieve the same thing with std::cin
directly, without having to use stringstreams.

  If an input stream fails to read data which fits the parameter type,
it will stop reading, so anything that was in the input (which was not
whitespace) will be left there. It's thus possible to check if reading
the integer filed, and if it did, read it as a string.
  The only catch is that you have to clear the error flags of std::cin
before you can continue reading properly.

  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.

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: My first C++ program
Date: 21 Sep 2008 07:32:00
Message: <48d630b0$1@news.povray.org>
Warp wrote:

>   Actually there is a way to achieve the same thing with std::cin
> directly, without having to use stringstreams.
> 
>   If an input stream fails to read data which fits the parameter type,
> it will stop reading, so anything that was in the input (which was not
> whitespace) will be left there. It's thus possible to check if reading
> the integer filed, and if it did, read it as a string.
>   The only catch is that you have to clear the error flags of std::cin
> before you can continue reading properly.

Thanks for the tip.



By the way... what's the usual C++ idiom for handling failure?

In Haskell, if you have some function that could fail for some reason, 
you have two options:

1. Throw an exception if there's a problem. (Only I/O code can catch and 
handle exceptions.)

2. Use the "maybe" datatype, which contains either some data, or a 
"there's nothing here" flag. (And because the type is different, the 
caller *must* explicitly check which it is before using the result for 
anything.)

Typically you throw an exception for something like "we ran out of 
memory" or "you called with an invalid argument". But for something 
like, say, looking up a key in a dictionary, it's a very predictable 
thing that the key might not actually exist, so the "maybe" approach is 
used there.

What is the "usual" C++ style for this kind of thing? (I'm asking a 
question of style here; clearly there are several possible things you 
*could* do in C++.)

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


Post a reply to this message

From: Warp
Subject: Re: My first C++ program
Date: 21 Sep 2008 07:53:44
Message: <48d635c6@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> What is the "usual" C++ style for this kind of thing? (I'm asking a 
> question of style here; clearly there are several possible things you 
> *could* do in C++.)

  The standard data containers, as well as 'new', throw an exception by
default when they run out of memory. Also the at() member function of
some of the containers throws an exception if you try to index out of
boundaries.

  If you don't want to throw exceptions in your own code, then it depends
on what is it that you want to do to signal a condition.

  The usual way to catch programming errors at runtime is to use
assertions. For example:

void foo(int min, int max)
{
    assert(min <= max);

    // rest of the code here
}

  If the assertion fails, a message will be printed and the program is
immediately terminated at that point. Obviously this should only be
used in situations which are a symptom of a programming error and which
must be fixed.

  (The good thing about assert() is that you can freely use it as much
as you want. In fact, the more you use it, the better. You can compile
the program with a special precompiler parameter which will remove all
the asserts from the executable so that they will not add overhead to
a final version.)

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: My first C++ program
Date: 21 Sep 2008 08:06:18
Message: <48d638ba$1@news.povray.org>
Warp wrote:

>   The standard data containers, as well as 'new', throw an exception by
> default when they run out of memory. Also the at() member function of
> some of the containers throws an exception if you try to index out of
> boundaries.
> 
>   If you don't want to throw exceptions in your own code, then it depends
> on what is it that you want to do to signal a condition.
> 
>   The usual way to catch programming errors at runtime is to use
> assertions. For example:
> 
> void foo(int min, int max)
> {
>     assert(min <= max);
> 
>     // rest of the code here
> }
> 
>   If the assertion fails, a message will be printed and the program is
> immediately terminated at that point. Obviously this should only be
> used in situations which are a symptom of a programming error and which
> must be fixed.

Right. So assert() is for stuff that should never happen if the 
programmer is doing their job right. In other words, BUGS.

How about stuff that might ordinarily be expected to not work? E.g., 
parsing strings, looking up keys in dictionaries, etc.

It seems that streams at least signal errors by altering the stream 
object and getting the programmer to call a member function to check 
whether an error condition occurred. Is that a usual C++ idiom?

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


Post a reply to this message

From: Warp
Subject: Re: My first C++ program
Date: 21 Sep 2008 08:18:51
Message: <48d63bab@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> It seems that streams at least signal errors by altering the stream 
> object and getting the programmer to call a member function to check 
> whether an error condition occurred. Is that a usual C++ idiom?

  I'm not sure there *is* any "usual" C++ idiom for error handling
(other than throwing exceptions).

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: (And in Haskell. Obviously.)
Date: 21 Sep 2008 10:09:31
Message: <48d6559b$1@news.povray.org>
Orchid XP v8 wrote:
> Both C and C++ are positively *bursting* with features that are subtle, 
> counter-intuitive and cryptic.

No, actually, C is really, really straightforward. Almost moreso than 
assembler. It's not subtle and complex and cryptic. It's just difficult 
and tedious.

> This isn't exactly news. C++ at least 
> appears to be something of an improvement in this regard...

I, personally, think C++ has many features that seem subtle and 
counter-intuitive, as evidenced by the fact that it's really hard to 
explain how some of the features work and when they come into play. Most 
people seem to say "this is how you use them" without actually knowing 
why using them that way actually works.  (Granted, I don't have a whole 
lot of experience with C++, so I probably sound way off base to those 
who know C++ well.)

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


Post a reply to this message

<<< Previous 49 Messages Goto Latest 50 Messages Next 50 Messages >>>

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