tags:

views:

249

answers:

5

Is this the best way to check a scalar variable is initialized in Perl using defined?

my $var;

if (cond) {
    $var = "string1";
}

# Is this the correct way?
if (defined $var) {
  ...
}
+2  A: 

If you don't care whether or not it's empty, it is. Otherwise you can check

if ( length( $str || '' )) {}
Axeman
A: 

'defined' will return true if a variable has a real value.

As an aside, in a hash, this can be true:

if(exists $h{$e} && !defined $h{$e})
msbmsb
`undef` is a real value. Using it as an indicator for "no value" is, while common, just a convention.
rafl
"real value" as in a valid scalar or reference value.
msbmsb
There is no such thing as an invalid scaler in perl.
rafl
Yes. You're speaking strictly, I was speaking conventionally.
msbmsb
+8  A: 

Perl doesn't offer a way to check whether or not a variable has been initialized.

However, scalar variables that haven't been explicitly initialized with some value happen to have the value of undef by default. You are right about defined being the right way to check whether or not a variable has a value of undef.

There's several other ways tho. If you want to assign to the variable if it's undef, which your example code seems to indicate, you could, for example, use perl's defined-or operator:

$var //= 'a default value';
rafl
`//` and `//=` operators were introduced in Perl 5.10. For prior versions the `||` and `||=` operators do the same thing except they will overwrite an initialized "defined but false" value like `"0"` or `""`.
mobrule
Begging your pardon, but scalars are `undef` by default, and the `defined` operator is what Perl offers to check against that value without incurring a "Use of uninitialized variable" warning. ('Cause y'all do have `-w` and `use strict` in effect, right?)
Blrfl
Blrfl: That's right. That's your point though? A scalar having a value of undef is entirely unrelated to whether it has been initialized or not, considering perl can't at all distinguish between uninitialized scalars and scalars that happen to hold the value `undef` because someone set it to `undef`.
rafl
Blrfl: scalar *variables* are undef unless you assign them a value, but that doesn't mean that they are not undef if you do assign them a value.
brian d foy
**@Blrfl:** you can assign an `undef` value to a variable after it's been initialized.
vol7ron
@rafl and BDF: I guess my point is that if you're writing code that actively avoids using an undefined scalar in warning-inducing situations, the semantics of declaring that scalar without initiaizing them become that Perl initializes it to `undef` for you. It may be splitting hairs, but I see assigning `undef` as effectively deinitializing the variable because its behavior becomes indistinguishable from Perl having done it for you. (Hope that made sense...)
Blrfl
+3  A: 

Depends on what you plan on doing with the variable whether or not it is defined; as of perl 5.10, you can do this (from perl51000delta):

A new operator // (defined-or) has been implemented. The following expression:

 $a // $b

is merely equivalent to

defined $a ? $a : $b

and the statement

$c //= $d;

can now be used instead of

$c = $d unless defined $c;
swilliams
+3  A: 

It depends on what you're trying to do. The proper C way to do things is to initialize variables when they are declared; however, Perl is not C, so one of the following may be what you want:

  1)   $var = "foo" unless defined $var;      # set default after the fact
  2)   $var = defined $var? $var : {...};     # ternary operation
  3)   {...} if !(defined $var);              # another way to write 1)
  4)   $var = $var || "foo";                  # 
  5)   $var ||= "foo";                        # 
  6)   $var //= "foo";                        # 5.10+


C way of doing things (not recommended):

# initialize the variable to a default value during declaration
#   then test against that value when you want to see if it's been changed
my $var = "foo";
{...}
if ($var eq "foo"){
   ... # do something
} else {
   ... # do something else
}

Another long-winded way of doing this is to create a class and a flag when the variable's been changed, which is unnecessary.

vol7ron