reduce() anomaly?

  • Thread starter Stephen C. Waterbury
  • Start date
A

Andrew Dalke

Me:
def imax(seq, f = lambda x: x):

The name, btw, is wrong. It should be 'obj_with_max_value'
'maxobj' or somesuch, since 'imax' should return the maximum
value of the iterator, which happens to be identical to what
max does.

The idea is the same.

Andrew
(e-mail address removed)
 
P

Patrick Maupin

Terry Reedy said:
syntax.)

I presume you mean as opposed to delete it altogether. Because apply
can be used with map while * and ** cannot and at least one person has
said he uses that.

That makes sense. It also fully supports the idea of pulling out
some of these features into an iterable-consumer module. Originally,
apply() provided functionality which would have been exceedingly
difficult to code in Python (I'd say "impossible", except someone
would post an example using eval(), or a stupefyingly long example
function which works on any size list up to 10,000 elements, or
whatever... :), but now it's just a one-line helper function for map().

Regards,
Pat
 
A

Andrew Dalke

Douglas Alan:
In Computer Science, however, "reduce" typically only has one meaning
when provided as a function in a language, and programmers might as
well learn that sooner than later.

There's also a __reduce__ and __reduce_ex__ in the pickle
protocol. See http://www.python.org/peps/pep-0307.html .
It's by far the most mentioned 'reduce' in the Python standard
library. Does it have anything to do with the 'reduce' function?
Not that I can tell. But I can't find an explaination for that
choice of a name.
FAQ
---
Q. Should I ever pass a function with side effects into reduce() or
map()?

A. No.

(Unless the side-effect is just printing out debugging information,
or saving away statistics, or something like that.)

Or raising an exception on error. And a true functional programmer
would say:

Q: Should I ever pass a function with side effects?
A: No.

;)
Andrew
(e-mail address removed)
 
V

Ville Vainio

Douglas Alan said:
Well, bah! There are precious few constructs in this world that are
clearer and more readable than

reduce(add, seq)

I asked my non-programmer girlfriend what she thinks your construct
does - she didn't know. She immediately understood what sum(seq) does.
 
V

Ville Vainio

Alex Martelli said:
EEK -- and have a designed-from-scratch functional module without
the warts. What about starting one as a sourceforge project, as I
mentioned elsewhere?

At least there is

http://sourceforge.net/projects/xoltar-toolkit


[stuff that should remain builtins]
iter, len, pow [for the crucial 3-arguments case], range (or some
preferable variant that returns an iterator), and zip seem pretty
+enumerate

are quite handy for interactive use, such as locals, globals,
dir, vars, ..., are not all that frequently used in programs --
so they might live in a module that the interactive mode gets
automatically, rather than being built-ins.

locals and globals seem to have a natural place in builtins IMHO.
All of this would be perfect for the mailing list on Python 3.0
if the latter existed. Posting it to c.l.py makes it unlikely
Guido will ever consider the discussion's resuts, anyway. The

How about the wiki at python.org?
 
R

Ron Adam

[reduce]
If you don't want to learn a cool concept that will only take you 60
seconds to learn, then you shouldn't be programming! Or you can stick
to loops.

As far as reduce goes, ppl will undoubtedly take a look at the
description, understand it in well under 60 seconds, can't think of
any use for the feature during the next 60 seconds (that wouldn't be
clearer with explicit iteration), and forget it soon after turning the
page. I didn't forget it, just wondered why such an oddball feature
was a builtin. Obviously reduce can rock someone's world, but life is
too short to bother if it doesn't rock yours.
and powerful feature with a slew of specific, tailored features. If
reduce() can be relegated to a library or for the user to implement
for himself, then so can sum(). If the language is to only have one,
it should be reduce().

I also think that reduce, sum, map and filter (and lots of others,
__builtins__ has *too much stuff*) should be removed from builtins,
but that will probably take some time (1997 years?). LC's and genexpes
will take care of most of that stuff. And people can always do:

from funtional import *
# map, filter, reduce, curry, ... (I want lots of these :)

There are also tons of functions that should be in sys, math or
whatever:

reload, repr, divmod, max, min, hash, id, compile, hex...

What's your pet deprecation candidate? I have always thought
`backticks` as repr has got to be the most useless feature around.


I think from a pragmatic point of view, what should be a built in
core, built in module, or in a standard library, should be
determined by how often they are needed to be used or depended on in
programs and modules. You could probably do a statistical annalist
to determine this by searching though the libraries, and a fairly
large library of end use applications.

Moving things closer to the core may increase the efficiency of the
most used items, and moving things further away would simplify and
better organize the language. It's always a trade off to some degree
isn't it?

Also, being in the core is not necessarily the fastest way. Modules
that accessing compiled and optimized dll's can be faster when related
functions are grouped so they can share code and data internally.

_Ron Adam
 
A

Alex Martelli

Andrew Dalke wrote:
...
The other three are in csv.py and look something like
quotechar = reduce(lambda a, b, quotes = quotes:
(quotes[a] > quotes) and a or b,
quotes.keys())
and are identical in intent to your use case -- select the
object from a list which maximizes some f(obj).


I have already suggested, in a post on this thread's direct ancestor 9 days
ago, the 100%-equivalent substitution in pure, simple, faster Python:

quotechar = None
for k in quotes:
if not quotechar or quotes[k]>quotes[quotechar]:
quotechar = k

or, for those who consider fast, simple, obviously correct code too boring,

quotechar = max([ (v,k) for k,v in quotes.iteritems() ])[-1]

which is more concise and at least as clever as the original.

This suggests the usefulness of a new function or two,
perhaps in itertools, which applies a function to a list

Nope -- itertools is not about CONSUMERS of iterators, which this one would
be. All itertools entries RETURN iterators.
of values and returns the first object which has the
maximum value, as in

Given that the sort method of lists now has an optional key= argument, I
think the obvious approach would be to add the same optional argument to min
and max with exactly the same semantics. I.e., just as today:

x = max(somelist)
somelist.sort()
assert x == somelist[-1]

we'd also have

x = max(somelist, key=whatever)
somelist.sort(key=whatever)
assert x == somelist[-1]

a perfectly natural extension, it seems to me. I've found such total and
extreme opposition to this perfectly natural extension in private
correspondence about it with another Python committer that I've so far
delayed proposing it on python-dev -- for reasons that escape me it would
appear to be highly controversial rather than perfectly obvious.
def longest(seq):
return imax(seq, len)

That would be max(seq, key=len) in my proposal.
lines. There were very few, and the paucity suggests
that 'sum' isn't needed all that often. Then again, I'm
not one who suggested that that be a builtin function ;)

Right, that was my own responsibility. I did identify about
10 spots in the standard library then (including substitutions
for reduce); that's more than the typical built-in has, even though
the tasks handled by the standard library are heavily slanted
to string and text processing, networking &c, and (of course)
"pure infrastructure", rather than typical application tasks.


Alex
 
A

Andrew Dalke

Alex:
I have already suggested, in a post on this thread's direct ancestor 9 days
ago, the 100%-equivalent substitution in pure, simple, faster Python:

I've only been skimming this thread. Now upon reread I see you also
looked at the standard library. No fair -- I'm supposed to be the only
one who does that! :)
Nope -- itertools is not about CONSUMERS of iterators, which this one would
be. All itertools entries RETURN iterators.

Yup. There's no good, existing, natural place for such a function, that
I can tell.
Given that the sort method of lists now has an optional key= argument, I
think the obvious approach would be to add the same optional argument to min
and max with exactly the same semantics. I.e., just as today:

That follows Moshe's comment that a "Decorate Max Undecorate",
in parallel to Decorate Sort Undecorate. Nice.
we'd also have

x = max(somelist, key=whatever)
somelist.sort(key=whatever)
assert x == somelist[-1]

Is 'key' also an iterable? ...
That would be max(seq, key=len) in my proposal.

Ahh, it's the function used to get the keys. What about 'getkey'
as a name?

I looked through the back thread but didn't see your function
definition. Is it backwards compatible to the existing max
function?... You know, I never realized how strange max was
in the first place, so that
max(1, 2)
and
max( (1, 2) )
are both valid. It must assume that if there's only one argument
then the latter form is appropriate. Then your form must say
that if there's only one non-keyword argument then it's of
the form

max(seq, **args)

But
max(a, b, key=len)
seems reasonable as well. Then again, so does
max(seq, len)
a perfectly natural extension, it seems to me. I've found such total and
extreme opposition to this perfectly natural extension in private
correspondence about it with another Python committer that I've so far
delayed proposing it on python-dev -- for reasons that escape me it would
appear to be highly controversial rather than perfectly obvious.

My guess is that reaction is based on the need to have both forms
max(a, b)
and
max(seq)
and allow a key function to be passed in, and make it feel
natural without running into problems when the two might be
mixed up.
even though
the tasks handled by the standard library are heavily slanted
to string and text processing, networking &c, and (of course)
"pure infrastructure", rather than typical application tasks.

Yeah, I worry about that bias error when I do my analysis.
I really should also scan some of the other (proprietary) code
bases I have access to, but then it leads to claims of being
irreproducible. Besides, despite being a scientific programmer,
I mostly do "string and text processing, networking &c."

Andrew
(e-mail address removed)
 
B

Bengt Richter

Andrew Dalke wrote:
...
The other three are in csv.py and look something like
quotechar = reduce(lambda a, b, quotes = quotes:
(quotes[a] > quotes) and a or b,
quotes.keys())
and are identical in intent to your use case -- select the
object from a list which maximizes some f(obj).

IMO the use cases in csv.py derive from a particular approach to a particular
problem, and don't mean much beyond that, except as a trigger for ideas. I.e., any
ideas have to stand on their own, without reference to the csv use cases.
(BTW I'm guessing one could do better with "for q in data.split(candidate_quote): ..." and
looking at q[0] and q[-1] and maybe q.strip()[0] and q.strip()[-1] as appropriate
to gather the statistics for the two candidate quotes. This would also let you check
for escaped quotes. But this is another rabbit trail here ;-)
I have already suggested, in a post on this thread's direct ancestor 9 days
ago, the 100%-equivalent substitution in pure, simple, faster Python:

quotechar = None
for k in quotes:
if not quotechar or quotes[k]>quotes[quotechar]:
quotechar = k

or, for those who consider fast, simple, obviously correct code too boring,

quotechar = max([ (v,k) for k,v in quotes.iteritems() ])[-1]

which is more concise and at least as clever as the original.

This suggests the usefulness of a new function or two,
perhaps in itertools, which applies a function to a list

Nope -- itertools is not about CONSUMERS of iterators, which this one would
be. All itertools entries RETURN iterators.
Ok, but what about returning an iterator -- e.g., funumerate(f, seq) -- that supplies f(x),x pairs
like enumerate(seq) supplies i,x?

