[Bioperl-l] tr/// and eval

simon andrews (BI) simon.andrews@bbsrc.ac.uk
Thu, 10 Oct 2002 15:05:55 +0100


> -----Original Message-----
> From: Pat Schloss [mailto:pds@plantpath.wisc.edu]
> Sent: Thursday, October 10, 2002 1:34 PM
> To: bioperl-l@bioperl.org
> Subject: [Bioperl-l] tr/// and eval
> 
> 
> Hi all, 
> 
> I'm trying to write a program with the simple task of counting the
> number of A's, T's, G's, and C's (and binary combinations of those
> letters, i.e. AA, AG, AC...) in a DNA sequence string. 
> 
> What I'd like to do pretty much expressed in the code below.  The
> problem I'm having is that when I do the tr/// I'm trying to 
> interpolate into the search a different letter of my modified alphabet.  
>
> ${$_} = ($ecoli=~ tr/$_//); 

You have two problems here.  First is the one you spotted which is that tr doesn't interpolate.  For the purpose you described before it is also the wrong tool to use.  tr operates on single characters, and you said you wanted to also spot dinucleotides, so in your case it's better to use the m// construct instead (the m is actually optional).

The other problem is the ${$_} construct.  This is called a symbolic reference - and is a bad thing.  There's (nearly) always a better way to do what you want than using a symref.  For the full details of why, consult the Perl FAQ

perldoc -q 'How can I use a variable as a variable name?'

In your case you'd be better off storing the count in a hash - so try the following code....

#!/usr/bin/perl -w
use strict;

my $ecoli = 'ACGGCGATTATTTGGGGCGGCAATATG';

my %counts;

foreach (qw(A T C G AA GG CC TT)){
  $counts{$_} = () = $ecoli=~/$_/g;
}

foreach (sort keys(%counts)){
  print "$_ occurred $counts{$_} times\n";
}