sort in scalar context

jplindstrom on 2005-10-01T16:40:49

Wow! The behaviour of sort in scalar context is undefined. I had no idea.

So why sorting in scalar context in the first place? Well...

is($oGraph->aName() + 0, 19, "Returns all nodes");


(the last thing in sub aName is to sort the list)

*Boom*

I understand the point of not doing an unecessary sort, but... why just not let it return the unsorted list in scalar context, i.e. the item count?

Well, at least I learned something new today.


Re:

Aristotle on 2005-10-02T04:12:44

is( @{ [ $oGraph->aName() ] } + 0, 19, "Returns all nodes" );

Re:

Aristotle on 2005-10-02T04:14:24

And yeah, you can make a case for returning an item count instead of just undef.

Why "item count"? Least likely!

merlyn on 2005-10-02T04:41:19

See my perlmonks posting on scalar context. "Count" is actually in the minority for things being returned in a scalar context.

I think a much more interesting thing would be a floating point value between 0 and 1 of how many adjacent pairs of items already meet the sort criteria, so "1..5" would be 1, but "reverse 1..5" would be 0.

Re:

Aristotle on 2005-10-02T06:38:45

That sortedness factor you propose sounds really useless. 0 + sort qw( 1 3 5 7 9 0 2 4 6 8 10 ) would return 0.9. But what am I supposed to conclude from that? The list is certainly not 90% sorted, nor can I think of any other way in which this metric might be useful.

OTOH, returning the item count would allow parity for

sub foo { sort @_ }

with

sub bar { map $_, @_ }

and

sub baz { grep 1, @_ }

in scalar context.

And item count in scalar context is actually the majority among functions that take a list and returns a list in list context.

Re:

Aristotle on 2005-10-02T06:41:11

Okay, it would return 0.8, because the default sort comparator is alphanumeric, not numeric, but you get the point.

I said "interesting", not "useful"

merlyn on 2005-10-02T11:37:43

I think "number of items" would be fairly useless. I mean, why should the word "sort" be there if all you want is the count? It would lead to misleading (and also non-backward compatible) code.

Maybe I'm the only Perl person on the planet that does not presume "length of list in scalar context" for every list-returning operation, but I think it's a fair starting place.

From a practical perspective, channelling Larry here for a moment (which after nearly two decades, I'm getting only slightly better at), there just wasn't a sensible scalar value for sort, hence it was left undef for future expansion.

Re:I said "interesting", not "useful"

Aristotle on 2005-10-02T12:25:42

Lack of parity with map and grep means that implementation details leak out of a function. The caller needs to know whether a function does return sort @foo or something like return map bar($_), sort @foo – even when the sorting is just a part of the function’s contract and not the operation of interest.

That’s just ridiculous.

Also: first you say it would lead to non-backward compatible code, then you say it was left open for expansion. Which is it?

Re:I said "interesting", not "useful"

merlyn on 2005-10-02T12:37:41

But you missed my point. I would not presume that a random subroutine that I called returned a length in a scalar context when only documented to return a list in a list context. So why should "sort" encourage that behavior. Instead, we should be getting the word out there to stop presuming that!

Re:

Aristotle on 2005-10-02T17:27:58

Ah. That is a more reasonable position.

I still don’t see the point. A superbly useful special semantic for the scalar context return of sort will never materialise. It’s been “open for expansion” for over a decade and will remain so for the next one, too.

I’d rather rid the world of another special case, boring as that may be, and spare five people per year the surprise of tripping over this.

But eh.

List in scalar context?!?

bart on 2005-10-03T00:23:26

I'm suprised nobody else told you yet with as many words: there's no such thing as a "list in scalar context".

So you think map and grep do return a list in scalar context? They don't. They return, in true Perl tradition, a list in list context, and they return "some useful value" in scalar context, which needn't even be related to that list. As grep and map in list context do not necessarily return the same number of items as they have arguments, it makes sense to make them return the count of items they would have returned. For grep that makes it easy for us to count the number of matches, very useful indeed.

But what's your excuse for sort? You could just as well expect it to behave as the comma operator, returning a list in list context (as usual), and the value of the last item of that list in scalar context. So sort in scalar context would then return the maximum value. Makes sense. ;-)