 |
 |
|
 |
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Darren New <dne### [at] san rr com> 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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Darren New <dne### [at] san rr com> 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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
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] nawaz org<<<<<<
anl
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On Tue, 23 Sep 2008 00:20:42 +0200, Darren New <dne### [at] san rr com> 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
|
 |
|  |
|  |
|
 |
|
 |
|  |
|
 |