Why does sort return undef in scalar context ?

R

Randal L. Schwartz

Rainer> If sort would return pi in scalar context, that would also be useful
Rainer> in some specific situations (as would any other value). But there is
Rainer> no more relation between the function of sort (return a specific
Rainer> permutation of its arguments) and 3.1415... than there is between
Rainer> permuting arguments and counting arguments.

I even addressed this point beginning in one of the early editions of
"Learning Perl", adding that being undefined, there was nothing
preventing sort in a scalar context from invoking "nethack". I do
recall a patch some number of years later (in jest) on P5P to do exactly
that. :)

The only serious proposals for scalar sort that I've seen are (a) a
boolean to say "yes, this list is already sorted", or perhaps (b) a
value between 0 and 1 as to "how sorted" the list already was, based on
a single pass of the sort comparator against adjacent elements. Not
sure when I would have used either one though.

if (sort { $a <=> $b } @list) { # this is already numerically sorted
...
}

print "Just another Perl hacker,"; # the original
 
W

Willem

Tad McClellan wrote:
)> Jim Gibson wrote:
)
)> ) Any problems with maintenance of your code is more likely going to be
)> ) due to poor design.
)>
)> Why did you feel the need to throw in a gratuitous ad hominem attack ?
)
) It is neither gratuitous nor ad hominem.
)
) It is entirely possible, whether you agree with it or not,
) that it *is* a poor design.

That *what* is ?
Reread the statement. There is no 'it' being referred to.

) Offering an opinion (even if different) is not "gratuitous".
)
) He didn't say that _you_ were bad, he said that your _code_ was bad,
) so, not "ad hominem" either...
)
) A criticism of your code is not a criticism of you.

You snipped the part that this was a response to. It was not a piece of
code. It was a side remark about the merits of different workarounds in
regards to maintenance.

Hell, I didn't even post any real code, just some example snippets,
so there is no code to criticize.

So I stand by my opinion that it was a gratuitous ad hominem attack.

)> You do realise that this very comment caused me to dismiss you as a viable
)> discussion partner, right ?
)
) You do realise that being unable to acknowledge that an opinion
) other than your own deserves to exist has caused me to dismiss you
) as a viable discussion partner, right?

The 'opinion other than your own' was that I, apparently, use poor code
design. Which was based on nothing.

You are correct that it is an opinion. If I were to call you a jerk and an
asshole, that would be an opinion as well. The naked fact that something
is an opinion does not make it okay to spew it, nor does it negate the fact
that it is an attack.

)> ) I have another suggestion for what sort could return in scalar context:
)> )
)> ) true if the array is already in sort, undef otherwise.
)>
)> Classic perl4 thinking: Let's overload it to do something related,
)> but different!
)
) Errr, having sort() return the number of elements is overloading
) it to do something *not related* but different.

I have already explained why this is false.
Simply restating it is not going to make it any less false.

Having sort() return the number of elements is logical and consistent.
See the arguments I presented crossthread, none of which have been refuted
(only blatantly dismissed).

To hammer in the last nail: It works exactly that way in Perl6.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
S

sreservoir

