[comp.lang.perl] defined

louie@sayshell.umd.edu (Louis A. Mamakos) (08/13/90)

I noticed that a perl script that I had stopped working under patchlevel 27.  It
seems like the defined() operator is working differently than it did before.

try this out:

#!/usr/local/bin/perl

if (defined(@foo)) {
	print "defined\n";
} else {
	print "not defined\n";
}

undef @foo;

if (defined(@foo)) {
	print "defined\n";
} else {
	print "not defined\n";
}

__END__


and you'll get

defined
not defined

printed at you.  Patchlevel 18 gives

not defined
not defined

This is on a NeXT workstation, and all tests passed just fine.

louie

raymond@math.berkeley.edu (Raymond Chen) (11/08/90)

[The question:]

Consider the following script:

    @foo{"bar"} = ();
    print keys(%foo), "\n"; # See, it's listed as one of the keys
    if (defined($foo{"bar"})) { print "Patch level 18 prints this\n"; }
		        else  { print "Patch level 36 prints this\n"; }

Observe that $foo{"bar"} was created via an associative array slice.

Who is right, Patch level 18 or Patch level 36?

The problem seems to be that, although $foo{"bar"} is defined,
its value is undef.  This schizophrenic state of affairs seems to
lead to different interpretations depending on your patch level.

(Maybe because PL16 initialized $foo{"bar"} = ""?  Is this related
to the change in semantics of local()?)

[How I noticed this:]

My current code initializes a list of commands via

   @commands{ split(/ /, "Scale Height Width Borders etc...") } = ();

and tests if a particular token is a command via

   if (defined($commands{$token})) {...}

This breaks under PL36 as described above.

I know I can write

  for (split(/ /, "Scale Height Width etc...")) { $commands{$_} = 1; }

but somehow, the slice looked spiffier to me at the time.  Ah, the
price one pays for a moment of folly.
--
@japh{split(/:/, "hacker,:Just :erl :another p")} = (); print sort keys %japh;
# Extra credit:  What is $japh{"hacker,"}?  What is defined($japh{"hacker,"})?

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (11/13/90)

In article <1990Nov8.005449.26158@agate.berkeley.edu> raymond@math.berkeley.edu writes:
: [The question:]
: 
: Consider the following script:
: 
:     @foo{"bar"} = ();
:     print keys(%foo), "\n"; # See, it's listed as one of the keys
:     if (defined($foo{"bar"})) { print "Patch level 18 prints this\n"; }
: 		        else  { print "Patch level 36 prints this\n"; }
: 
: Observe that $foo{"bar"} was created via an associative array slice.
: 
: Who is right, Patch level 18 or Patch level 36?

It's a judgement call, but I think 36 is righter.  It's nice to be able
to differentiate

	@foo{"bar"} = ();

from

	@foo{"bar"} = ("");

Or look at it another way.  You can have an existing variable with an
undefined value, why not an existing array element with an undefined
value?

If the x operator worked on array values (it doesn't), then you could say

	@foo{"foo", "bar"} = (1) x 2;

(I don't think I can make x work on array values without breaking scripts,
alas.  Hmm, maybe I can, if I require the parens.  Hmm...  Still possible
to break scripts, I think...)

: The problem seems to be that, although $foo{"bar"} is defined,
: its value is undef.  This schizophrenic state of affairs seems to
: lead to different interpretations depending on your patch level.
: 
: (Maybe because PL16 initialized $foo{"bar"} = ""?  Is this related
: to the change in semantics of local()?)

Yes, it is.  It's actually a difference in the semantics of list assignment,
of which local() assignment is a subset.

: [How I noticed this:]
: 
: My current code initializes a list of commands via
: 
:    @commands{ split(/ /, "Scale Height Width Borders etc...") } = ();
: 
: and tests if a particular token is a command via
: 
:    if (defined($commands{$token})) {...}
: 
: This breaks under PL36 as described above.
: 
: I know I can write
: 
:   for (split(/ /, "Scale Height Width etc...")) { $commands{$_} = 1; }
: 
: but somehow, the slice looked spiffier to me at the time.  Ah, the
: price one pays for a moment of folly.

How 'bout something like this:

	%commands = &set("Scale Height Width Borders etc...");

	sub set {
	    local($string, @result) = @_;
	    for (split(' ', $string)) {
		push(@result, $_, 1);
	    }
	    @result;
	}

	if ($commands{$token}) {...}

It would be nice if there was a way to generate arbitrarily long lists of
some specified value on demand, but I haven't (yet) got up the gumption to
turn Perl into Icon.  :-)

Larry

friedman@chekov.UU.NET (Barry Friedman) (03/21/91)

I've noticed the following non-intuitive behaviour of 'defined()':
When a variable is used in a string it becomes defined.

I don't recall any discussion on this.

#!/usr/bin/perl

$a='$b is undefined';
$a='$b is defined' if defined ($b);
print $a,"\n";
print "b is now <$b>","\n";
$a='$b is defined' if defined ($b);
print $a,"\n";
__END__

produces
$b is undefined
b is now <>
$b is defined

--
Barry Friedman                INTERNET: friedman%chekov@uunet.uu.net
Phone: (613) 782-2389         UUCP: ...!uunet!chekov!friedman
Emax Computer Systems Inc.  440 Laurier Ave. W., Ottawa, Ont. Canada K1R 5C4

composer@chem.bu.edu (Jeff Kellem) (03/22/91)

In article <1991Mar21.142935.11333@bmers145.bnr.ca> friedman@chekov.UU.NET (Barry Friedman) writes:
 > I've noticed the following non-intuitive behaviour of 'defined()':
 > When a variable is used in a string it becomes defined.
 >
 > I don't recall any discussion on this.
 >
 > #!/usr/bin/perl
 >
 > $a='$b is undefined';
 > $a='$b is defined' if defined ($b);
 > print $a,"\n";
 > print "b is now <$b>","\n";
 > $a='$b is defined' if defined ($b);
 > print $a,"\n";
 > __END__
 >
 > produces
 > $b is undefined
 > b is now <>
 > $b is defined

From the man page (actually my Texinfo conversion of the man page) under
the section titled "Data Types and Objects",

    "...An undefined null string may become defined the first time you
    access it, but prior to that you can use the `defined()' operator to
    determine whether the value is defined or not."

Therefore, accessing "$b" in the line `print "b is now <$b>", "\n";'
makes $b defined instead of undefined.

Cheers...

			-jeff

Jeff Kellem
Internet: composer@chem.bu.edu

rbj@uunet.UU.NET (Root Boy Jim) (03/23/91)

In article <1991Mar21.142935.11333@bmers145.bnr.ca> friedman@chekov.UU.NET (Barry Friedman) writes:
> I've noticed the following non-intuitive behaviour of 'defined()':
> When a variable is used in a string it becomes defined.

This is a tricky situation. In LISP, mentioning an atom as a data object
actually intern's it, but does not bind it. You cannot use the value
cell until you set it to something.

However, in perl, variables "spring to life" on reference, with
"null or zero values as appropriate". In order to accommodate
this, variables must become defined.

I really don't like using defined for this reason, and shy away from it.
-- 
		[rbj@uunet 1] stty sane
		unknown mode: sane