Path: utzoo!attcan!uunet!cs.utexas.edu!usc!elroy.jpl.nasa.gov!jpl-devvax!lwall From: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Newsgroups: comp.lang.perl Subject: Re: defined() on an undef array element created via slice Message-ID: <10334@jpl-devvax.JPL.NASA.GOV> Date: 12 Nov 90 19:22:14 GMT References: <1990Nov8.005449.26158@agate.berkeley.edu> Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Organization: Jet Propulsion Laboratory, Pasadena, CA Lines: 83 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