New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sort in scalar context is undefined #12803
Comments
From @demerphqsort is documented as having undefined behavior in scalar context. This is really annoying as code like: return keys %hash; cannot be safely changed to return sort keys %hash; as if it is used in scalar context it wont return the number of items my @temporary= sort keys %hash; IMO this is silly. Why shouldnt sort() become a no-op in this case and This bug affects all modern perls as far as I know, including perl Cheers, Summary of my perl5 (revision 5 version 17 subversion 9) configuration: Characteristics of this binary (from libperl): -- |
From @tseeOn 02/20/2013 07:06 AM, yves orton (via RT) wrote:
But this is just a documentation bug, right? Using some random blead from after 5.17.7 and before 5.17.8: perl -e 'use warnings; use strict; sub foo {my %h = 1..10; return sort This does not warn. But this does: perl -e 'use warnings; use strict; sort qw(1..10); my $x = sort qw(1..10)' Is the bug report here specifically about documenting (and implementing) If so, I guess you could modify the docs and then do an op_null() in the --Steffen PS: Yes, sort{} blocks could have side effects. That's already undefined |
The RT System itself - Status changed from 'new' to 'open' |
From @demerphqOn 20 February 2013 07:49, Steffen Mueller <smueller@cpan.org> wrote:
No. I think that sort having undefined behavior in *scalar* context is a bug. It should return the number of items in the list just like keys, or Why should sort be different?
My point is the following is stupid: $ ./perl -Ilib -le'use warnings; use strict; sub foo {my %h = 1..10; Why should it return the most useless possible result of undef? Why
Please drink some coffee and reread my OP :-). I said *scalar* context. The behavior of sort in void context is an cheers, -- |
From @Smylersyves orton writes:
That's a reasonable argument for sort in scalar context being a no-op. However, returning the number of items in the list only serves as a return localtime; into: return sort localtime; So maybe a better no-op behaviour would be for sort in scalar context to In your example that would put keys in scalar context, which would do Cheers Smylers |
From @demerphqOn 20 February 2013 12:16, Smylers <Smylers@stripey.com> wrote:
I like that idea. If its doable then I think its worth doing. Yves -- |
From @tamiasOn Wed, Feb 20, 2013 at 11:16:19AM +0000, Smylers wrote:
Note that under that implementation, C<< scalar sort(4, 3, 2, 1) >> would Ronald |
From Eirik-Berg.Hanssen@allverden.noOn Wed, Feb 20, 2013 at 10:17 PM, Ronald J Kimball <rjk@tamias.net> wrote:
... which is exactly what it would return without the sort, and no more More generally: For the case when a C<< return EXPR >> is amended to a C<< return sort That sounds like a good thing. The current undef seems remarkably useless – even as a usage error But I guess it's better to keep the current warning (if not necessarily Eirik |
From @xdgI would prefer it to act exactly like map would, since it's a list Having it force scalar context on the input is a bad idea: return sort $obj->method(); What if method uses wantarray to determine if a list or single value While I'm fine with it not actually bothering to sort in scalar David |
From @demerphqOn 21 February 2013 00:00, David Golden <xdg@xdg.me> wrote:
I think we could warn if sort is called in scalar context in block form. Yves |
From @xdgOn Thu, Feb 21, 2013 at 2:47 AM, demerphq <demerphq@gmail.com> wrote:
Why? If I'm offering a list of values in response to a function call, E.g. I have a module that does "return sort { ... } stuff()" -- having If we're really concerned about it, we shouldn't optimize away the But I don't think we should be that concerned about it. A sort block David -- |
From @b2gillsOn Thu, Feb 21, 2013 at 10:47 AM, David Golden <xdg@xdg.me> wrote:
I totally agree with David. I don't see why these aren't (largely) equivalent $x = sort @y; I think the first one should be optimized to just: $x = @y; Then by extension these should work the same: sub x{ If someone needs the side effects of calling sort they should sub x{ # Or sub x{ return sort @_ } # my $x = x(); # say scalar( x() ); (Oddly enough these are also work-arounds for the current situation) |
From @bulk88Brad Gilbert wrote:
I think this optimization is useful. Especially for less than perfectly |
From @b2gillsOn Thu, Feb 21, 2013 at 12:51 PM, bulk88 <bulk88@hotmail.com> wrote:
Actually the way it currently works is more like sub sort(...){ Which should be slightly faster than what I am vying for: sub sort(...){ So it is not actually speeding up old code. Any code that is successfully working around the current behaviour |
From @demerphqOn 20 February 2013 07:06, yves orton <perlbug-followup@perl.org> wrote:
So far the options proposed seem to be: 1) return the number of items For me: Either of the 1) or 2) make sense to me. I lean a little towards 2) as return @array; and return keys %hash; and return grep { /pat/ } (LIST); and return map { "x" . $_ } (LIST); all return the same thing in list and scalar context. I am less concerned that return $x, $y, $z; behave the same in list and scalar context, so I am fine with going The third option is the most surprising, and IMO the least useful as Yves -- |
From @b2gillsOn Thu, Feb 21, 2013 at 2:20 PM, demerphq <demerphq@gmail.com> wrote:
My recommendation is 1) I think it would be better if it were 1) since it $x = sort qw" d a b c "; 1) $x == 4 2) $x eq 'c' # <= WHAT??!! 3) $x eq 'a' With 2) it would be impossible to implement a Since the return value depends on whether it is given a list, I can see where 2) would be easier to optimize I do see some appeal to implementing 3) $ perl -E'say scalar keys %::' So then I can only recommend 1) I can also see this generating a warning. $x = sort qw' d a b c '; Since you could write it more specifically. 1) These should work without a warning: $x = sub{ sort qw' d a b c ' }->(); I also think they should return the same thing 1) or 3) My recommendation is 1) return the number of items Far second choice is 3) return minimum. I am completely against 2), as it's not even self-consistent. |
From @demerphqOn 22 February 2013 01:07, Gisle Aas <gisle@activestate.com> wrote:
But then we have the optimization for exactly one case, instead of a Also consider the complexity involved in making this work: my $min= sort { $b->[0] cmp $a->[0] || $a->[1] <=> $b->[1] } @array; We cant simply scan the list to find the minimum, we will have to my $min= (sort { $b->[0] cmp $a->[0] || $a->[1] <=> $b->[1] } @array)[0]; would do. So IMO this is not the right choice. It is not huffman To me, making sort in scalar context do something that can already be Yves -- |
From @demerphqOn 21 February 2013 21:20, demerphq <demerphq@gmail.com> wrote:
I have pushed a patch to implement this on the yves/scalar_sort topic The commit currently is: commit 59cf203 make sort in scalar context return the number of elements This allows one to add a "sort" to a routine that returned an array, -- |
From @xdgOn Fri, Feb 22, 2013 at 8:13 AM, demerphq <demerphq@gmail.com> wrote:
+1 I think sort is most similar to map and grep in that they are all list -- |
From @tamiasOn Fri, Feb 22, 2013 at 08:36:41AM +0100, demerphq wrote:
Of course we can simply scan the list to find the minimum. my $min = $array[0]; for my Ronald |
From @demerphqOn 22 February 2013 17:29, Ronald J Kimball <rjk@tamias.net> wrote:
Yeah, true, still, its not "simply scanning for the minimum" anymore is it? Yves -- |
From j.imrie1@virginmedia.comOn 22/02/2013 16:43, demerphq wrote:
use List::Util qw(min); |
From @rjbs* demerphq <demerphq@gmail.com> [2013-02-22T08:13:36]
I am at least tentatively in favor of this, if not just plain ol' in favor. ...but I'd like it to wait for 5.19.0 to open. We've already got a number of Thanks for working on this! -- |
From @druud62On 2013-02-22 23:34, John Imrie wrote:
John, I think that you missed the overriding of 'min'. List::Util::min returns the lowest numerical value. -- $ perl -MList::Util=min,reduce -wle ' |
From j.imrie1@virginmedia.comOn 24/02/2013 12:11, Dr.Ruud wrote:
Argh!! Yes you are right. Sorry We need a string version of min then. John |
From @SmylersJohn Imrie writes:
List::Util::minstr Smylers |
From @druud62On 2013-02-24 14:22, John Imrie wrote:
Its 'minstr' can not cut this cake either. Check the reduce-example in my previous message. -- |
From @janduboisOn Thu, Feb 21, 2013 at 11:36 PM, demerphq <demerphq@gmail.com> wrote:
I don't understand the "dangerous" part of your comment, unless you mean: The only dangerous part is assuming that a function normally returning a Beyond that, both the "return the number" and "return the first" is already One thing slightly more interesting about the first element case is that we my $max = reverse sort @list; that could work in linear time. Cheers, |
From @demerphqOn 25 February 2013 19:57, Jan Dubois <jand@activestate.com> wrote:
Well I suppose this is sufficiently a matter of taste that probably I sub list_of_keys { if (list_of_keys()) { that adding "sort" to the return of list_of_keys(): sub list_of_keys { wouldn't break the code that does if (list_of_keys()) { ... }. Returning the max/min means that every place that I want to do: return sort thingee(); I have to do return wantarray ? sort thingee() : thingee(); which is just PITA and poorly huffman encoded.
That's like saying the only dangerous part of a lawnmower is the Whereas I only rarely want to do something like find the minimum of an
Return the first meaning return the min/max? Or return the first item
Except that would break the documented interface of reverse, so no we I think a much much more interesting approach for this is to make list IOW I should be able to get an optized solution to something like this: my ($x,$y,$z)= sort { ... } @big_array; and have perl do something clever so that it doesnt sort the full list Which btw would allow this: my ($x,$y,$z)= reverse sort { ... } @big_array; Which does what you want and doesn't require we change scalar behavior cheers, -- |
From @janduboisOn Mon, Feb 25, 2013 at 11:19 AM, demerphq <demerphq@gmail.com> wrote:
No, I see what you mean. Except that it doesn't work that way right now. Which is one of my concerns with this: returning the number of elements in my $count = sort keys %hash; The "sort" is essentially a no-op, except for the special case inside the
I thought you could also use return my @list = sort thingee(); but I now realize that this will not optimize the sort() when called in
For me it is a wash, I think I find both situations equally likely.
Both
Darn. Now this makes the "return the first" option less appealing...
Yes. I suspect doing this just for N=1 covers the vast majority of use
I definitely wouldn't want to change the defined reverse() behavior; I was So I think I agree with your proposal. :) Cheers, |
From @davidnicolOn Sun, Feb 24, 2013 at 7:38 AM, Smylers <Smylers@stripey.com> wrote:
Then there's an an alternative to list utils, which will give you the n http://search.cpan.org/~davidnico/Tie-Quicksort-Lazy-0.04/lib/Tie/Quicksort/Lazy.pm for my would become use Tie::Quicksort::Lazy; Anyway. Everytime there's a new cat we figure out a new way to skin it. Having once, on something of a dare, submitted a patch to CORE::sort that Peace. -- |
Migrated from rt.perl.org#116877 (status was 'open')
Searchable as RT116877$
The text was updated successfully, but these errors were encountered: