Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Newbie: Looking for comments on this (working) script

Reply
Thread Tools

Newbie: Looking for comments on this (working) script

 
 
Trebor A. Rude
Guest
Posts: n/a
 
      04-27-2004
I've been trying to learn Perl in recent days, and was hoping the group
could offer some pointers on my first attempt to do something useful (to
me, anyway) with it. To that end, any constructive comments, suggestions,
etc. on this script would be appreciated.

The script takes a list of .ogg files on the command line and reads the tag
information from them (which come out in "key=value" form), then uses it to
construct a command to put the same tag information into a
corresponding .mp3 file (I prefer .oggs for listening on my computer, but
my car's CD player only works with audio or MP3 CDs). Here it is:

#!/usr/bin/perl

use warnings;
use strict;
use vars '$file';

my %options = (title => '-t',
artist => '-a',
album => '-A',
tracknumber => '-T');

sub run_id3v2 (@)
{
my @command = ("id3v2", @_, $file);
return system(@command) == 0;
}

foreach (@ARGV)
{
$file = $_;
my @output = `vorbiscomment -l \Q$file\E 2>&1`;

if ($? != 0)
{
print "Problems reading tags from $file, skipping it:\n", @output;
next;
}

my %comments = map { chomp; split /=/, $_, 2 } @output;

my @arguments = ();

# Also considered using (if this is strange indentation, thank
# cperl-mode):
#
# push @arguments,
# map {($options{$_}, $comments{$_})}
# grep exists $options{$_}, keys %comments;

push @arguments,
map {exists $options{$_} ? ($options{$_}, $comments{$_}) : ()}
keys %comments;

$file =~ s/\.ogg/.mp3/;

run_id3v2('-D') or die "Problem removing old tags from $file.";
run_id3v2(@arguments) or die "Problem adding new tags to $file.";
run_id3v2('-s') or die "Problem removing new id3v1 tags from $file.";
}

 
Reply With Quote
 
 
 
 
Paul Lalli
Guest
Posts: n/a
 
      04-27-2004
On Tue, 27 Apr 2004, Robin wrote:

> > sub run_id3v2 (@)

>
> what's this supposed to do? Which perldoc can I find out in?
>


Do you even *try* before posting here? Gee, it's having to do with a
subroutine, you think *maybe* it might be in the documentation for
subroutines?

perldoc perlsub
it's called a prototype, although this particular one is rather useless.
Can you read the documentation and tell us why, Robin?

Paul Lalli
 
Reply With Quote
 
 
 
 
Paul Lalli
Guest
Posts: n/a
 
      04-27-2004
On Tue, 27 Apr 2004, Robin wrote:

> > > > sub run_id3v2 (@)
> > >
> > > what's this supposed to do? Which perldoc can I find out in?
> > >

> >
> > Do you even *try* before posting here? Gee, it's having to do with a
> > subroutine, you think *maybe* it might be in the documentation for
> > subroutines?
> >
> > perldoc perlsub
> > it's called a prototype, although this particular one is rather useless.
> > Can you read the documentation and tell us why, Robin?

>
> because he really isn't using any references? I scanned the perlsub docs,
> and this is probably wrong, but I have to write a paper.
> -Robin


Almost correct, actually. A prototype of (@) tells perl "Only accept a
list of arguments" (as opposed to something like ($\@), which says "accept
a scalar value followed by an actual named array". But accepting a list
of arguments is the default behavior for Perl subroutines. Therefore,
using a prototype of (@) is no different than not using a prototype at
all. (it is very different, however, from using an empty prototype, like
sub myfunc() )

To clarify, prototypes do not have to have anything to do with references.
They can be used to restrict the number and type of arguments passed to
subroutines. For example:

sub myfunc($$) {

This function will only accept two scalar values. They can be any scalar
values you want, be them strings literals, numeric literals, named scalar
variables, or yes, references. But the following function calls are all
permitted:

myfunc("foo", 'bar');
myfunc(1, $string);
myfunc('', 0);

none of which do any conversions to references. In this case, the
prototype could be in place to cause fatal errors for any of these
function calls:

myfunc ("foo", "bar", "baz");
myfunc (42);
myfunc ();
@ten = (1..10);
myfunc (@ten);


Paul Lalli
 
Reply With Quote
 
Robin
Guest
Posts: n/a
 
      04-27-2004


> sub run_id3v2 (@)


what's this supposed to do? Which perldoc can I find out in?

Thanks,
-Robin



 
Reply With Quote
 
John W. Krahn
Guest
Posts: n/a
 
      04-27-2004
"Trebor A. Rude" wrote:
>
> I've been trying to learn Perl in recent days, and was hoping the group
> could offer some pointers on my first attempt to do something useful (to
> me, anyway) with it. To that end, any constructive comments, suggestions,
> etc. on this script would be appreciated.
>
> The script takes a list of .ogg files on the command line and reads the tag
> information from them (which come out in "key=value" form), then uses it to
> construct a command to put the same tag information into a
> corresponding .mp3 file (I prefer .oggs for listening on my computer, but
> my car's CD player only works with audio or MP3 CDs). Here it is:
>
> #!/usr/bin/perl
>
> use warnings;
> use strict;
> use vars '$file';


You don't really need a $file package variable.


> my %options = (title => '-t',
> artist => '-a',
> album => '-A',
> tracknumber => '-T');
>
> sub run_id3v2 (@)


You don't really need the (@) prototype as that is the default behavior
for subs.


> {
> my @command = ("id3v2", @_, $file);


Without the $file package variable this would be:

my @command = ( 'id3v2', @_ );


> return system(@command) == 0;
> }
>
> foreach (@ARGV)
> {
> $file = $_;


foreach my $file ( @ARGV ) {


> my @output = `vorbiscomment -l \Q$file\E 2>&1`;


You could use chomp() here instead of later in map.

chomp( my @output = `vorbiscomment -l \Q$file\E 2>&1` );


> if ($? != 0)
> {
> print "Problems reading tags from $file, skipping it:\n", @output;
> next;
> }
>
> my %comments = map { chomp; split /=/, $_, 2 } @output;


Without the chomp() this would become:

my %comments = map split( /=/, $_, 2 ), @output;


However, it looks like you are not using anything after the '='.

my @comments = map /^([^=]+)/, @output;


> my @arguments = ();
>
> # Also considered using (if this is strange indentation, thank
> # cperl-mode):
> #
> # push @arguments,
> # map {($options{$_}, $comments{$_})}
> # grep exists $options{$_}, keys %comments;
>
> push @arguments,


You are declaring @arguments and then pushing values into it. Why not
just assign the values when you declare it?

> map {exists $options{$_} ? ($options{$_}, $comments{$_}) : ()}
> keys %comments;


my @arguments =
map {exists $options{$_} ? ($options{$_}, $_) : ()}
@comments;


> $file =~ s/\.ogg/.mp3/;


You probably only want to match /\.ogg/ if it is at the end of $file.

$file =~ s/\.ogg$/.mp3/;


> run_id3v2('-D') or die "Problem removing old tags from $file.";
> run_id3v2(@arguments) or die "Problem adding new tags to $file.";
> run_id3v2('-s') or die "Problem removing new id3v1 tags from $file.";
> }


With $file now local to the foreach loop you need to add it to the
argument list.

run_id3v2( '-D', $file ) or die "Problem removing old tags from
$file.";
run_id3v2( @arguments, $file ) or die "Problem adding new tags to
$file.";
run_id3v2( '-s', $file ) or die "Problem removing new id3v1 tags from
$file.";
}


HTH

John
--
use Perl;
program
fulfillment
 
Reply With Quote
 
Robin
Guest
Posts: n/a
 
      04-27-2004
> > > sub run_id3v2 (@)
> >
> > what's this supposed to do? Which perldoc can I find out in?
> >

>
> Do you even *try* before posting here? Gee, it's having to do with a
> subroutine, you think *maybe* it might be in the documentation for
> subroutines?
>
> perldoc perlsub
> it's called a prototype, although this particular one is rather useless.
> Can you read the documentation and tell us why, Robin?


because he really isn't using any references? I scanned the perlsub docs,
and this is probably wrong, but I have to write a paper.
-Robin





 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      04-28-2004
On Tue, 27 Apr 2004, Robin wrote:

> "Paul Lalli" <(E-Mail Removed)> wrote in message
> >
> > Almost correct, actually. A prototype of (@) tells perl "Only accept a
> > list of arguments" (as opposed to something like ($\@), which says "accept
> > a scalar value followed by an actual named array". But accepting a list
> > of arguments is the default behavior for Perl subroutines. Therefore,
> > using a prototype of (@) is no different than not using a prototype at
> > all. (it is very different, however, from using an empty prototype, like
> > sub myfunc() )
> >
> > To clarify, prototypes do not have to have anything to do with references.
> > They can be used to restrict the number and type of arguments passed to
> > subroutines. For example:
> >
> > sub myfunc($$) {
> >
> > This function will only accept two scalar values. They can be any scalar
> > values you want, be them strings literals, numeric literals, named scalar
> > variables, or yes, references. But the following function calls are all
> > permitted:
> >
> > myfunc("foo", 'bar');
> > myfunc(1, $string);
> > myfunc('', 0);
> >
> > none of which do any conversions to references. In this case, the
> > prototype could be in place to cause fatal errors for any of these
> > function calls:
> >
> > myfunc ("foo", "bar", "baz");
> > myfunc (42);
> > myfunc ();
> > @ten = (1..10);
> > myfunc (@ten);
> >
> >
> > Paul Lalli

>
> Thanks, that's way more clear than the perldoc, in my humble opinion.
>
> Basically to clarify your intitial question, this prototype doesn't do
> anything because the arguments for a subroutine are already an array, @_,
> correct?
>


On the right track, but your wording can quickly lead to incorrectness.
All subroutine's arguments are always passed into the array @_, regardless
of prototype. A prototype decides how many and what kind of arguments
will be allowed into that array. For example
sub f1($@);
declares f1 to be a subroutine that will accept a single scalar followed
by a list of values. Valid calls for this subroutine include:
f1($foo, @bar);
f1("hello", "world");
f1("hello", "how", "are", "you?");
f1(@arr1, $scal);

In this last case, the prototype would cause @arr1 to be automatically
referenced, and the remaining list would contain soley $scal. So in the
function @_ would contain two elements - a reference to @arr1, and an
alias to $scal.

If you read the section on prototypes, it will tell you what each
identifier means. $ is any scalar value, \$ is a named scalar variable, @
is a list of values, \@ is a named array variable, etc.

From this, you can see that @ is something of a catch-all, because in
Perl, any sequence of values is a list. In the same way that
(@foo, @bar) = (1..10);
will cause @foo to contain 1 through 10, and @bar to contain nothing,
sub foo($@@)
is nonsensical because the first list identifier already covers any
following values. In the general case then, it makes no sense for @ to
come anywhere but the last identifier in a prototype. In the specific
case of sub foo (@);, the prototype isn't doing anything special - it's
just saying "take a list of values" which is exaclty what all perl
subroutines do anyway.

Is that clearer, or did I just muddy the explanation?

> One question, and I don't think this is in the perldoc perlsub, although I
> still haven't fully covered it, but can a subroutine, with strict in use, be
> called without parantheses in a script that's not a module after it has it's
> prototype? Or that's not a subroutine imported from a module?


Parentheses have little to nothing to do with a prototype. However,
giving a subroutine a prototype requires that the compiler can see the
prototype before the subroutine is called. For example, this code
generates a warning:

foo ("bar", "baz");

sub foo(\@$){
print "In foo: $_[0], $_[1]\n";
}

In this case, the parser couldn't tell before you called foo() that foo()
had a prototype it should check. So it outputted a warning and continued,
ignoring the prototype.

You are, btw, allowed to predeclare subroutines before defining them:

sub foo(\@$);

foo ("bar", "baz");

sub foo (\@$){
print "In foo: $_[0], $_[1]\n";
}

This code will now generate a fatal error telling you you didn't properly
call foo(). The use of parentheses in calling the subroutine is optional,
because the subroutine was predeclared. (This is standard procedure for
all subroutines, and is unaffected by the use of prototypes).

I hope that's clear,
Paul Lalli
 
Reply With Quote
 
Robin
Guest
Posts: n/a
 
      04-28-2004

"Paul Lalli" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Tue, 27 Apr 2004, Robin wrote:
>
> > > > > sub run_id3v2 (@)
> > > >
> > > > what's this supposed to do? Which perldoc can I find out in?
> > > >
> > >
> > > Do you even *try* before posting here? Gee, it's having to do with a
> > > subroutine, you think *maybe* it might be in the documentation for
> > > subroutines?
> > >
> > > perldoc perlsub
> > > it's called a prototype, although this particular one is rather

useless.
> > > Can you read the documentation and tell us why, Robin?

> >
> > because he really isn't using any references? I scanned the perlsub

docs,
> > and this is probably wrong, but I have to write a paper.
> > -Robin

>
> Almost correct, actually. A prototype of (@) tells perl "Only accept a
> list of arguments" (as opposed to something like ($\@), which says "accept
> a scalar value followed by an actual named array". But accepting a list
> of arguments is the default behavior for Perl subroutines. Therefore,
> using a prototype of (@) is no different than not using a prototype at
> all. (it is very different, however, from using an empty prototype, like
> sub myfunc() )
>
> To clarify, prototypes do not have to have anything to do with references.
> They can be used to restrict the number and type of arguments passed to
> subroutines. For example:
>
> sub myfunc($$) {
>
> This function will only accept two scalar values. They can be any scalar
> values you want, be them strings literals, numeric literals, named scalar
> variables, or yes, references. But the following function calls are all
> permitted:
>
> myfunc("foo", 'bar');
> myfunc(1, $string);
> myfunc('', 0);
>
> none of which do any conversions to references. In this case, the
> prototype could be in place to cause fatal errors for any of these
> function calls:
>
> myfunc ("foo", "bar", "baz");
> myfunc (42);
> myfunc ();
> @ten = (1..10);
> myfunc (@ten);
>
>
> Paul Lalli


Thanks, that's way more clear than the perldoc, in my humble opinion.

Basically to clarify your intitial question, this prototype doesn't do
anything because the arguments for a subroutine are already an array, @_,
correct?

One question, and I don't think this is in the perldoc perlsub, although I
still haven't fully covered it, but can a subroutine, with strict in use, be
called without parantheses in a script that's not a module after it has it's
prototype? Or that's not a subroutine imported from a module?

Thanks,

--
Regards,
-Robin
--
[ webmaster @ infusedlight.net ]
www.infusedlight.net







 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      04-28-2004

Quoth Paul Lalli <(E-Mail Removed)>:
>
> sub f1($@);
> declares f1 to be a subroutine that will accept a single scalar followed
> by a list of values. Valid calls for this subroutine include:
> f1($foo, @bar);
> f1("hello", "world");
> f1("hello", "how", "are", "you?");
> f1(@arr1, $scal);
>
> In this last case, the prototype would cause @arr1 to be automatically
> referenced, and the remaining list would contain soley $scal. So in the
> function @_ would contain two elements - a reference to @arr1, and an
> alias to $scal.


Not true. A prototype of $ causes that argument to be evaluated in
scalar context, i.e.

f1(@arr1, $scal);

is equivalent to

f1(scalar(@arr1), $scal);

which means that the first argument will be the *length* of the array,
not a ref to it.

Ben

--
Razors pain you / Rivers are damp
Acids stain you / And drugs cause cramp. [Dorothy Parker]
Guns aren't lawful / Nooses give
Gas smells awful / You might as well live. http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      04-28-2004
On Wed, 28 Apr 2004, Ben Morrow wrote:

> Quoth Paul Lalli <(E-Mail Removed)>:
> >
> > sub f1($@);
> > declares f1 to be a subroutine that will accept a single scalar followed
> > by a list of values. Valid calls for this subroutine include:
> > f1($foo, @bar);
> > f1("hello", "world");
> > f1("hello", "how", "are", "you?");
> > f1(@arr1, $scal);
> >
> > In this last case, the prototype would cause @arr1 to be automatically
> > referenced, and the remaining list would contain soley $scal. So in the
> > function @_ would contain two elements - a reference to @arr1, and an
> > alias to $scal.

>
> Not true. A prototype of $ causes that argument to be evaluated in
> scalar context, i.e.
>
> f1(@arr1, $scal);
>
> is equivalent to
>
> f1(scalar(@arr1), $scal);
>
> which means that the first argument will be the *length* of the array,
> not a ref to it.


Whoops. You are correct of course. My apologies for the faulty
information. I should double check what I type when trying to inform
someone.

Paul Lalli
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: [SI] Looking Up/Looking Down, The 'Duck Comments Rob Digital Photography 0 03-19-2013 06:51 AM
[SI] Looking Up/Looking Down is UP! -- Comments Rob Digital Photography 2 03-19-2013 06:38 AM
Re: [SI] Looking Up/Looking Down, The 'Duck Comments Tony Cooper Digital Photography 0 03-19-2013 04:20 AM
A program to replace all JS comments with JSP comments in jsp files tungchau81@yahoo.com Java 0 06-02-2006 06:35 AM
Newbie Looking for Advice/Comments on Script dgp@dodgeit.com Perl Misc 1 02-02-2005 06:29 PM



Advertisments