Mailing List Archive

Re: perl bug: array of undefs is falsely false
Excerpts from the mail message of Mark Jefferys:
)
) ["@x= (undef,undef)" is false.]
)
) Well, this can't be considered a bug, since it's intentional (maybe a
) documentation bug---I was really lax on that obligation). It might be
) a bad idea, although I don't really like any of the solutions:

Indeed, a complicated issue. I've rolled this around at many
angles...

I think it is clear that often you don't want undefs created as
place holders and often you don't want trailing undefs stripped.
Perl puts practicality before rigid consistancy so creating and
stripping undefs is common, but not universal. I think the best
solution is to allow the user to select from both types of
behavior, so long as it can be done reasonably. For example,
using "-1" in "split(/re/,$str,-1)" lets us prevent the default
stripping of trailing nulls.

I'm sure we don't want to change

@arr[@sub] and @hash{@sub}

so that they no longer return ("create") undefs for out-of-bounds
subscripts and non-existant keys. But I think being able to
request exactly that behavior could be generally useful. If
we allow this behavior for anonymous array slices as well, then
that can be used for the

if( @arr= (getpwent)[0,2] )

case and thus removes any motivation for having

"@x= (undef,undef)" considered false

(at least I don't see any other motivation).

How about:

@arr[@sub] for map { $arr[$_] } @sub
@arr([@sub]) for map { $_ < $[ || $#arr < $_ ? () : $arr[$_] } @sub
@hash{@sub} for map { $arr{$_} } @sub
@hash({@sub}) for map { $_ in keys(%hash) ? $hash{$_} : () } @sub

where "$_ in keys(%hash)" is pseudo Perl for whether hv_fetch()
returned 0. [.I don't think this adds ambiguity to the parsing,
but I certainly could be wrong.]

That is, @arr[@sub] and @hash{@sub}, stay the same. @arr([@sub])
does not "create" undefs as place holders for out-of-bounds
elements. @hash({@sub}) does not "create" undefs as place holders
for non-existant keys.

So we would now have to do:

if( @arr= (getpwent)([0,2]) )
^ ^
since "if( @arr= (getpwent)[0,2] )" never worked in perl4 anyway.

I'd also like a way to tell if a key is present in a hash, ie.
distinquish between hv_fetch() returning 0 vs. &(&sv_undef). For
most tied hashes, it would be the same as defined($hash{$key}),
but defining a non-default EXISTS() would allow a difference. So
using @tied_hash({@sub}) would cause EXISTS() to be called if
FETCH() returned undef [.I probably wouldn't change hv_fetch() but
instead change a few callers of hv_fetch() and add a caller].

Perhaps a new boolean: "$key in %hash" or "in(%hash,$key)".
Perhaps "keys(%hash,@keys)" could return the elements of @keys
that are keys of %hash: "map { $_ in %hash ? $_ : () } @keys".

But, in case you hate @arr([@sub]) and can't suggest a better
way to suppress undef place holders, here are my thoughts on
the previously proposed solutions:

) 1. Document the real behavior. Suggest using
) if ((@arr = func()), @arr) ...
) when a list of undefs should be true.

Kinda yuck but no worse than a few other rare cases in Perl.
Probably not possible in the face of the powerful special-interest
lobby from the DB users. :)

) 2. Make list-assignments return undef for zero objects assigned,
) and SV_NO for undef-only assignments. This allows:
) if (defined(@arr = func())) ...

This doesn't allow you, in (func())[0,2], to distinguish whether
func() returned () or (undef,"foo",undef,"bar").

It also means defined() is required above but if you try to
make a habit of using defined() you'll get bit because
while( defined( @arr= (getpwent)[0,2] ) ) {
will never end.

) 3. Make list-assignments normal, but have list-slices cut off
) trailing undefs, so
) (getpwent)[0,2]
) returns an empty list.
) A. This will cause code which relies on list-slices
) returning a fixed number of items to break. Sub calls
) are a likely source of problems:
) func1((func2())[1,3], ++$cnt);
) # Expects $cnt in 3rd place, not last.
) B. If any of the elements sliced is magic, we either have to
) get its value, which wastes time and can cause problems,
) or *not* get its value, which can fail.

I don't understand this last one (B).

) 4. Same as #3, except only eliminate undefs if you can eliminate
) all of them. Slightly reduces the problem with #A, does nothing
) for #B.
) 5. Same as #3, except cut off trailing *out-of-bound* references in
) list-slices. More likely to do what you want with #A, and fixes
) #B.
) 6. Combine #4 and #5. Same comments as #5.

The problem of documenting these properly makes me very wary of them.

) 7. Make a list-slice of an empty list be empty. This is an example
) of minimal intervention: make sure empty lists stay empty, and
) thus false, but otherwise acts normally. This would be somewhat
) easier to implement for tied arrays (and hashes).

This raises the problem of (A) again.

) 8. Make array assignments of slices magical, returning false if the
) original list was empty (or something). A really do-what-I-want
) solution.

But will still surprise people with

while( @ids= (getpwent)[2,3] ) {
if( $ids[0] == $uid && $ids[1] == $gid ) {
last;
}
}
if( @ids ) {
# We found a match!
}

because we'll always "find a match".

If it can be implemented relatively easilly, I'd vote for this.

[.Why do I keep thinking we need a new value, NoneSuch, which is
used for things that have never been set (such as out-of-bounds
elements)? exists() would be to NoneSuch as defined() is to
sv_undef. There would be no _direct_ way to set anything to
NoneSuch ("$#arr=5" indirectly sets "$arr[6]" to NoneSuch,
"delete($hash{key})" indirectly sets "$hash{key}" to NoneSuch).
In an assignment, NoneSuch is always transformed to sv_undef.
Would this help the problem of sv_undef causing too many "Use
of uninitialized value" warnings?]
--
Tye McQueen tye@metronet.com || tye@doober.usu.edu
Nothing is obvious unless you are overlooking something
http://www.metronet.com/~tye/ (scripts, links, nothing fancy)
Re: perl bug: array of undefs is falsely false [ In reply to ]
On Thu, 5 Oct 1995, Tye McQueen wrote:

% How about:
%
% @arr[@sub] for map { $arr[$_] } @sub
% @arr([@sub]) for map { $_ < $[ || $#arr < $_ ? () : $arr[$_] } @sub
% @hash{@sub} for map { $arr{$_} } @sub
% @hash({@sub}) for map { $_ in keys(%hash) ? $hash{$_} : () } @sub
%
% where "$_ in keys(%hash)" is pseudo Perl for whether hv_fetch()
% returned 0. [.I don't think this adds ambiguity to the parsing,
% but I certainly could be wrong.]
%
% That is, @arr[@sub] and @hash{@sub}, stay the same. @arr([@sub])
% does not "create" undefs as place holders for out-of-bounds
% elements. @hash({@sub}) does not "create" undefs as place holders
% for non-existant keys.
%
% So we would now have to do:
%
% if( @arr= (getpwent)([0,2]) )
% ^ ^
% since "if( @arr= (getpwent)[0,2] )" never worked in perl4 anyway.

Note that this has worked in perl5 for a little while, so there may be
a few scripts that this would break.

% I'd also like a way to tell if a key is present in a hash, ie.
...
% Perhaps a new boolean: "$key in %hash" or "in(%hash,$key)".
% Perhaps "keys(%hash,@keys)" could return the elements of @keys
% that are keys of %hash: "map { $_ in %hash ? $_ : () } @keys".

Or how about "exists $hash{$key}"? I don't think it would take too
much effort to add that. :-)


% ) 2. Make list-assignments return undef for zero objects assigned,
% ) and SV_NO for undef-only assignments. This allows:
% ) if (defined(@arr = func())) ...
%
% This doesn't allow you, in (func())[0,2], to distinguish whether
% func() returned () or (undef,"foo",undef,"bar").

Very true.

% It also means defined() is required above but if you try to
% make a habit of using defined() you'll get bit because
% while( defined( @arr= (getpwent)[0,2] ) ) {
% will never end.

I don't follow this. If Perl cannot deduce what the user wants, then
it will have to provide two different ways of writing this: one for
each interpretation. *All* of the solutions require rewriting if Perl
gets it wrong (including yours: @arr[] vs. @arr([]))---it's only a
question of how often it does, and how confusing the exceptions are.

% ) 3. Make list-assignments normal, but have list-slices cut off
% ) trailing undefs, so
% ) (getpwent)[0,2]
% ) returns an empty list.
% ) A. This will cause code which relies on list-slices
% ) returning a fixed number of items to break. Sub calls
% ) are a likely source of problems:
% ) func1((func2())[1,3], ++$cnt);
% ) # Expects $cnt in 3rd place, not last.
% ) B. If any of the elements sliced is magic, we either have to
% ) get its value, which wastes time and can cause problems,
% ) or *not* get its value, which can fail.
%
% I don't understand this last one (B).

Annoying technical issue. GMagical scalars cannot simply be tested
for undefs---they don't have a meaningful value unless mg_get is
called on them first. Doing so will waste time, since mg_get will
probably be called again when the value is used. Also, if I remember
correctly, I tried to fix this in the alpha, and ran into some sort of
difficulty with getting the value correctly.

% ) 7. Make a list-slice of an empty list be empty. This is an example
% ) of minimal intervention: make sure empty lists stay empty, and
% ) thus false, but otherwise acts normally. This would be somewhat
% ) easier to implement for tied arrays (and hashes).
%
% This raises the problem of (A) again.

Granted, although far less often than the others. I like this one
mostly because the exceptions I can think of are more contrived than
for the others, and pretty easy to work around:

@arr ? @arr[@idx] : (undef) x @idx

% ) 8. Make array assignments of slices magical, returning false if the
% ) original list was empty (or something). A really do-what-I-want
% ) solution.
%
% But will still surprise people with
%
% while( @ids= (getpwent)[2,3] ) {
% if( $ids[0] == $uid && $ids[1] == $gid ) {
% last;
% }
% }
% if( @ids ) {
% # We found a match!
% }
%
% because we'll always "find a match".

Also, this won't work if there is a sub-call separating the slice from
the assignment:

sub zoop { (getpwent)[2,3] }
while (@ids = zoop()) ...

% If it can be implemented relatively easilly, I'd vote for this.
%
% [.Why do I keep thinking we need a new value, NoneSuch, which is
% used for things that have never been set (such as out-of-bounds
% elements)? exists() would be to NoneSuch as defined() is to
% sv_undef. There would be no _direct_ way to set anything to
% NoneSuch ("$#arr=5" indirectly sets "$arr[6]" to NoneSuch,
% "delete($hash{key})" indirectly sets "$hash{key}" to NoneSuch).
% In an assignment, NoneSuch is always transformed to sv_undef.
% Would this help the problem of sv_undef causing too many "Use
% of uninitialized value" warnings?]

Maybe... It would be nice to fix the spurious warnings. But there
will always be potential problems with it: I'm sure someone will ask
why

$save = oper();
...
if (exists $save) ...

doesn't act like

if (exists oper()) ...


There's also a good reason for having "exists $hash{$key}" not simply
get $hash{$key} and test it: For some tied arrays, checking exists
may be far more efficient than getting the value. I suppose this use
could be optimized, though.


Mark
Re: perl bug: array of undefs is falsely false [ In reply to ]
This topic generated quite a discussion!

I'd like to narrow it down and check if we've reached a consensus:

> From: Mark Jefferys <mark@skye.as.utexas.edu>
>
> % since "if( @arr= (getpwent)[0,2] )" never worked in perl4 anyway.
>
> Note that this has worked in perl5 for a little while, so there may be
> a few scripts that this would break.

Since it was never well documented I doubt there are that many scripts
that use this other than those you've written yourself. Then again
Larry may take the view that the possibility makes the risk of undoing
the change to high.


> % Excerpts from the mail message of Mark Jefferys:

> % ) 2. Make list-assignments return undef for zero objects assigned,
> % ) and SV_NO for undef-only assignments. This allows:
> % )
> % ) if (defined(@arr = func())) ...

> % ) 3. Make list-assignments normal, but have list-slices cut off
> % ) trailing undefs, so
> % ) (getpwent)[0,2]
> % ) returns an empty list.
> % ) A. This will cause code which relies on list-slices
> % ) returning a fixed number of items to break. Sub calls
> % ) are a likely source of problems:
> % ) func1((func2())[1,3], ++$cnt);
> % ) # Expects $cnt in 3rd place, not last.

> % ) 7. Make a list-slice of an empty list be empty. This is an example
> % ) of minimal intervention: make sure empty lists stay empty, and
> % ) thus false, but otherwise acts normally. This would be somewhat
> % ) easier to implement for tied arrays (and hashes).
> %
> % This raises the problem of (A) again.
>
> Granted, although far less often than the others. I like this one
> mostly because the exceptions I can think of are more contrived than
> for the others, and pretty easy to work around:
>
> @arr ? @arr[@idx] : (undef) x @idx
>
> % ) I kinda like #2 or #7 at the moment; [...]

So, to summarise the situation (and check that _I_ understand it :) ...

- Currently evaluation in scalar context of the assignment of a list
of undefs is regarded as false.

- It seems widely agreed that this is not ideal.

- This was added to cater for: while (($user, $uid) = (getpwent)[0,2]) { }

- It seems widely agreed that this is useful.

I also like #7 "Make a list-slice of an empty list be empty".
Feels kind'a like null-propagation in SQL expressions.

#2 seems too subtle for people to remember to use in their code.
Especially where they don't expect to get nulls but might in error
conditions.

Does anyone have and hard objections or better alternatives?

Larry, do you concur?

Tim.
Re: perl bug: array of undefs is falsely false [ In reply to ]
On Fri, 6 Oct 1995, Tim Bunce wrote:

% This topic generated quite a discussion!
%
% I'd like to narrow it down and check if we've reached a consensus:
%
%> From: Mark Jefferys <mark@skye.as.utexas.edu>
%>
%>% since "if( @arr= (getpwent)[0,2] )" never worked in perl4 anyway.
%>
%> Note that this has worked in perl5 for a little while, so there may be
%> a few scripts that this would break.
%
% Since it was never well documented I doubt there are that many scripts
% that use this other than those you've written yourself. Then again
% Larry may take the view that the possibility makes the risk of undoing
% the change to high.

Actually, I'm not too worried about my own scripts. I'm concerned
because I remember this coming up as a "Why doesn't this work?",
"Because, but it would be better if it did," situation.

Some people may have written "while (@arr = (getpwent)[0,2]) ..." or
an equivalent, never realizing they were using a feature. Changing it
now would break their scripts (if they exist at all).

%>% Excerpts from the mail message of Mark Jefferys:

[ #1 is current behavior: list-assign in scalar context returns ]
[ SV_UNDEF if only undefs assigned, otherwise count is returned. ]

%>%) 2. Make list-assignments return undef for zero objects assigned,
%>%) and SV_NO for undef-only assignments. This allows:
%>%)
%>%) if (defined(@arr = func())) ...
%
%>%) 3. Make list-assignments normal, but have list-slices cut off
%>%) trailing undefs, so
%>%) (getpwent)[0,2]
%>%) returns an empty list.

%>%) 7. Make a list-slice of an empty list be empty. This is an example
%>%) of minimal intervention: make sure empty lists stay empty, and
%>%) thus false, but otherwise acts normally. This would be somewhat
%>%) easier to implement for tied arrays (and hashes).

%>%) I kinda like #2 or #7 at the moment; [...]
%
% So, to summarise the situation (and check that _I_ understand it :) ...
%
% - Currently evaluation in scalar context of the assignment of a list
% of undefs is regarded as false.
%
% - It seems widely agreed that this is not ideal.
%
% - This was added to cater for: while (($user, $uid) = (getpwent)[0,2]) { }

Technically, #3 was added to cater to this. I didn't think much of
the solution, and offered #1 as an alternative (with source). I don't
remember any other ideas being discussed.

% - It seems widely agreed that this is useful.
%
% I also like #7 "Make a list-slice of an empty list be empty".
% Feels kind'a like null-propagation in SQL expressions.
%
% #2 seems too subtle for people to remember to use in their code.
% Especially where they don't expect to get nulls but might in error
% conditions.

Perhaps. I offered #2 as a variation on #1 which is easier to work
around.


Mark
Re: perl bug: array of undefs is falsely false [ In reply to ]
: > % Excerpts from the mail message of Mark Jefferys:
:
: > % ) 2. Make list-assignments return undef for zero objects assigned,
: > % ) and SV_NO for undef-only assignments. This allows:
: > % )
: > % ) if (defined(@arr = func())) ...
:
: > % ) 3. Make list-assignments normal, but have list-slices cut off
: > % ) trailing undefs, so
: > % ) (getpwent)[0,2]
: > % ) returns an empty list.
: > % ) A. This will cause code which relies on list-slices
: > % ) returning a fixed number of items to break. Sub calls
: > % ) are a likely source of problems:
: > % ) func1((func2())[1,3], ++$cnt);
: > % ) # Expects $cnt in 3rd place, not last.
:
: > % ) 7. Make a list-slice of an empty list be empty. This is an example
: > % ) of minimal intervention: make sure empty lists stay empty, and
: > % ) thus false, but otherwise acts normally. This would be somewhat
: > % ) easier to implement for tied arrays (and hashes).
: > %
: > % This raises the problem of (A) again.
: >
: > Granted, although far less often than the others. I like this one
: > mostly because the exceptions I can think of are more contrived than
: > for the others, and pretty easy to work around:
: >
: > @arr ? @arr[@idx] : (undef) x @idx
: >
: > % ) I kinda like #2 or #7 at the moment; [...]

I think that as we move into using prototypes, func1() above would
probably be declared as

sub func1 ($$$);

so you wouldn't be able to say

func1((func2())[1,3], ++$cnt);

in any event. (Unless I did something Really Strange with argument
processing to make it look inside a list slice.)

: So, to summarise the situation (and check that _I_ understand it :) ...
:
: - Currently evaluation in scalar context of the assignment of a list
: of undefs is regarded as false.
:
: - It seems widely agreed that this is not ideal.
:
: - This was added to cater for: while (($user, $uid) = (getpwent)[0,2]) { }
:
: - It seems widely agreed that this is useful.
:
: I also like #7 "Make a list-slice of an empty list be empty".
: Feels kind'a like null-propagation in SQL expressions.

A little, though I think Perl's notion is a little more fail-soft.

: #2 seems too subtle for people to remember to use in their code.
: Especially where they don't expect to get nulls but might in error
: conditions.
:
: Does anyone have and hard objections or better alternatives?
:
: Larry, do you concur?

Hail the concurring hero, eh?

[sorry]

I'm leaning toward #7 too. Especially since it makes array assignments
a little faster...

On the other hand, doing something a bit #8ish wouldn't be too difficult.
It would be relatively trivial to inform the OP_LSLICE that it was on the
right side of an OP_AASSIGN. I don't think we'd even have to worry about
whether the assignment was in a scalar context, though even that wouldn't
be difficult to do.

Larry
Re: perl bug: array of undefs is falsely false [ In reply to ]
> %> From: Mark Jefferys <mark@skye.as.utexas.edu>
> %>
> %>% since "if( @arr= (getpwent)[0,2] )" never worked in perl4 anyway.
> %>
> %> Note that this has worked in perl5 for a little while, so there may be
> %> a few scripts that this would break.

Yes, I remember getting Larry to fix it, as I'm the one who submitted
that bug. I do see why you're upset by it, though.

--tom
Re: perl bug: array of undefs is falsely false [ In reply to ]
On Fri, 6 Oct 1995, Larry Wall wrote:

> I think that as we move into using prototypes, func1() above would
> probably be declared as
>
> sub func1 ($$$);
>
> so you wouldn't be able to say
>
> func1((func2())[1,3], ++$cnt);
>
> in any event. (Unless I did something Really Strange with argument
> processing to make it look inside a list slice.)

I think this is a case of knowing just enough LISP to be dangerous. The
thing is, some people (me included, I'm afraid) tend to write code like
that. Talk about breaking current scripts...

> I'm leaning toward #7 too. Especially since it makes array assignments
> a little faster...

It certainly seems a decent solution. Easy to explain, and minimal surprise.

> On the other hand, doing something a bit #8ish wouldn't be too difficult.
> It would be relatively trivial to inform the OP_LSLICE that it was on the
> right side of an OP_AASSIGN. I don't think we'd even have to worry about
> whether the assignment was in a scalar context, though even that wouldn't
> be difficult to do.

Non-minimal surprise and context sensistivity... Then again, this _is_
perl. ;-)

> Larry

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: perl bug: array of undefs is falsely false [ In reply to ]
Excerpts from the mail message of Mark Jefferys:
) % I'd also like a way to tell if a key is present in a hash, ie.
[...]
) Or how about "exists $hash{$key}"? I don't think it would take too
) much effort to add that. :-)

No fair adding it my copy while I'm not looking! :)

) % It also means defined() is required above but if you try to
) % make a habit of using defined() you'll get bit because
) % while( defined( @arr= (getpwent)[0,2] ) ) {
) % will never end.
)
) I don't follow this. If Perl cannot deduce what the user wants, then
) it will have to provide two different ways of writing this: one for
) each interpretation. *All* of the solutions require rewriting if Perl
) gets it wrong (including yours: @arr[] vs. @arr([]))---it's only a
) question of how often it does, and how confusing the exceptions are.

You're right, that disadvantage isn't specific to this case.
I still like the idea of having the option to slice without
creating undefs for out-of-bounds subscripts.

) % [.Why do I keep thinking we need a new value, NoneSuch, which is
) % used for things that have never been set (such as out-of-bounds
) % elements)?
[...]
) There's also a good reason for having "exists $hash{$key}" not simply
) get $hash{$key} and test it:

I wasn't suggesting that. Since a tied hash would use a Perl "sub
EXISTS", it would have _no way_ of returning NoneSuch. Putting
NoneSuch on the Perl stack to be returned would transform it into
undef.

) Maybe... It would be nice to fix the spurious warnings. But there
) will always be potential problems with it: I'm sure someone will ask
) why
) $save = oper();
) if (exists $save) ...
) doesn't act like
) if (exists oper()) ...

Any such people already can't handle why

sub notdef { undef; }
print "TRUE\n" if defined(&notdef);

prints TRUE. Now that exists() exists, we've become a bit
inconsistant here. Ignoring backward compatibility:

defined() should only check an expression value so defined(&func)
should be the same as defined($x=&func).

To see if a function exists, you should use exists(&func).
exists() does not take an expression or value as an argument
so saving some value in $save=oper() doesn't effect what
exists($save) returns (except when doing so creates $save).

Now silly stuff on how exists() and delete() should be extended:

delete(&func) would be used to make the next &func re-autoload.
undef(&func) would keep its current behavior, to make &func() an
error (leave &func cached as if autoloading failed).

$x= "global";
{ my $x= "my";
print "($x) ";
delete($x); # Remove lexical from scope, a compile-time op
print "<$x> ";
delete($x); # Delete $x from symbol table
print "[$x]\n";
}
# This would print "(my) <global> []".

Notice how my mind likes to deny that it is "x" in the symbol
table and not "$x"? But NoneSuch would allow us to hide that
fact. ;>
--
Tye McQueen tye@metronet.com || tye@doober.usu.edu
Nothing is obvious unless you are overlooking something
http://www.metronet.com/~tye/ (scripts, links, nothing fancy)
Re: perl bug: array of undefs is falsely false [ In reply to ]
Excerpts from the mail message of Larry Wall:
) I think that as we move into using prototypes, func1() above would
) probably be declared as
)
) sub func1 ($$$);
)
) so you wouldn't be able to say
)
) func1((func2())[1,3], ++$cnt);
)
) in any event. (Unless I did something Really Strange with argument
) processing to make it look inside a list slice.)

So this means that the call to chown will be changed to

chown( [$uid,$gid], @files );

right? 1/2 :)

) On the other hand, doing something a bit #8ish wouldn't be too difficult.
) It would be relatively trivial to inform the OP_LSLICE that it was on the
) right side of an OP_AASSIGN. I don't think we'd even have to worry about
) whether the assignment was in a scalar context, though even that wouldn't
) be difficult to do.

So would this information wander into OP_LSLICEs that are return
values of functions [that are return values of functions] on the
right-hand side of an OP_AASSIGN? Just curious, not advocating a
position this time.
--
Tye McQueen tye@metronet.com || tye@doober.usu.edu
Nothing is obvious unless you are overlooking something
http://www.metronet.com/~tye/ (scripts, links, nothing fancy)
Re: perl bug: array of undefs is falsely false [ In reply to ]
> defined() should only check an expression value so defined(&func)
> should be the same as defined($x=&func).

You'd break a lot of code. I and surely many others are used to

defined &f # function existence (modulo AUTOLOAD || inheritance)
vs
defined f() # first call function, then check retval

I have noticed that all this delete() vs splice() vs undef() stuff is a
tad inconsistent or hard to follow for some folks, and I guess I
don't blame them too much..

--tom
Re: perl bug: array of undefs is falsely false [ In reply to ]
Excerpts from the mail message of Tom Christiansen:
)
) > defined() should only check an expression value so defined(&func)
) > should be the same as defined($x=&func).
)
) You'd break a lot of code.

Sorry, I thought prefacing that with "Ignoring backward
compatibility:" was enough. I wasn't advocating a change,
just pointing out something I wish had been different.
The "should" was as in "should have, in a perfect world,"
not as in "should be changed to".
--
Tye McQueen tye@metronet.com || tye@doober.usu.edu
Nothing is obvious unless you are overlooking something
http://www.metronet.com/~tye/ (scripts, links, nothing fancy)
Re: perl bug: array of undefs is falsely false [ In reply to ]
On Fri, 6 Oct 1995, Larry Wall wrote:

% I think that as we move into using prototypes, func1() above would
% probably be declared as
%
% sub func1 ($$$);
%
% so you wouldn't be able to say
%
% func1((func2())[1,3], ++$cnt);
%
% in any event. (Unless I did something Really Strange with argument
% processing to make it look inside a list slice.)

Assuming someone used prototypes. Also, the same limitation applies to
the arguments of a format.


Mark
Re: perl bug: array of undefs is falsely false [ In reply to ]
On Sat, 7 Oct 1995, Tye McQueen wrote:

% Excerpts from the mail message of Mark Jefferys:
% ) % I'd also like a way to tell if a key is present in a hash, ie.
% [...]
% ) Or how about "exists $hash{$key}"? I don't think it would take too
% ) much effort to add that. :-)
%
% No fair adding it my copy while I'm not looking! :)

Oops.

% defined() should only check an expression value so defined(&func)
% should be the same as defined($x=&func).

This is mostly the confusion between &func as a way of referring to
&func, and as a way of calling it. A good reason to deprecate the
latter, IMHO.

% To see if a function exists, you should use exists(&func).
% exists() does not take an expression or value as an argument
% so saving some value in $save=oper() doesn't effect what
% exists($save) returns (except when doing so creates $save).

OK. I like that, actually.

% Now silly stuff on how exists() and delete() should be extended:
%
% delete(&func) would be used to make the next &func re-autoload.
% undef(&func) would keep its current behavior, to make &func() an
% error (leave &func cached as if autoloading failed).
%
% $x= "global";
% { my $x= "my";
% print "($x) ";
% delete($x); # Remove lexical from scope, a compile-time op
% print "<$x> ";
% delete($x); # Delete $x from symbol table
% print "[$x]\n";
% }
% # This would print "(my) <global> []".

That's either really clever or really gross---I can't quite decide. I
think I like it.

% Notice how my mind likes to deny that it is "x" in the symbol
% table and not "$x"? But NoneSuch would allow us to hide that
% fact. ;>

Perhaps. I don't see any reason why we need to add an actual NoneSuch
scalar to make this work.

IDEA: One thing that could be done---and this would cut down on spurious
warnings a lot---is to create the SVs, AVs, and HVs when first
accessed, instead of when their containing GVs are created. A warning
could be produced if this is done in a non-modification context.

I don't know precisely how this would affect performance, though.
For example, there would need to be an extra check in pp_sv to see
that the accessed scalar was non-zero. On the other hand, Perl
wouldn't waste time (and space) creating unused AVs and HVs when
someone uses $x without the others. And the current warning checks
could be thrown out.


Mark
Re: perl bug: array of undefs is falsely false [ In reply to ]
Excerpts from the mail message of Mark Jefferys:
) On Sat, 7 Oct 1995, Tye McQueen wrote:
) % defined() should only check an expression value so defined(&func)
) % should be the same as defined($x=&func).
)
) This is mostly the confusion between &func as a way of referring to
) &func, and as a way of calling it. A good reason to deprecate the
) latter, IMHO.

I disagree. It is because defined() is doing two different
things: checking if a value is undef and checking if a
function exists. The second function should not be overloaded
into defined() now that we have exists().~

) % Now silly stuff on how exists() and delete() should be extended:
) %
) % delete(&func) would be used to make the next &func re-autoload.
) % undef(&func) would keep its current behavior, to make &func() an
) % error (leave &func cached as if autoloading failed).
) %
) % $x= "global";
) % { my $x= "my";
) % print "($x) ";
) % delete($x); # Remove lexical from scope, a compile-time op
) % print "<$x> ";
) % delete($x); # Delete $x from symbol table
) % print "[$x]\n";
) % }
) % # This would print "(my) <global> []".
)
) That's either really clever or really gross---I can't quite decide. I
) think I like it.

The "remove lexical from scope" I was only half serious about.
I'd probably change that to "compile-time error" if this became
a serious proposal.

) % Notice how my mind likes to deny that it is "x" in the symbol
) % table and not "$x"? But NoneSuch would allow us to hide that
) % fact. ;>
)
) Perhaps. I don't see any reason why we need to add an actual NoneSuch
) scalar to make this work.

Oh, I see where the confusion is coming from. NoneSuch is not
a scalar. If fact, I'd probably just use NULL for it and add
a macro that turns NULL to &sv_undef whenever a value is stored
or copied.

) IDEA: One thing that could be done---and this would cut down on spurious
) warnings a lot---is to create the SVs, AVs, and HVs when first
) accessed, instead of when their containing GVs are created. A warning
) could be produced if this is done in a non-modification context.