Rainer Weikusat wrote:
) There is actually at least on similar operation in Perl, namely,
) reverse, which also returns a permutation of the input list. In scalar
) context, it will concatenate whatever the elements on the list
) stringify to and return a reversed string. This seems a little
) arbitrary and not really useful in many cases, eg,
)
) [rw@tear]~ $perl -de 0
)
) Loading DB routines from perl5db.pl version 1.3
) Editor support available.
)
) Enter h or `h h' for help, or `man perldebug' for more help.
)
) main::(-e:1): 0
) DB<1> print scalar(reverse(\$a, \$b, \$c))
) )0efcb38x0(RALACS)0ffcb38x0(RALACS)040db38x0(RALACS

Wow that's pretty useless!

But in the simplest case (a single string argument), the behavior of scalar
reverse is perfectly logical:

$x = "foobar";
$y = reverse $x;
say $y;

If a language built for text processing didn't have a reverse-string
operation, that would be weird.

A 'reverse string' operation which also works in list context had
nevertheless been a better idea, cf

DB<16> p map { reverse $_; } qw(ab bc de)
abbcde

% perl -E'say for map { ~~reverse $_; } qw(ab bc de)'
ba
cb
ed

when you want scalar context, just ask for it.
 
R

Rainer Weikusat

sreservoir said:
(e-mail address removed) (Alan Curry) writes:
[...]
A 'reverse string' operation which also works in list context had
nevertheless been a better idea, cf

DB<16> p map { reverse $_; } qw(ab bc de)
abbcde

% perl -E'say for map { ~~reverse $_; } qw(ab bc de)'
ba
cb
ed

when you want scalar context, just ask for it.

I didn't ask. Does this perhaps tell something to you
 
S

sreservoir

sreservoir said:
(e-mail address removed) (Alan Curry) writes:
[...]
But in the simplest case (a single string argument), the behavior of scalar
reverse is perfectly logical:

$x = "foobar";
$y = reverse $x;
say $y;

If a language built for text processing didn't have a reverse-string
operation, that would be weird.

A 'reverse string' operation which also works in list context had
nevertheless been a better idea, cf

DB<16> p map { reverse $_; } qw(ab bc de)
abbcde

% perl -E'say for map { ~~reverse $_; } qw(ab bc de)'
ba
cb
ed

when you want scalar context, just ask for it.

I didn't ask. Does this perhaps tell something to you

it could be easier if scalar and list reverse were different, sure,
but as it is, if it doesn't work properly in list context with only
one argument, then you add more unnecessary complication than if it
simply required you to ask for scalar context when you want it.
 
W

Willem

sreservoir wrote:
) On 08/31/2011 10:00 AM, Willem wrote:
)> [snip]
)
) in short, you remain committed to your opinion, and it will not change.

In the absence of convincing counter arguments, or even refutations of the
arguments I presented, why should I not remain convinced of my opinion ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
S

sln

(e-mail address removed) wrote:
) I don't know why this is the case, but you should fix it up in the
) function that wraps the return of sort().

My apologies.
I hadn't made clear that I was well aware how to work around this issue.

No apologies are necessary. Neither were your confusing examples.
A simple fyi: print 'undef' if !defined sort();
for those that don't already know. Anything more is meaningless.

-sln
 
P

Peter J. Holzer

I have another suggestion for what sort could return in scalar context:

true if the array is already in sort, undef otherwise.

if (sort @foo) {
...
}


die "..." unless sort @bar;

Yes, makes sense.

hp
 
R

Rainer Weikusat

Willem said:
Rainer Weikusat wrote:
) I usually prefer the term 'subroutine' because it emphasizes that this
) is not a function in the mathematical sense:

You should be worrying more about the definition of 'function' in the
computer sciences, because that's much more closely related to
programming.

People who plunder 'alien sciences' for terms should be worried about
the misunderstandings and -conceptions which result when other people
encounter a seemingly familiar term that actually refers to something
completely different. Eg, probably, the reason why people write C code like
this:

int larger_length(char const *s0, char const *s1)
{
if (strlen(s0) > strlen(s1)) return strlen(s0);
else if (strlen(s1) > strlen(s0) return strlen(s1);
return -1;
}

is that they lack the intuitive understanding of the difference
between what C calls 'a function' (a subroutine executing a particular
algorithm) and a mathematical function (which doesn't "do" anything
but defines a mapping from elements of one set to elements of a second
set).

But that was just supposed to demonstrate that use of the term
'subroutine' doesn't indicate anything about a relation to Perl4 (and
not even to Perl, although these things are called 'subroutines' in
the Perl documentation).

[...]
)> The deliberate choice was made because the language designer didn't see any
)> use cases. If there *is* a use case, then that (not seeing a use case) is
)> quite literally an oversight.
)
) If sort would return pi in scalar context, that would also be useful
) in some specific situations (as would any other value). But there is
) no more relation between the function of sort (return a specific
) permutation of its arguments) and 3.1415... than there is between
) permuting arguments and counting arguments.

Yes there is. If you view sort in a functional-programming way, then
it is: 'array -> sort -> array'. Using an array as a scalar gives
the number of elements. Therefore using the result of sort as a scalar
should give the number of elements as well. Simple logic.

Evaluating an array in a scalar context returns the number of
arguments in the array. Leaving the minor impreciseness aside, your
argument falls down at two levels:

1. The Perl sort isn't defined based on arrays but on lists and
evaluating a list in a scalar context returns the last member of the
list. Consequently, if sort was context-agnostic, it would return the
largest value on the input list, not the number of elements.

2. Since sort isn't context agnostic, it's behaviour in scalar
context is whatever someone considered sensible in this
situation. 'Counting elements' and 'permuting elements' are still two
completely different things. Consequently, there is no reason why a
function supposed to generate a permutation should suddenly return a
count in a different context. Especially considering that this count
is already known to the caller because it is the number of arguments
passed to the function.
Compare, for example, a completely OO language, where there is a 'list'
class. To get the perl behaviour of number-of-elements, you would simply
implement a convert-to-integer member function, which the language then
automatically calls whenever it has a 'list' but wants an 'integer'.

I certainly wouldn't do that but implement a 'count items on list'
subroutine instead.
Now, there is a sort function which takes a 'list' object and returns a
'list' object. It is left as an exercise to figure out what would happen
if you were to use sort() but want the result as an integer.

PS: As far as I can tell from the online docs, it works like this
in Perl6 as well.

Then, you should perhaps user Perl6 and not Perl5 ...
 
R

Rainer Weikusat

sreservoir said:
sreservoir said:
On 08/31/2011 07:44 AM, Rainer Weikusat wrote:
(e-mail address removed) (Alan Curry) writes:
[...]

But in the simplest case (a single string argument), the behavior of scalar
reverse is perfectly logical:

$x = "foobar";
$y = reverse $x;
say $y;

If a language built for text processing didn't have a reverse-string
operation, that would be weird.

A 'reverse string' operation which also works in list context had
nevertheless been a better idea, cf

DB<16> p map { reverse $_; } qw(ab bc de)
abbcde

% perl -E'say for map { ~~reverse $_; } qw(ab bc de)'
ba
cb
ed

when you want scalar context, just ask for it.

I didn't ask. Does this perhaps tell something to you

it could be easier if scalar and list reverse were different, sure,
but as it is, if it doesn't work properly in list context with only
one argument, then you add more unnecessary complication than if it
simply required you to ask for scalar context when you want it.

I did not ask a question a la "Oh my god! I need to reverse the items
on this list and cannot figure out how !! PLEASE HEEELP MEEEEE !!!"
because I wasn't looking for the answer to this question.
 
A

Alan Curry

The only serious proposals for scalar sort that I've seen are (a) a
boolean to say "yes, this list is already sorted", or perhaps (b) a
value between 0 and 1 as to "how sorted" the list already was, based on
a single pass of the sort comparator against adjacent elements. Not
sure when I would have used either one though.

In void context:

sort @foo;

the obvious intent is to sort the array in place. It could even apply to
arbitrary lists:

sort $x, $y; # Equivalent to: ($x,$y) = ($y,$x) if $x gt $y

Apply the same rule in non-void scalar context, but add: returns true if the
list was changed.

if(sort $x, $y) {
# redisplay the user interface elements that depend on $x and/or $y
}

Trying to decide on a scale of 0 to 1 "how serious" I am...
 
D

Dr.Ruud

Randal L. Schwartz:

In void context:

sort @foo;

the obvious intent is to sort the array in place. It could even apply to
arbitrary lists:

sort $x, $y; # Equivalent to: ($x,$y) = ($y,$x) if $x gt $y

Apply the same rule in non-void scalar context, but add: returns true if the
list was changed.

if(sort $x, $y) {
# redisplay the user interface elements that depend on $x and/or $y
}

Trying to decide on a scale of 0 to 1 "how serious" I am...

One obvious thing to return in scalar context, is the last element of
the sorted list.

That can also be done by: @foo ? (sort {...} @foo)[-1] : undef.

It can be used to implement max() and min(), but I have not met similar
code much, so I consider it a waste to make it so.
 