[I'd suggest extending enumerate, but I already want to pass optional range parameters there,
so one could control the numeric values returned, e.g., enumerate(seq,<params>) corresponding to
zip(xrange( said:
Given that the sort method of lists now has an optional key= argument, I This is a new one on me:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: sort() takes no keyword arguments

Do you mean the comparison function? Or is there something else now too?
I'm beginning to infer that key= is actually a keyword arg for a _function_
to get a "key" value from a composite object (in which case ISTM "getkeyvalue" or "valuefunc"
would be a better name). But IMO "key" suggests it will be used on elements x like x[key],
not passing a definition key=whatever and then using key(x) to get values.
think the obvious approach would be to add the same optional argument to min
and max with exactly the same semantics. I.e., just as today:

x = max(somelist)
somelist.sort()
assert x == somelist[-1]

we'd also have

x = max(somelist, key=whatever)
somelist.sort(key=whatever)
assert x == somelist[-1]
I think I like it, other than the name. Maybe s/key/valuefunc/ ;-)
a perfectly natural extension, it seems to me. I've found such total and
extreme opposition to this perfectly natural extension in private
correspondence about it with another Python committer that I've so far
delayed proposing it on python-dev -- for reasons that escape me it would
appear to be highly controversial rather than perfectly obvious.


That would be max(seq, key=len) in my proposal.

That's a nice option for max (and min, and ??), but ISTM that it would
also be nice to have a factory for efficient iterators of this kind.
It would probably be pretty efficient then to write

maxlen, maxitem = max(funumerate(len,seq))

or

def longest(seq):
return max(funumerate(len,seq))[-1]

and it would be available as infrastructure for other efficient loops in
addition to being tied in to specific sequence processors like max and min.

Of course we can roll our own:
... for x in seq: yield fun(x),x
...
>>> seq = 'ab cde f gh ijk'.split()
>>> seq ['ab', 'cde', 'f', 'gh', 'ijk']
>>> max(funumerate(len,seq)) (3, 'ijk')
>>> min(funumerate(len,seq)) (1, 'f')
>>> max(funumerate(len,seq))[-1] 'ijk'
>>> longest(seq)
'ijk'
lines. There were very few, and the paucity suggests
that 'sum' isn't needed all that often. Then again, I'm
not one who suggested that that be a builtin function ;)

Right, that was my own responsibility. I did identify about
10 spots in the standard library then (including substitutions
for reduce); that's more than the typical built-in has, even though
the tasks handled by the standard library are heavily slanted
to string and text processing, networking &c, and (of course)
"pure infrastructure", rather than typical application tasks.

Regards,
Bengt Richter
 
A

Andrew Dalke

Alex:
Bengt Richter
This is a new one on me:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: sort() takes no keyword arguments
Do you mean the comparison function? Or is there something else now too?

Quoting from Brett Cannon's most excellent
python-dev Summary for 2003-10-01 through 2003-10-15

=============================================
Decorate-sort-undecorate eye for the list.sort guy
--------------------------------------------------
Raymond Hettinger suggested adding built-in support for the
decorate-sort-undecorate (DSU) sorting idiom to list.sort (see the
Python Cookbook recipe at
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52234 which is
recipe 2.3 in the dead tree version or Tim Peters' intro to chapter 2
for details on the idiom). After a long discussion on the technical
merits of various ways to do this, list.sort gained the keyword
arguments 'key' and 'reverse'.

'key' takes in a function that accepts one argument and returns what the
item should be sorted based on. So running ``[(0,0), (0,2),
(0,1)].sort(key=lambda x: x[1])`` will sort the list based on the second
item in each tuple. Technically the sort algorithm just runs the item
it is currently looking at through the function and then handles the
sorting. This avoids having to actually allocate another list. If
'key' and 'cmp' are both provided then 'key' is called on the items to
be sorted and the function's return values are then passed to 'cmp'.

'reverse' does what it sounds like based on whether its argument is true
or false.

list.sort also became guaranteed to be stable (this include 'reverse').

A discussion of whether list.sort should return self came up and was
*very* quickly squashed by Guido. The idea of having a second method,
though, that did sort and returned a copy of the sorted list is still
being considered.

Contributing threads:
`decorate-sort-undecorate
<http://mail.python.org/pipermail/python-dev/2003-October/038652.html>`
`list.sort
I'm beginning to infer that key= is actually a keyword arg for a _function_
to get a "key" value from a composite object (in which case ISTM "getkeyvalue" or "valuefunc"
would be a better name). But IMO "key" suggests it will be used on elements x like x[key],
not passing a definition key=whatever and then using key(x) to get values.

I concur. (Ooops, should have said "Me too!" :)

That's a nice option for max (and min, and ??), but ISTM that it would
also be nice to have a factory for efficient iterators of this kind.
It would probably be pretty efficient then to write

maxlen, maxitem = max(funumerate(len,seq))

With generator expressions this is

maxlen, maxitem = max( ((len(x), x) for x in seq) )

It still has the (slight) problem that it assumes x is comparable
when there are multiple items with the same length. Nearly
all of these quicky versions make that assumption. The
quicky will-work-for-any-item version would look more like

maxlen, pos, maxitem = max( ((len(x), i, x) for i, x in enumerate(seq)) )


Andrew
(e-mail address removed)
 
P

Paul Rubin

Andrew Dalke said:
list.sort also became guaranteed to be stable (this include 'reverse').

I don't see the reason for that. It seems like a needless restriction
on implementers.
A discussion of whether list.sort should return self came up and was
*very* quickly squashed by Guido. The idea of having a second method,
though, that did sort and returned a copy of the sorted list is still
being considered.

Changing the behavior of list.sort would be really bad, but I
certainly favor adding a new method (maybe list.nsort). There should
also be list.nuniq which takes a sorted list and strips duplicate
elements.
 
D

David Eppstein

That's a nice option for max (and min, and ??), but ISTM that it would
also be nice to have a factory for efficient iterators of this kind.
It would probably be pretty efficient then to write

maxlen, maxitem = max(funumerate(len,seq))

With generator expressions this is

maxlen, maxitem = max( ((len(x), x) for x in seq) )

It still has the (slight) problem that it assumes x is comparable
when there are multiple items with the same length. Nearly
all of these quicky versions make that assumption. The
quicky will-work-for-any-item version would look more like

maxlen, pos, maxitem = max( ((len(x), i, x) for i, x in enumerate(seq)) )[/QUOTE]

The new sort(key=...) option works even when the underlying objects are
incomparable. I'd expect the same of max(key=...)

So (supposing such a change ever happens) you could instead write
maxitem = max(seq, key=len)
maxlen = len(maxitem)
 
T

Terry Reedy

Paul Rubin said:
'reverse').

I don't see the reason for that. It seems like a needless restriction
on implementers.

Which is why Guido long resisted making such a guarantee, in spite of
many requests. (The previous list.sort was not stable.) However,
timsort is stable, tested for about a year, and so fast for lists both
random and with various types of order, and so close to optimal in
terms of number of comparisons, that Guido was willing to 'annoint' it
as list.sort for the indefinite future. If there were a generally
useful non-stable sort discovered proposed in the future, is could be
added under a different name.

Terry J. Reedy
 
P

Paul Rubin

Terry Reedy said:
Which is why Guido long resisted making such a guarantee, in spite of
many requests. (The previous list.sort was not stable.) However,
timsort is stable, tested for about a year, and so fast for lists both
random and with various types of order, and so close to optimal in
terms of number of comparisons, that Guido was willing to 'annoint' it
as list.sort for the indefinite future. If there were a generally
useful non-stable sort discovered proposed in the future, is could be
added under a different name.

I think that decision is a little too CPython-centric. Some other
Python implementation (maybe even Jython) might like to implement the
list.sort method by calling some other sort routine (like the one
already in the library for that language) rather than by porting
timsort, even if timsort is better. Also, someone might want to
implement an indexable class that isn't a list (maybe it's a disk file
or something) and want to give it a sort method that cannot work by
sucking the keys into memory and calling timsort (maybe there are too
many keys to fit in memory, so external methods must be used). It may
turn out to work best to use some nonstable sorting method, but then
the behavior will be inconsistent with list.sort and that makes more
cruft that the application programmer has to remember.

Most sorting applications don't care about stability. I think if a
new sorting method is going to get added so there's separate methods
for guaranteed-stable and possibly-nonstable sorting, it's best to let
the new method be the stable one (maybe list.ssort) and leave the
existing one alone.

Of course then you want variants that return self instead of None, so
you have list.sort, list.ssort, list.nsort, and list.nssort. It gets
out of hand.

Maybe the best way to do this kind of thing is with keyword arguments
rather than new methods.
 
A

Andrew Dalke

Paul Rubin:
"Andrew Dalke" <[email protected]> writes:
[actually, I was quoting from the python-dev summary of Brett C's.

Paul:
Changing the behavior of list.sort would be really bad, but I
certainly favor adding a new method (maybe list.nsort). There should
also be list.nuniq which takes a sorted list and strips duplicate
elements.

Do you want unix-style unique where repeats are merged into
one, so that 1 2 2 1 -> 1 2 1 or do you want it to return
items which only occur once, and you don't care about the
order (as in dict.from_keys([1, 2, 2, 1]).keys() which can
return [1, 2] or [2, 1]) or do you want the order of the keys
in the final list to maintain the same order as the initial list,
so that [2, 1, 1, 2] -> [2, 1] always?

Andrew
(e-mail address removed)
 
A

Andrew Dalke

Paul Rubin:
I think that decision is a little too CPython-centric. Some other
Python implementation (maybe even Jython) might like to implement the
list.sort method by calling some other sort routine (like the one
already in the library for that language)

That's not a problem with Jython, since Java has a stable sort, see
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html#sort(java
..util.List)

There was a OCaml implemenation of a Python variant, called
Vyper. OCaml has a stable sort
http://caml.inria.fr/devtools/doc_ocaml_classic/Array.html

C++'s STL include a stable_sort
http://www.codeguru.com/cpp/stlguide/stable_sort.shtml

C# doesn't appear to have a stable sort.

WWPyPyD? (What Would PyPy do?) I don't know.
Also, someone might want to
implement an indexable class that isn't a list (maybe it's a disk file
or something) and want to give it a sort method that cannot work by
sucking the keys into memory and calling timsort (maybe there are too
many keys to fit in memory, so external methods must be used).

There are a couple of misconceptions here:

- sort is a method on lists. It only works on lists. Unlike STL,
which distinguishes between a container and an algorithm, there
is no way to apply sort directly to anything which isn't a list. Your
case (using sort on "a disk file or something") cannot occur.

- All the keys must fit in memory. This is a consequence of being
a list. (The keys may depend on other resource to do the
comparison.) C++ is different in this regard as well.

- The sort only rearranges references so there's no way to use
sort to directly sort the values on disk as you could in C++.
It may
turn out to work best to use some nonstable sorting method, but then
the behavior will be inconsistent with list.sort and that makes more
cruft that the application programmer has to remember.

It may have, but now with the restriction on what the sort must do
there's been a redefinition of what 'best' means for Python. No
implementation of Python is now allowed to do so, so the application
programmer won't have to remember it. All it does it make it
slightly harder for a C# programmer to write a Python implementation.
And I assume there's plenty of 3rd party libraries which can help out.
Most sorting applications don't care about stability.

Really? I prefer my sorts to be stable since it best agrees
with what a person would do, assuming infinite patience.
It's nice because it's well defined and platform independent --
which is important because I've seen bugs crop up in some
programs which assumed a sort (3C) under IRIX will give
the same order as under Solaris -- C's sort is not stable.
I think if a
new sorting method is going to get added so there's separate methods
for guaranteed-stable and possibly-nonstable sorting, it's best to let
the new method be the stable one (maybe list.ssort) and leave the
existing one alone.

Humbug. You want an extra method (and possibly a couple of
independent algorithms which can be used on your disk-based
but list-like data structures) which for the most widely used version
of Python (CPython) will not do anything different and for which
the second most widely used version (Jython) is a trivial change,
all so that *someday* someone who implements a Python in a
language which doesn't have a fast stable search doesn't have
to write one (copying out of any standard text book), find a
3rd party version, or translate one?

Why not worry about something more complex, like regular
expressions. CPython and Jython almost certainly have
differences in edge cases, and what will the version of Python
written in Prolog use?

Andrew
(e-mail address removed)
 
M

Magnus Lie Hetland

[snip]
- sort is a method on lists. It only works on lists. Unlike STL,
which distinguishes between a container and an algorithm, there
is no way to apply sort directly to anything which isn't a list. Your
case (using sort on "a disk file or something") cannot occur.

Surely he was talking about implementing "list-alikes"...? I.e.
sequences polymorphically equivalent to lists, or at least wrt.
sequence-ness and sorting...? The stability requirement does make this
sort of thing a tad more difficult. (Not that I find it very
problematic; I'm just trying to interpret the meaning of the post.)
 
S

SUZUKI Hisao

All in all, I agree with you. You have pointed out precisely
what has been making Python more attractive than, say, Perl.

The argument that some programmers might be too lazy to want to learn
powerful, simple, and elegant features that can be taught in seconds,
is no good reason to remove such features from Python and bloat Python
by replacing them with a plethora of less powerful, less elegant
features.

I like Python because it is a very simple, generic, easy-to-learn
programming language, where I didn't have to learn much of anything
new. It was just like all the other myriad of programming
languages I have programmed in, only less cluttered than most, and
"light-weight" in its implementation and accessibility.

So do I.

As to sum(), when learning string addition (concatenation),
one may wonder why sum() does not handle it:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for +: 'int' and 'str'

while general reduce() does it just as _expected_:
>>> reduce(str.__add__, ['a', 'b', 'c'])
'abc'

It may be sum() that is more difficult to learn...

For this particular problem, it is better to use
''.join(['a', 'b', 'c']), you know.
However, it is important for Python to have an easy and generic
way to do things. If we have to read the manual through to solve
anything, what is the point to use Python instead of Perl (or Ruby,
to some extent)?
I having nothing against learning new stuff, by the way, but when I
want to learn new stuff, I'm not particularly interested in the
idiosyncrasies of Python -- I'd spend my effort learning something a
bit more exotic, like OCaml, or Haskell, that might stretch my brain a
bit. Learning a bunch of idiosyncratic detail is just tedious. This
is one of the most important reasons that Perl sucks so badly.

Again in said:
And as I have pointed out, it goes against the principle of simplicity
and expressiveness to remove an easy to use and easy to learn simple
and powerful feature with a slew of specific, tailored features. If
reduce() can be relegated to a library or for the user to implement
for himself, then so can sum(). If the language is to only have one,
it should be reduce().

I agree with you.

However, It may be better to give reduce() some nice notation.
Someone (sorry, but I do not remember) suggested such one:
[s: s+c for c in ['a', 'b', 'c']]
or
[s='': s+c for c in ['a', 'b', 'c']]
though it may not be the nicest.

-- SUZUKI Hisao
 
A

Andrew Dalke

Magnus Lie Hetland:
Surely he was talking about implementing "list-alikes"...?

Yes, I think you're right about that, and I misinterpreted
his statement.

That being the case, an alternative is to have that 'sort'
implements the Python required semantics, and that
'fsort' or somesuch ('f' for 'fast'?) implement the
appropriate data-structure specific one.

Then again, is the change that "all Python list-alikes must
implement stable sort" or that "Python native lists shall
now and forever implement stable sort"?

The official statement from the BDFL is
http://mail.python.org/pipermail/python-dev/2003-October/038773.html
] OK, I pronounce on this: Python's list.sort() shall be stable.

That's a statement only that list.sort shall be stable and
not that all .sort() methods must be stable.

BTW, there was a *HUGH* amount of discussion about
sort and stability and keys and DSU on the python-dev list.
See the archive
http://mail.python.org/pipermail/python-dev/2003-October/thread.html#38772
and look for "decorate-sort-undecorate" as well as subjects
with the word 'sort' in them.

Andrew
(e-mail address removed)
 
V

Ville Vainio

SUZUKI Hisao said:
However, It may be better to give reduce() some nice notation.

I think the idea is to hide the thing somewhere far away from
builtins, not to *increase* its prominence in the language by
introducing new syntax.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,609
Members
45,253
Latest member
BlytheFant

Latest Threads

Top