Yeah, that's what I was talking about.

) I don't know precisely how this would affect performance, though.
) For example, there would need to be an extra check in pp_sv to see
) that the accessed scalar was non-zero. On the other hand, Perl
) wouldn't waste time (and space) creating unused AVs and HVs when
) someone uses $x without the others. And the current warning checks
) could be thrown out.

I wondered it this was intentionally not done in order to reduce
the likelyhood that a "minor" bug in Perl would cause a core dump
via a NULL dereference.

~Okay, I'm almost to the point of advocating a change, but it
would have to be done by 1) making exists(&func) work, 2)
announce that defined(&func) should be replaced with exists(&func)
as some future version will change defined(&func), 3) wait a
long time, 4) make defined(&func) give a warning, 5) make
defined(&func) no longer compile, 6) wait a long time, 7) make
defined(&func) the same as defined(func()). Not worth the change
unless it allows other improvements as well, which I think it does.
--
Tye McQueen tye@metronet.com || tye@doober.usu.edu
Nothing is obvious unless you are overlooking something
http://www.metronet.com/~tye/ (scripts, links, nothing fancy)
Re: perl bug: array of undefs is falsely false [ In reply to ]
: On Sat, 7 Oct 1995, Tye McQueen wrote:
:
: % Excerpts from the mail message of Mark Jefferys:
: % ) % I'd also like a way to tell if a key is present in a hash, ie.
: % [...]
: % ) Or how about "exists $hash{$key}"? I don't think it would take too
: % ) much effort to add that. :-)
: %
: % No fair adding it my copy while I'm not looking! :)
:
: Oops.
:
: % defined() should only check an expression value so defined(&func)
: % should be the same as defined($x=&func).

Um, defined() is also magical for arrays and hashes, guys.

: This is mostly the confusion between &func as a way of referring to
: &func, and as a way of calling it. A good reason to deprecate the
: latter, IMHO.

Gee, it's context dependent. How awful... :-)

: % To see if a function exists, you should use exists(&func).
: % exists() does not take an expression or value as an argument
: % so saving some value in $save=oper() doesn't effect what
: % exists($save) returns (except when doing so creates $save).
:
: OK. I like that, actually.

But I think exists(&func) should determine whether the function has
been *declared*, not whether the function has been defined. I would
like to be able to distinguish the two.

: % Now silly stuff on how exists() and delete() should be extended:
: %
: % delete(&func) would be used to make the next &func re-autoload.
: % undef(&func) would keep its current behavior, to make &func() an
: % error (leave &func cached as if autoloading failed).
: %
: % $x= "global";
: % { my $x= "my";
: % print "($x) ";
: % delete($x); # Remove lexical from scope, a compile-time op
: % print "<$x> ";
: % delete($x); # Delete $x from symbol table
: % print "[$x]\n";
: % }
: % # This would print "(my) <global> []".
:
: That's either really clever or really gross---I can't quite decide. I
: think I like it.

I'd rather not say what I think of it.

: % Notice how my mind likes to deny that it is "x" in the symbol
: % table and not "$x"? But NoneSuch would allow us to hide that
: % fact. ;>
:
: Perhaps. I don't see any reason why we need to add an actual NoneSuch
: scalar to make this work.
:
: IDEA: One thing that could be done---and this would cut down on spurious
: warnings a lot---is to create the SVs, AVs, and HVs when first
: accessed, instead of when their containing GVs are created. A warning
: could be produced if this is done in a non-modification context.
:
: I don't know precisely how this would affect performance, though.
: For example, there would need to be an extra check in pp_sv to see
: that the accessed scalar was non-zero. On the other hand, Perl
: wouldn't waste time (and space) creating unused AVs and HVs when
: someone uses $x without the others. And the current warning checks
: could be thrown out.

As far as I know, the only time Perl creates AVs and HVs on spec is
when sv_setsv() creates a fake *. And I found last week that I could
comment out that Perl4-derived code now because in Perl 5, fake globs
are true aliases rather than temporary namespaces, as in Perl 4. (Perl 4
actually copied the pointers, while Perl 5 keeps a reference counted GP
("glob pointer") structure.)

So it looks like we've already reached a state where the Perl 5 compiler
always knows when it has to create values, at least for arrays and hashes.

I believe it still creates SVs on spec though. You'll note the code
that pushes SV values doesn't bother to check whether it's an lvalue.

Larry