Why does sort return undef in scalar context ?

A

Alan Curry

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).

That's a bad demonstration, since it doesn't really show the "last value"
result of the comma operator. It seems to be showing that you think $s got
the size of @a2 because @a2 is the last operand of the comma operator.

What actually happens, since assignment has higher precedence,
is $s=@a1 and a useless evaluation of @a2 in void context.

Make @a1 and @a2 different lengths and you'll see the difference.
 
J

John W. Krahn

Rainer 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. Evaluating a list in scalar context
returns the last element of the list, NOT the number of members.

Yes, but, sort is not a list, it is an operator. Operators can return
completely different things depending on context. For example:
localtime or getpwnam.



John
 
W

Willem

Alan Curry wrote:
) In article <[email protected]>,
)>
)>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).
)
) That's a bad demonstration, since it doesn't really show the "last value"
) result of the comma operator. It seems to be showing that you think $s got
) the size of @a2 because @a2 is the last operand of the comma operator.
)
) What actually happens, since assignment has higher precedence,
) is $s=@a1 and a useless evaluation of @a2 in void context.
)
) Make @a1 and @a2 different lengths and you'll see the difference.

You are quite correct! I should be more careful when making a point:

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

The answer being 4, of course.


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

Randal L. Schwartz

Ted> I don't like it, because it differentiates between

Ted> $x = scalar sort @y;

Ted> and

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

But that's not true in general.

You can't equate:

$x = <FOO>;

and

@x = <FOO>;
$x = scalar @x;

either. Please stop trying to say "the scalar value of a list is its
length". It's actually more often *not* true rather than true, as my
perlmonks post shows: http://www.perlmonks.org/?node_id=347416

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

Randal L. Schwartz

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

No, it's not logical, not consistent (see
http://www.perlmonks.org/?node_id=347416 for counter examples) and
completely utterly useless. Why not just look at the original list?
Why call "sort" in a scalar context merely to *count* elements?

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

Randal L. Schwartz

Willem> Why did you snip the part where I said that *no* function that returns
Willem> a list returns the last item in scalar context ?

How about "getpwnam", which returns the *third* item of the list in a
scalar context?

Perl HAS NO RULE about "converting a list to a scalar", only a bunch of
rules about functions that do one thing in a scalar context and another
in a list context. Do you understand yet?

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

Rainer Weikusat

Willem> Why did you snip the part where I said that *no* function that returns
Willem> a list returns the last item in scalar context ?

How about "getpwnam", which returns the *third* item of the list in a
scalar context?

Perl HAS NO RULE about "converting a list to a scalar", only a bunch of
rules about functions that do one thing in a scalar context and another
in a list context.

This doesn't seem to be true, it's just somewhat diffcult to
demonstrate because the Perl extension/ C interface needs to be used
to actually create something like 'a list which is evaluated in scalar
context' (although the Perl example I posted is functionally
equivalent).

Leading remark: This is my minium effort attempt to create a passthru
function which just returns its argument list. It doesn't crash perl
here, at least not immediately.

In order to be able to get anywhere here, it is first necessary to
have something which compiles a file with C source code such that it
will be compatible with perl. The following shellscript can be used
for that:

--------------
#!/bin/sh
#
# invoke C compiler in a 'suitable' way to compile xs code
#
# $Id: perlcc,v 1.4 2009-04-14 12:25:02 rw Exp $
#

PATH=/usr/local/bin:/bin:/usr/bin
export PATH

CC=`perl -V::cc: | tr -d "'"`
CC_DL=`perl -V::cccdlflags: | tr -d "'"`
CC_OPT=`perl -V::eek:ptimize: | tr -d "'"`
CFLAGS=`perl -MExtUtils::Embed -e ccopts`

$CC $CC_DL $CC_OPT $CFLAGS -c "$@"
--------------

Another script to turn the object code file produced by the first
script into a shared object suitable for being loaded into perl is
also required:

--------------
#!/bin/sh
#
# invoke linker in a 'suitable way' to create a shared object
# which can be loaded into perl
#
# $Id: perlld,v 1.2 2009-04-14 11:11:17 rw Exp $
#

PATH=/usr/local/bin:/bin:/usr/bin
export PATH

LD=`perl -V::ld: | tr -d "'"`
LD_DL_0=`perl -V::ccdlflags: | tr -d "'"`
LD_DL_1=`perl -V::lddlflags: | tr -d "'"`
LDFLAGS=`perl -MExtUtils::Embed -e ldopts`

$LD $LD_DL_0 $LD_DL_1 "$@" $LDFLAGS
--------------

NB: Both of these scripts are known to be working in 'Linux',
specifically, Debian and Ubuntu. Assuming these scripts have been put
into some directory in the PATH using suitable names (perlcc and
perlld are the names used by me) and made executable, a suitable 'xs'
source code file needs to be created:

---------------
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

MODULE = main

void nop(...)
PPCODE:
XSRETURN(items);
----------------

This needs to be turned into a shared object by executing the command
sequence

xsubpp a.xs >a.c
perlcc a.c
perlld -o a.so a.o

Provided this has been done a Perl script similar to the one included
below can be used to play with this function (the shared object is
supposed to be available as /tmp/a.so):

----------------
#!/usr/bin/perl
#

use DynaLoader;

my ($lib, $sym, @a);

$lib = DynaLoader::dl_load_file('/tmp/a.so');
$lib || die("failed to load");

$sym = DynaLoader::dl_find_symbol($lib, 'XS__nop');
$sym || die("didn't find nop symbol");
DynaLoader::dl_install_xsub('nop', $sym, '/tmp/a.so');

@a = nop(1, 2, 3, 5);
print(join(',', @a), "\n");
print(scalar(nop(1, 2, 3, 5)), "\n");
 
T

Ted Zlatanov

On Fri, 02 Sep 2011 08:49:45 -0700 (e-mail address removed) (Randal L. Schwartz) wrote:

RLS> Please stop trying to say "the scalar value of a list is its
RLS> length". It's actually more often *not* true rather than true, as
RLS> my perlmonks post shows: http://www.perlmonks.org/?node_id=347416

I did not try to say that and don't care at all what sort() returns in a
scalar context. I'm trying to dig something useful out of this
discussion. Unfortunately this thread seems to be mostly opinions about
the status quo and not about improving Perl.

Specifically there is *no way* to get the sort-p information (boolean or
float) without calling sort(), which is either stupid or wasteful
depending on your point of view. sort-p is useful on its own and
merging it with the sort() scalar context is what I don't want. So I
think it's worth putting it in Perl 5 or 6 if that's not too difficult.

Ted
 
R

Rainer Weikusat

Willem said:
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 ?

It means that you 'conceptual interpretation' is not correct:
'Conceptually', sort is an operation which takes an ordered set as
input and produces a permuted ordered set as output. One example of an
implementation of 'an ordered set' is the Perl datatype array. Another
example is what is called 'a list' in Perl -- some number of items
returned individually on the call/ return stack of a subroutine (or
passed to it in this way, although 'an array' is automatically created
for such an input list insofar the subroutine processing it has been
written in Perl) without a 'Perl array' being involved here. Another
example for an type of ordered set Perl doesn't support directly would
be a linked list (easily implementable in various ways). Another
ordered set supported by Perl would be an array slice.

In line with the style of argumentation you have used so far, your
statement is not only wrong but also, irrelevant: The perl sort
operation is defined in some specific way and this definition governs
its behaviour, not some theoretical generalization of 'sort operations
as such'.

[...]
) 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.
[...]

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.

'The operator that creates a list in list context' does not exist in
the text above, not even 'in scalar context'. What the text actually
says is that a 'list value constructor' (parenthesized expression with
indivual elements separated by commas) behaves as if it was a 'C comma
operator' in scalar context. Also, 'Perl list' can be created without
resorting to 'Perl list value constructors' meaning, your attempt at
defining the Perl concept 'list value constructor' away doesn't help:
A subroutine returning a list still effectively returns the last
element of that list when being called in scalar context (and no other
behaviour was implemented).
)> 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 ?

For the usual reasons, wrong and irrelevant: You don't know 'any function
which returns a list with these property' because you have
'cleverly' defined all subroutines written in Perl which return lists
via list value constructors as 'not really returning lists' and no
builtin function with said property exists. But

sub xyz { return ($_[0], $_[1]); }

is nevertheless such a subroutine. It is also possible to define the
'return a list composed of the arguments to the subroutine' subroutine
in Perl:

sub nop { return @_[0 .. $#_]; }

No list value constructor here (I haven't used slices for anything so
far, that's why I didn't think of this).

It is irrelevant because "I haven't observed X" is a statement about
the speaker and not about X.

[...]
)> 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.

The reason for this expection appears to be that you wrongly assumed
that 'sort' and the 'other operations returning a count in scalar
context' would belong to the same class because your were solely
looking at the input and output types in list context (takes a list,
returns a list) and were incorrectly assuming that 'list evaluated in
scalar context' would return the number of elements on the list: The
latter isn't true, the former misses an important difference between
'sort' and these 'other operations': The number of elements on the
output list is among the output information generated by these other
operations but it is not 'output information determined by sort'.
 
I

Ilya Zakharevich

either. Please stop trying to say "the scalar value of a list is its
length". It's actually more often *not* true rather than true, as my
perlmonks post shows: http://www.perlmonks.org/?node_id=347416

I suspect that the main heat of this discussion comes of from
(objectively confusing) clash of two DIFFERENT meanings of the word
LIST in discussions of Perl language.

a) LIST CONTEXT is the "opposite of scalar context";

b) and there is a LIST CONSTRUCTION (more or less comma operator).

The List construction may be put in two different (actually, three ;-)
contexts. It behaves differently in these contexts.

The list context appears only in (surprise!) one context. One
concludes that the behaviour of the list operator in scalar/list
context SHOULD NOT have a direct relation to how context switches the
meaning of the operator.

[This is pure logic, so not directly applicable to any real-life
situation ;-). However, an experiment with Perl docs at hand would
immediately confirm this.]

===== The principal question

If an operator is primarily designed to work in list context and
return X, what is the MOST LOGICAL thing to return in scalar context

===== The conventional answer

If there are SEVERAL things which may be all EXPECTED to be "logically
deducible" (possibly by DIFFERENT PEOPLE) - it was decided to be an
"unwanted situation". This is called "the principle of least surprise".

[Perl is not very "logical"; one needs to MEMORIZE a lot of stuff.
So if adding a certain USEFUL feature would force people to
memorize MORE, a benefit should be weighted against the added problem.]

Hope this helps,
Ilya
 
I

Ilya Zakharevich

In order to be able to get anywhere here, it is first necessary to
have something which compiles a file with C source code such that it
will be compatible with perl. The following shellscript can be used
for that:

IMO, the simplest way to experiment with C-to-Perl interface is

a) Use h2xs with appropriate options to generate an "empty" XSUB
module named FOO;

b) Add some XSUB directives to the end of FOO/FOO.xs and testing
code to FOO/t/FOO.t;

c) run
Makefile.PL
make test
in ./FOO.

(Or at least it was the simplest way 15 years ago. Is there a simpler
way now?)

Hope this helps,
Ilya
 
R

Randal L. Schwartz

Ilya> If there are SEVERAL things which may be all EXPECTED to be
Ilya> "logically deducible" (possibly by DIFFERENT PEOPLE) - it was
Ilya> decided to be an "unwanted situation". This is called "the
Ilya> principle of least surprise".

The actual answer is "whatever was most logical *to Larry*". Any other
answer isn't paying attention to history.

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

Willem

Ted Zlatanov wrote:
) Specifically there is *no way* to get the sort-p information (boolean or
) float) without calling sort(), which is either stupid or wasteful
) depending on your point of view. sort-p is useful on its own and
) merging it with the sort() scalar context is what I don't want. So I
) think it's worth putting it in Perl 5 or 6 if that's not too difficult.

Can't you create it with the reduce() function in List::Util ?


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

Ilya Zakharevich said:
IMO, the simplest way to experiment with C-to-Perl interface is

I'm not usually 'experimenting' with it, rather using it. The two
scripts I posted actually exist because I have a certain perl program
with some additional functions written in C which were too small and
specific to warrant putting them into a module (the same program also
uses several more elaborate extension modules written in C in order
to get access to various 'Linux interfaces' not otherwise available to
Perl code).
a) Use h2xs with appropriate options to generate an "empty" XSUB
module named FOO;

b) Add some XSUB directives to the end of FOO/FOO.xs and testing
code to FOO/t/FOO.t;

c) run
Makefile.PL
make test
in ./FOO.

(Or at least it was the simplest way 15 years ago. Is there a simpler
way now?)

Similar to these 'tiny functions', a single XS routine supposed to
demonstrate a specific property of perl hardly warrants creating a
complete extension module, especially not when it is supposed to be
part of a USENET posting as this would be rather unwieldy.
Hope this helps,

Thanks for the effort, but I wasn't joking when I wrote that I have
been using Perl in all kinds of professional and non-professional
context since about 1996. And this included creating more than half a
dozen XS modules (the program/ product I mentioned uses six of them),
hacking the mod_perl code in order to fix a couple of bugs/ annoyances
with that and adding some more features to DBD::pg (specifically,
complete support for the Postgres async interface, just done in a
way that I wouldn't want to publish it. But it works very nicely :).

I'm also really clueless about lots of things I haven't ever dealt
with so far.
 
K

Keith Thompson

Ilya> If there are SEVERAL things which may be all EXPECTED to be
Ilya> "logically deducible" (possibly by DIFFERENT PEOPLE) - it was
Ilya> decided to be an "unwanted situation". This is called "the
Ilya> principle of least surprise".

The actual answer is "whatever was most logical *to Larry*". Any other
answer isn't paying attention to history.

Sure, but if what was most logical to Larry happens to be consistent
with the principal that Ilya suggests, that's a good thing to know,
and a good rule of thumb for understanding why Perl is the way it is.
 
T

Ted Zlatanov

W> Ted Zlatanov wrote:
W> ) Specifically there is *no way* to get the sort-p information (boolean or
W> ) float) without calling sort(), which is either stupid or wasteful
W> ) depending on your point of view. sort-p is useful on its own and
W> ) merging it with the sort() scalar context is what I don't want. So I
W> ) think it's worth putting it in Perl 5 or 6 if that's not too difficult.

W> Can't you create it with the reduce() function in List::Util ?

I guess, but that's not much better because it still involves a lot of
Perl. I'm talking about a built-in at the C level that can amortize
what the interpreter knows about the list (e.g. inserting an element out
of order in a sorted list decreases the "sortedness" while inserting it
in the right place maintains it).

Ted
 
I

Ilya Zakharevich

Then your recollections of history are very different from mine.
Larry did not have much (practically any?) DIRECT influence on what
has happened after some moment - I think about 1996. (Of course, his
legacy had - in particular "this principle of least surprise".)

And Perl of today has very little resemblance to what it was in 1996.
(Enough to say that in 1996 most of my Perl programming time was spent
fighting bugs in Perl.)

I suspect the return value of sort() in scalar context was discussed
many times on p5p after that "cut-off". The current situation has very
little to do with Larry's decisions (although the end result may
coincide with what it was in Perl 4).

Sorry for my fuzzy memory,
Ilya
 
I

Ilya Zakharevich

Similar to these 'tiny functions', a single XS routine supposed to
demonstrate a specific property of perl hardly warrants creating a
complete extension module,

Why? Especially if creating this module takes one very short line of
code (and testing it another line), and your instructions take pages...
especially not when it is supposed to be
part of a USENET posting as this would be rather unwieldy.

I posted exactly because I found YOUR post unwieldy.

Hope this helps,
Ilya
 
R

Rainer Weikusat

Ilya Zakharevich said:
Why? Especially if creating this module takes one very short line of
code (and testing it another line), and your instructions take
pages...


I posted exactly because I found YOUR post unwieldy.

So, do you think I should have posted a tar-file of the directory tree
created by h2xs, complete with detailed documentation enabling
someone who doesn't already know his way about that to understand what
is where for which reason inside there, instead, and after these pages
of unrelevant code and meta-information and unrelevant explanation of
that, finally gotten to 'assuming you manged to follow me up to here,
you can now add these six lines here and that three lines there so you
can see what I was trying to show you'?

In this case, I'd say your definition of 'unwieldy' is rather
strange.
 
I

Ilya Zakharevich

So, do you think I should have posted a tar-file of the directory tree
created by h2xs, complete with detailed documentation enabling
someone who doesn't already know his way about that to understand what
is where for which reason inside there, instead, and after these pages
of unrelevant code and meta-information and unrelevant explanation of
that, finally gotten to 'assuming you manged to follow me up to here,
you can now add these six lines here and that three lines there so you
can see what I was trying to show you'?

Of course not. Just replace 90% of YOUR pages of instructions by two lines

h2xs OPTIONS

and

perl Makefile.PL && make test

Ilya
 

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,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top