C05cad8e507792fd5aac221af97dfe26

I'm having serious trouble with Perl's syntactic niceties... I can get a function like this to work with a single scalar or a single array but this doesn't work. Please help me figure out where my syntax is wrong (and if we can make this cleaner, all the better!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use Cache::FileCache;

$cache = new Cache::FileCache( );

# this subroutine works just fine
sub stockInfoFresh
{
	my $tick = $_[0];
	
	$tick =~ tr/a-z/A-Z/;
	
	my $first_let = substr($tick,0,1);
	
	my $name = "Ticker not found";
	my $exch = '';
	
	my $sth = $dbh->prepare("SELECT * FROM `Stock` WHERE `Ticker` = '$tick'"); $sth->execute;
	
	my @stockid = $sth->fetchrow_array;
	
	if ($stockid[0]) {
		$name = $stockid[2];
		$exch = $stockid[3];
	}
	
	$sth->finish;
	
	my @out; 
	
	return($tick, $first_let, $name, $exch, @stockid);
}

# this subroutine fails
sub stockInfo
{
	my $tick = $_[0];
	
	my @stockInfo = $cache->get( "stockInfo" . $tick );
	
	if( not defined @stockInfo )
	{
		@stockInfo = &stockInfoFresh($tick);
		
		$cache->set( "stockInfo" . $tick, \@stockInfo, "1 hour" );
	}

	# at this point, $stockInfo[0] is empty

	return @stockInfo;
}

# this fails

my($tick, $first_let, $name, $exch, @stockid) = &stockInfo($t);

Refactorings

No refactoring yet !

B8d457d2c39911ea4c74ba7d66b9c3f7

Marco Valtas

October 12, 2007, October 12, 2007 02:34, permalink

2 ratings. Login to rate!

Hi, I made some modifications in your code I believe will work, here some mock tests worked. The problem probably was how you tested how get() returned. I made some obs inside the code as well.

Some tips:
Avoid the * inside a SQL, you never know when someone will add a column and make your code fail.
If you know that your SQL will return one and only one row (your code implies this condition) you can avoid the prepare and execute with
selectcol_arrayref(), here is one example from my legacy code:

my($domain_id) = @{$self->{dbh}->selectcol_arrayref("
SELECT domain_id FROM domain_project
WHERE project_id='$project_id'
")};

Hope that helps.

perl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 
# always use strict and warnings, this can solve hours of debuging!
use strict;
use warnings;

use Cache::FileCache;

# defined somewere else...
my $dbh;
my $t;

my $cache = new Cache::FileCache( );
# $cache->clear(); # clear all cached information.`

# this subroutine works just fine
sub stockInfoFresh
{
	my ($tick) = @_; # this is a better way to get arguments
	
	$tick =~ tr/a-z/A-Z/; # to uppercase
	
	my $first_let = substr($tick,0,1);
	
	my $name = "Ticker not found";
	my $exch = '';
	
    my $sth = $dbh->prepare("SELECT * FROM `Stock` WHERE `Ticker` = '$tick'"); $sth->execute;
	
    # this implies that you will work with one and only one row.
    # if multiple rows this should be inside a while loop.
    my @stockid = $sth->fetchrow_array;
	
	if ($stockid[0]) {
		$name = $stockid[1];
		$exch = $stockid[2];
	}

    $sth->finish;
	
    # when returning a array try to avoid return a array as
    # ($one, $two, @three), this syntax can raise difficult bugs.
	return($tick, $first_let, $name, $exch, $stockid[0]);
}

# this subroutine fails
sub stockInfo
{
	my ($tick) = @_; # this is a better way to get a argument

    # get returns a array reference, you should get in a scalar
    # just to test if FileCache returned something    
	my $stockInfo = $cache->get( "stockInfo" . $tick );

    # I will save the result in this array.
    my @stockInfo;

	if( not $stockInfo  )
	{
		@stockInfo = &stockInfoFresh($tick);
		
		$cache->set( "stockInfo" . $tick, \@stockInfo, "1 hour" );
	}
    else {
        # if FileCache returned something is a reference to an array
        # so now lets dereference it.
        @stockInfo = @{$stockInfo};
    }

	# at this point, $stockInfo[0] is empty

	return @stockInfo;
}


my($tick, $first_let, $name, $exch, $stockid) = &stockInfo($t);


print "$tick $first_let $name $exch $stockid\n";
C05cad8e507792fd5aac221af97dfe26

montoya

October 12, 2007, October 12, 2007 02:53, permalink

No rating. Login to rate!

Thanks Marco, I will definitely follow your advice. I think @{$stockInfo} might be what I was looking for!

Your refactoring





Format Copy from initial code

or Cancel