[p4perl] Help with Hashes

Craig Leigh cleigh at blackboard.com
Tue Jan 4 07:03:16 PST 2005

Thanks this works

CM Team
Lead Engineer

-----Original Message-----
From: Tony Smith [mailto:tony at smee.org] 
Sent: Wednesday, December 29, 2004 1:08 PM
To: Craig Leigh
Cc: Robert Cowham; p4perl at perforce.com
Subject: Re: [p4perl] Help with Hashes

Craig Leigh wrote:

>	$p4->Edit ("c:/src/file.txt");
>	foreach my $e ($p4->Errors()){
>	      print "$e->[0]\n";
>	}
>	Path 'c:/src/file.txt' is not under client's root 'C:\code'.
>Which is correct!
>	foreach $e (@$chglist){
>	print "$e->[0]\n";
>	}
>gives this:
>	Not an ARRAY reference at C:\src\p4synop.pl line 66, <STDIN>
>line 1.
One of the most important things to know when working with P4Perl is 
what type of result to expect back  when you run a command. The rules 
are designed to make correct usage simple, but they're not always 
obvious. The comments above the implementation of P4::Run in P4.pm 
explain it best:

# Execute a command. The return value depends on the context of the
# Returns an array of results if the caller's asked for one
# Returns undef if result set is empty
# Returns a scalar result in scalar context if only one result exists.
# Returns an array ref in scalar context if more than one result exists.

Note that the return types above are evaluated in that order! i.e. if 
the caller's asked for an array, then an array is what they get and the 
rest is irrelevant.

When you run 'p4 edit //one/single/file' you can expect zero or one 
results (zero if there was an error). Whereas when you run 'p4 changes' 
you're usually going to get more than one result so you should expect an

array. So, I'd typically use:

    my $output = $p4->Edit( "//one/single/file" );


    my @changes = $p4->Changes( '-t', '-m5' );

Basically the lesson is to give some consideration to the type of value 
you (a) want and (b) expect to be returned.

If you're searching for 100% consistency, the answer is to always call 
P4::Run in array context. e.g.

    my @changes = $p4->Changes( "-t", "-m5", "//depot/some/path/..." );

will always return an array no matter what the results look like.

In your specific case, you need to iterate over the result array and 
treat each member of the array as a hash ref (if you're using 
ParseForms() mode). i.e.

	foreach $c (@$chglist){
		printf( "Change: %d by %s\n", $c->{ 'change' }, $c->{
'user' } );

As Robert points out, you can also test the type of the return value for
extra safety. YMMV though - it's easy to write more error checking code
than code to do what you wanted in the first place.


This e-mail is intended only for the personal and confidential use of the recipient(s) named above. 
It may include Blackboard confidential and proprietary information, and is not for redistribution.

More information about the p4perl mailing list