T

Ted Zlatanov

On Wed, 31 Aug 2011 05:53:25 -0700 (e-mail address removed) (Randal L. Schwartz) wrote:

RLS> The only serious proposals for scalar sort that I've seen are (a) a
RLS> boolean to say "yes, this list is already sorted", or perhaps (b) a
RLS> value between 0 and 1 as to "how sorted" the list already was, based on
RLS> a single pass of the sort comparator against adjacent elements. Not
RLS> sure when I would have used either one though.

RLS> if (sort { $a <=> $b } @list) { # this is already numerically sorted
RLS> ...
RLS> }

I don't like it, because it differentiates between

$x = scalar sort @y;

and

@x = sort @y;
$x = scalar @x;

I don't see any practical gain from the first one, so why break
transitivity? To add yet more syntactic sugar we don't need, perhaps
good for Perl golfing but discouraged in production code?

Much better would be to provide a sorted-p predicate that can be used
generally without forcing a scalar context, and with a clear purpose.
That would actually be useful and can't be done as easily or as
efficiently in pure Perl as it would be on the interpreter side.

Fractional degrees of sort order are perhaps useful but they are much
more expensive to calculate.

Ted
 
R

Rainer Weikusat

[...]
) Errr, having sort() return the number of elements is overloading
) it to do something *not related* but different.

I have already explained why this is false.
Simply restating it is not going to make it any less false.

Having sort() return the number of elements is logical and
consistent. See the arguments I presented crossthread, none of which
have been refuted (only blatantly dismissed).

You claimed that the sort routine would take an array as input and
return an array as output. This is wrong. Sort takes a list as input
and returns a list as ouput. Evaluating a list in scalar context
returns the last element of the list, NOT the number of members.

Besides being wrong, this is also besides the point: You expect that
sort behaves as if it was context-agnostic but it isn't: The behaviour
of sort in a scalar context is whatever the person who implemented it
considered sensible. And it is not sensible to expect a subroutine
whose purpose is to create a permutation of its inputs to count these
inputs instead. That's a completely arbitrary descisions which has no
inherent relation to the purpose of the routine: It's just based on
your original misassumption that sort would return an array and your
desire that this sort-returning-an-array which doesn't exist should
also be context-agnostic.
To hammer in the last nail: It works exactly that way in Perl6.

So fucking what?
 
R

Rainer Weikusat

Rainer Weikusat said:
[...]
) Errr, having sort() return the number of elements is overloading
) it to do something *not related* but different.

I have already explained why this is false.
Simply restating it is not going to make it any less false.

Having sort() return the number of elements is logical and
consistent. See the arguments I presented crossthread, none of which
have been refuted (only blatantly dismissed).

You claimed that the sort routine would take an array as input and
return an array as output. This is wrong. Sort takes a list as input
and returns a list as ouput.

Addition: Provided that sort got a list as input, the implementation
actually sorts (as far as I understood it from a fairly cursory look
at it) the contents of the call stack in place and 'returns' the
sorted stack contents as output list. The closest simple approxmiation
to that in Perl (AFAIK) looks like this:

sub agnostic_sort
{
return eval('('.join(',', sort(@_)).')');
}
 
W

Willem

Rainer Weikusat wrote:
)
) [...]
)
)> ) Errr, having sort() return the number of elements is overloading
)> ) it to do something *not related* but different.
)>
)> I have already explained why this is false.
)> Simply restating it is not going to make it any less false.
)>
)> Having sort() return the number of elements is logical and
)> consistent. See the arguments I presented crossthread, none of which
)> have been refuted (only blatantly dismissed).
)
) You claimed that the sort routine would take an array as input and
) return an array as output. This is wrong.

I claimed that the sort routine *conceptually* is a function from arrays
to arrays. This is correct.

) Sort takes a list as input
) and returns a list as ouput. Evaluating a list in scalar context
) returns the last element of the list, NOT the number of members.

Can you show a piece of perl code that 'evaluates a list in scalar
context', but without using a comma to build the list?

If not, then one could just as well say that the comma operator returns
the concatenation of its operands in list context, and the rightmost
operand in scalar context, and the whole concept of 'evaluating a list
in scalar context' can be dropped altogether.

As you argue below, this is irrelevant because functions are aware
of the context they are in. Several functions that return lists
will return the list count in scalar context. I don't know a single
one that will return the last item of the list.

All this is evidence that it is quite sensible to expect a function
that returns a list, to return an item count in scalar context.

) Besides being wrong, this is also besides the point: You expect that
) sort behaves as if it was context-agnostic but it isn't:

I am trying to argue that sort *should* behave as if it was
context-agnostic, because that is the most sensible option.
The person implementing it did not find *any* sensible scalar
to return, and therefore decided to return nothing.

) of sort in a scalar context is whatever the person who implemented it
) considered sensible. And it is not sensible to expect a subroutine
) whose purpose is to create a permutation of its inputs to count these
) inputs instead.

I am trying to argue that it *is* sensible to expect that. Simply claiming
the opposite of that fact does nothing to further the discussion.

To reiterate: I am trying to have a theoretical discussion on the merits of
having sort return an item count in scalar context.

)> To hammer in the last nail: It works exactly that way in Perl6.
)
) So fucking what?

Apparently nothing to people who are stuck programming in one language.
Those of us who use multiple languages have higher expectations.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Rainer Weikusat

Willem said:
Rainer Weikusat wrote:
)
) [...]
)
)> ) Errr, having sort() return the number of elements is overloading
)> ) it to do something *not related* but different.
)>
)> I have already explained why this is false.
)> Simply restating it is not going to make it any less false.
)>
)> Having sort() return the number of elements is logical and
)> consistent. See the arguments I presented crossthread, none of which
)> have been refuted (only blatantly dismissed).
)
) You claimed that the sort routine would take an array as input and
) return an array as output. This is wrong.

I claimed that the sort routine *conceptually* is a function from arrays
to arrays. This is correct.

The perl sort is defined based on lists.
) Sort takes a list as input) and returns a list as
ouput. Evaluating a list in scalar context) returns the last element
of the list, NOT the number of members.

Can you show a piece of perl code that 'evaluates a list in scalar
context', but without using a comma to build the list?

If not, then one could just as well say that the comma operator returns
the concatenation of its operands in list context, and the rightmost
operand in scalar context, and the whole concept of 'evaluating a list
in scalar context' can be dropped altogether.

No, it can't, because, again, the 'theoretical model' you like to use
here is in conflict with the Perl documentation:

List value constructors
List values are denoted by separating individual values by
commas (and enclosing the list in parentheses where precedence
requires it):

(LIST)

In a context not requiring a list value, the value of what
appears to be a list literal is simply the value of the final
element, as with the C comma operator. For example,

@foo = ('cc', '-E', $bar);

assigns the entire list value to array @foo, but

$foo = ('cc', '-E', $bar);

assigns the value of variable $bar to the scalar variable $foo.
[perldata(1)]

As you argue below, this is irrelevant because functions are aware
of the context they are in. Several functions that return lists
will return the list count in scalar context.

Several functions which *happen* to generate an output list from an
input list where the number of elements on the output list cannot be
predicted without performing the operation on the input list return
this number when used in scalar context. The sort operation does not
have this property: Since it permutes the elements from the input
list, the number of elements of the output list is identical to the
number of elements on the input list.

[...]
) Besides being wrong, this is also besides the point: You expect that
) sort behaves as if it was context-agnostic but it isn't:

I am trying to argue that sort *should* behave as if it was
context-agnostic, because that is the most sensible option.

That's the most sensible option FOR YOU because you happen to have
written some code based on the assumption that sort would behave in
this way despite it actually doesn't.
 
D

David Canzi

Willem said:
Jim Gibson wrote:
) I do not think that your use case is valid. It is silly to sort an
) array when all you want is the number of elements in the array. The
) subroutine that you wrote to do this is not a good example of good
) design. That could be why nobody on this groups agrees that what you
) want is desirable.

Well, the fact that you call it a subroutine, and not a function, clearly
shows that you're stuck in the old perl4 days.

Script started on Thu Sep 1 16:19:13 2011
dmcanzi@tribulation $
dmcanzi@tribulation $ perl -e 'print $^V, "\n"'
v5.10.1
dmcanzi@tribulation $
dmcanzi@tribulation $ man perlsub | head
PERLSUB(1) Perl Programmers Reference Guide
PERLSUB(1)



NAME
perlsub - Perl subroutines

SYNOPSIS
To declare subroutines:

dmcanzi@tribulation $
dmcanzi@tribulation $ exit

Script done on Thu Sep 1 16:19:32 2011
 
W

Willem

Rainer Weikusat wrote:
)> Rainer Weikusat wrote:
)> I claimed that the sort routine *conceptually* is a function from arrays
)> to arrays. This is correct.
)
) The perl sort is defined based on lists.

Yes, so you reiterated several times.
What does that have to do with conceptual interpretations ?

)> ) Sort takes a list as input) and returns a list as
)> ouput. Evaluating a list in scalar context) returns the last element
)> of the list, NOT the number of members.
)>
)> Can you show a piece of perl code that 'evaluates a list in scalar
)> context', but without using a comma to build the list?
)>
)> If not, then one could just as well say that the comma operator returns
)> the concatenation of its operands in list context, and the rightmost
)> operand in scalar context, and the whole concept of 'evaluating a list
)> in scalar context' can be dropped altogether.
)
) No, it can't, because, again, the 'theoretical model' you like to use
) here is in conflict with the Perl documentation:
)
) List value constructors
) List values are denoted by separating individual values by
) commas (and enclosing the list in parentheses where precedence
) requires it):
)
) (LIST)
)
) In a context not requiring a list value, the value of what
) appears to be a list literal is simply the value of the final
) element, as with the C comma operator. For example,
)
) @foo = ('cc', '-E', $bar);
)
) assigns the entire list value to array @foo, but
)
) $foo = ('cc', '-E', $bar);
)
) assigns the value of variable $bar to the scalar variable $foo.
) [perldata(1)]

I'm not seeing "a list evaluated in scalar context returns the last
element". What you quoted above supports my intepretation, that
'what appears to be a list' (i.e. values separated by commas), when
in scalar context, is *not* a list, but the last value.

For example, what is the result of the following Perl code:
my @a1 = qw(a b c); my @a2 = qw(d e f); my $s = @a1,@a2; say $s;
(Without looking it up).

So, as it appears, the documentation does not back up your claim
that 'evaluating a list in scalar context returns the last element'.
Instead, 'the operator that creates a list in list context, returns
the last element in scalar context'. Which is a special case to
accomodate the expectations of C programmers about the comma operator.

In other words: in that case, there is a *good reason* why the
comma-operator is not context-agnostic, and *instead* returns the
last element. In case of sort(), there is no good reason not to
be context-agnostic, and return the argument count.

)> As you argue below, this is irrelevant because functions are aware
)> of the context they are in. Several functions that return lists
)> will return the list count in scalar context.
)
) Several functions which *happen* to generate an output list from an
) input list where the number of elements on the output list cannot be
) predicted without performing the operation on the input list return
) this number when used in scalar context. The sort operation does not
) have this property: Since it permutes the elements from the input
) list, the number of elements of the output list is identical to the
) number of elements on the input list.

Why did you snip the part where I said that *no* function that returns
a list returns the last item in scalar context ? It was the juxtaposition
of the two which formed my argument, and by snipping that part, you
effectively changed my argument into something that you could attack.

)
) [...]
)
)> ) Besides being wrong, this is also besides the point: You expect that
)> ) sort behaves as if it was context-agnostic but it isn't:
)>
)> I am trying to argue that sort *should* behave as if it was
)> context-agnostic, because that is the most sensible option.
)
) That's the most sensible option FOR YOU because you happen to have
) written some code based on the assumption that sort would behave in
) this way despite it actually doesn't.

Yes. That's what I just said. Does it not occur to you that when somebody
expects something to happen a certain way, they have good reasons for that?
And in case you had missed it, this whole thread I have been presenting the
very reasons I have for these expectations.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 

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,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top