BW Glitch said:
My question goes again, what is so difficult about sum()?
Nothing is difficult about sum(). My point is not that it is
difficult, but rather that is unnecessary bloat, and I don't want to
see Python become a bloated languages.
You say you find yourself incredulous that people find reduce() much
harder than sum(). It is not hard to see why. reduce() does not tell
you anything about what is about to happen, despite your claims that
it is easier.
I didn't say that reduce() is easier. I said that it is perfectly
easy and more useful than sum(), and therefore the criticism of bloat
does not necessarily apply (no pun intended) to it, since it useful
enough, arguably, to not be bloat.
It doesn't offer any advantages over more readable ways of
expressing it, namely loops.
Sure it does. Loops are not particulary easy to read, while reduce()
is perfectly easy to read.
Let's assume that we already understand the function longer, given by
def longer(a, b):
if len(b) > len(a): return b
else: return a
Now consider:
(1) apply(longer, seq)
vs.
(2) longest = ""
for s in seq: longest = longer(acc, s)
Number 1, I can just read, like I can read English. Number 2, I have
to stop and think about. The reason for this is that there are only
three elements of meaning in the first case, and they compose
naturally, while in the second case there are seven elements of
meaning, three of them repeated twice, making ten elements of meaning.
This is too many elements of meaning composed in a rather complicated
way to just be able to read. It requires additional thought in
addition to the reading.
I'm already sick of you saying that reduce() is trivial.
Well, it is.
It took me well over a year to understand what it was for
That's, no doubt, merely because the documentation for reduce() in the
Python manual is not very good. It does nothing to tell you what
kinds of things you might use it for.
and I have yet to find any *good* use to it.
You already know of one: for summing numbers before sum() was
unfortunately added to the language.
In addition to finding the longest string in a sequence, I've given
you a number of other good uses in previous messages: multiplying
numbers, subtracting numbers, xoring bits (good for use as a very easy
checksum), and'ing bits, or'ing bits, and'ing a list of booleans,
or'ing a list of booleans,
Personally, I use it mostly when doing the kind of thing demonstrated
above by apply(longer, seq). I often wish to find the most
{something} element of a sequence, and use apply to find it.
As I said before, it seems to me that you only want people with your
CS background to do the programming.
I had no background in CS when I learned apply() in a minute or two
when I was in tenth grade. All I had was an APL manual, which
explained well in a few sentences (via a few examples) what apply() is
good for.
The question has come in this thread several times and it is still
unanswered: show a case where reduce() _is_ the obvious way of doing
something. I'm not asking for much, y'know...
I've given on several occassions a number of perfectly good uses for
reduce().
Regarding "*the* obvious way" -- I've said before that there is rarely
*one* obvious way to do anything, though there may several obvious
ways. Those who think there is only one obvious way are too full of
their own way of thinking.
Ah, but it is still related, y'know. The problem here was that I
_could_ decide to make the app more sturdy by implementing Gaussian
Elimination with scaled partial pivoting because it is the correct way\0
of doing it.
The issue is not related. There is no reason to make something more
general if no one is ever going to use that extra generality, so you
had no good reason to make your app more general, since *you* didn't
need that extra generality, and *you* were the target audience for
your app. However, Python is a general purpose programming language
where you can't make many assumptions about what people will and won't
need to do with it. People can and do use reduce() to good effect.
And there is no good reason to put sum() into the core of Python
because it just isn't useful enough to be there.
How does this ties to your statement on preparing for worst case
scenario? Well, this ends up to be a design decision, because it
might be irrelevant or difficult to prepare for it. Preparing
something for worst case scenario is a Good Thing(tm) most of the
time, but there are situations where it's your worst nightmare. If
you do program with the worst case scenario every single time
without giving thought to it, fine by me. But I like to make the
desicion on how far should my software go.
I program for the worst case scenario that is important to handle
gracefully. (For instance, the filesystem is full with an app
that is meant for production use.) I don't worry about handling worst
case scenarios that are not important to handle gracefully. (E.g., an
atom bomb has been detonated across the street.) Knowing the
difference is an art, but if you think that a general-purpose max()
routine should not handle gracefully the situation where the input
data is randomly ordered, then I maintain that you are not familiar
enough with your art.
IIRC again, readability and writability are in opposites.
No they are not.
There may be some tension between the two at times, but they *nothing*
like opposites.
If you design a language to be highly readable, you're going to have
a hell of a time writing it (ie, AppleScript, for example; note: it
isn't that bad, just too wordy).
Python is both highly readable and highly writable.
Designing a language with high writability goes the other way (ie,
Perl when used everything). So it's impossible to have it both ways,
readable and writable.
To me, Perl is neither readable nor writable.
Did you missed reduce() in C/C++/Assembly?
At times. I coped.
Btw, C++ has reduce() in its STL, only it is called accumulate(). You
can easily find it, however, because the manual index lists reduce()
and points you at accumulate(). I'm not able to use accumulate(),
however, in my C++ code, because we use a C++ compiler that doesn't
have STL.
This is the example from *The C++ Programming Language* for
accumulate()/reduce() translated into Python:
inventory = ( # Description, Unit Price, Number of Units
("blue table", 50.36, 10),
("red chair", 20.42, 8),
("green vase", 7.99, 5),
("green Lambroghini", 120000, 1),
)
def valueInventory(totalSoFar, record):
return totalSoFar + record[1] * record[2]
totalValueOfInventory = reduce(valueInventory, inventory, 0)
C++'s STL has no sum() function, btw, that I am aware of, though it
does have a sum() method on valarray, which is fine by me.
My point is that you are complaining about Python's restrictions. In a
MCU, restrictions come in various ways.
And there are times where programming an MCU is the best way to
solve a problem.
(1) I never complained about Python's restrictions. I'm complaining
about bloating the language with minimally useful features like sum().
Or the misguided idea that ill-conceived restrictions *should* be put
into Python. Fortunately, such ones have not been put into it.
(2) The idea that Python should be made in any way like an MCU is
crazy.
And which tool do you propose instead of shotguns and fly swatters?
I already said: equipment for manufacturing interchangable parts,
from which either fly swatters or shotguns can be contructed.
And as I pointed out, in English, there is no native concept for
fly-swatter or shot-gun. There is the concept of fly and the concept
of swatter, and the notion of gun and the notion of shot, and both
"fly-swatter" and "shotgun" are built out of these concepts. This is
a very good thing. We hardly need to bloat up the English vocabulary
with special words for fly-swatters or shotguns.
Over all the time I've been doing design, I've learned that there's no
bad design decision if it was reached in a logical way. Now, doing
something just because is a bad design decision.
That's utterly absurd. The road to hell is paved with good intention.
There's a reason for that aphorism -- it's quite true! I can't even
begin to count the numbers of times I've seen problematic designs come
out of reasonable assumptions and plausible reasoning, but often,
something important is overlooked along the way, and that something
comes back to bite you later.
That's impossible, my friend.
If you think so, then you must not use Python very much, my friend.
My time to say I don't see your point. reduce() is way too general for
its own good. Almost every other feature in the language is controlled
in different ways, allowing flexibility and reducing side effects.
reduce() is not too general for it's own good. It is just right.
Your argument for reduce() being too general is that some people have
misused it. That argument is unsound, since people have misused, at
one time or another, nearly every feature of Python. The logical
consequence of your reasoning is that all features of Python are too
general for their own good. Reductio ad absurdum.
For me, expressive is describing something that can other people can
understand.
That's not what "expressive" means. Expressive means that you can
naturally translate your thoughts into the medium, not necessarily
that the result is easy to understand. Shakespeare, for instance, was
expressive, but perhaps not particularly accessible, at least to
most speakers of modern English.
Expressivity and accessibility are orthogonal issues, but they need
not always be at odds, as Python often proves.
Please name mainstream languages that do have reduce().
Python and C++. OCaml gets a bunch of attention these days. I don't
know whether you would consider it mainstream, but it has it, though I
think it might call it foldl(). APL and Lisp are two other popular
languages that have it. The GNU implementation of Java has it.
That's just off of the top of my hea.
Obviously, some memorizing is needed. But I don't want to memorize
every single feature just to know what a code is doing.
That's why you should keep the number of features built into the
language small, powerful, general, and orthogonal. sum() doesn't cut
the mustard.
I tried, but the damn parenthesis just got in the way. Getting
something as simple as adding an array the old fashioned way was
painful.
The argument that Lisp is bad because of its parentheses is an
argument that pains me. That makes no more sense than the
all-to-frequent argument that Python is bad because doing nesting by
indentation is evil.
If you ask me, these are not flaws with the respective languages, but
with the proponents of these arguments. In both cases, the proponent
is projecting their own resistance to learning a different reasonable
approach onto the language. My advice to such people is to learn to
overcome your resistance. Life is richer when you open yourself to
new ideas.
Not necessary. The ternary operator is quite specific (unless you
start abusing it) to the situation and it is included in many
languages.
The ternary operator is anything but specific! It is a general
purpose conditional statement. You will notice that Guido wishes to
make it even more general by adding "elif" clauses.
So the rule of the thumb generally is to put in the core what makes
sense. Not all the general stuff, but what is useful.
Only that which has a lot of uses should be put into the core.
reduce() is everything *but* useful.
As I have pointed out repeatedly, many people, including me, find
reduce() to be very useful.
It would be interesting to hear why sum() was included in the core, though.
Guido woke up on the wrong side of the bed that one day.
sum(), min() and max() are "simple" things in the abstract. However,
they depend on the object. So, in an OO language, these are better
modeled _inside_ an object, which in Python's case is a class.
(1) One shouldn't be forced to program in an OO style in Python.
(2) Often there are a number of different ways to sum together a class of
objects. Defining a different class for each addition operator would
be extremely ugly.
I think the reason addition is "above" all other operations is
because every other operation can be defined with addition. But only
substraction can be used to define addition, if the latter is not
defined.
This has no relevance to the topic at hand. It would be extremely
silly to try to do the equivalent of
reduce(mul, seq)
using addition.
Probabilities, for example, "add" by multiplying them together, so if
you wish to combine numbers representing probabilities, you can't use
sum(), unless you define a class. But (1) you shouldn't have to. (2)
Calling the method that combines probabilities, "__add__", so you can
use sum() on the probabilities would be inadvisable.
My point is that addition can be used to define the other operations.
So?
I am not talking about you, I'm talking about the average person.
First of all, who says I'm not the average person? Secondly, Python
should be aimed for smart people, not "average" people. Programming
languages aimed at "average" people, like Cobol and Visual Basic and
Pascal are *terrible* programming languages. (Versions of Pascal that
have been significantly extended might be okay.)
Not at all. If the functionality of reduce() is, well, reduced, it
would make it easier to explain, as it would have some real
connotation. As is, reduce() serves no purpose.
(1) You keep asserting obvious falsities like "reduce() serves no
purpose". Many people find it very useful and a number of people who
are much smarter than either you or I put it into their programming
languages because it *is* useful. If you insist on holding onto
absurdities, then your conclusions will also be absurd.
(2) People learn to generalize very well and correctly from a small
number of examples. (This is a fact of human cognition, which you may
attempt to disagree with, but if you do then you disagree with
well-researched facts from Cognitive Psychology.) If the general case
is not natural, however, then people won't learn the generalization
properly from the examples. By special-casing reduce(), you would
make it harder to learn and memorize, because the natural
generalization from a small set of examples would be broken. Then one
would have to learn the exceptions and restrictions. So, not only
would it be less useful, it would be harder to learn and remember. A
lose/lose all around.
Either lots of languages do, or lots of languages don't provide
reduce(). This is a mutually exclusive.
If I understand you correctly, you need to learn some elementary
logic. The proposition, "Lots of languages provide reduce()" is
perfectly conisistent with the proposition, "Lots of languages do not
provide reduce()". Just like the proposition "Lots of people love
Christmas" is consistent with the proposition "Lots of people hate
Christmas". If you can't see this, take a nap, have some food to get
nutrition to your brain, and think on it again.
I agree. But its functionality can be easily implemented in most languages.
So? All the more reason to not put it into the core of the language.
reduce() can be easily implemented in almost all modern dynamic
languages too, which is an argument, actually, that it doesn't need to
be in the core. But then again, I never said that it did.
How difficult is it to implement the sum() functionality in either
of these languages? How difficult is it to implement the reduce
functionality?
In Python, both sum() and reduce() are trivial to implement. In C and
Java, it is impossible to implement sum() because neither language
would know how to call the right add operator for the data type being
summed. (Well, maybe you could do it in Java by using its
introspection abilities, but I'm willing to bet that it wouldn't be
pretty). Alternatively, in C and Java, you could implement reduce(),
but it would be rather combersome to use because you would have to
cast the result back to the correct type. Also, the function passed
to reduce() would have to be specially coded to take void*'s or Object
objects, and then cast them to the correct type for that function.
All this would make reduce() rather combersome to use and type unsafe.
For these reasons, the advantages you would see from reduce() in these
languages wouldn't be worth the pain, and consequently, this is why
reduce() is rare in statically typed languages.
In C++, you can easily implement both reduce() and sum() using
templates. (And, in fact, reduce() is part of STL.) This is a good
example of why statically typed languages should have paramaterized
types. Unfortunately, most don't.
No, that's not the direction Python should take. However, built-in
functions should be things that make sense (no reduce()). Or are you
going to argue to eliminate the print statement, like in C?
No. Why would I want to do that? Print, unlike sum(), is used
extremely often.
That would work in an ideal world. Please come to the real world.
In the real world, people make all sorts of stupid decisions when
programming. Languages that try to prevent this are not good,
practical, programming languages. Don't take my word for it -- try
programming in Euclid, which had this very aim.
Me neither. But what other option is there for overgeneralized functions?
You keep ignoring the point. So what if you can abuse reduce() -- you
can abuse loops. We shouldn't try to figure out every way that a loop
might be abused and then have the language try to warn you if you do
that. If you did so, you would also prevent perfectly good usages of
loops. Instead, you should making the looping constructs be simple,
elegant, and general, and rely on training to teach people how to use
loops properly.
The very same thing is true for *any* construct in the language,
including reduce().
Very well. Your decision.
It wouldn't be just my decision. I guarantee you that many, many
people would feel precisely the same way. Perhaps enough to kill off
Python as a viable language.
Strange. In my case, the -Wall saved me from a *lot* of mistakes in
that otherwise would have taken me a lot of time to discover.
Then use it if you like. The nice thing about -Wall is that it is
*optional*. Apparently, you would have it be mandatory. But in that
case, you would never be able to do *anything* that -Wall complains
about. In the compiler I use, that would rule out just about every
program I have ever seen that does anything significant.
I was under the impression you didn't had any. And I still do.
At least I understand elementary logic.
|>oug