n v40, ... under Perl 5.6; and $opus->tracks

[email protected] ("Sean M. Burke") Fri, 03 Aug 2001 04:53:32 -0600
Newsgroups perl.midi
Message-ID <[email protected]>
At 09:09 2001-08-03 +0200, Douglas Eck wrote about two problems:

>I'm running version 0.79 under debian linux testing (sid)
>I'm running perl v5.6.1
>[...]
>   use MIDI::Simple;
>   n v40,  n60, n64, n67, d100;
>Perl spits out this error:
>%>perl /tmp/goo.pl
>Unknown note/rest option: "(" at /tmp/goo.pl line 10

Looking at this code, and the code in MIDI::Simple, and the error message,
I was about to declare that the world had GONE MAD.

Until I somehow remembered: 40 is ord '('.  And as of Perl 5.6, the
bareword v40 is a "literal value constructor"!
The short story is to use quotes around v\d+ things:
  n 'v40', n60, ...;

Or if using barewords at all makes you feel dirty (and the BAD kind of
dirty), then you can just use strict, and then merrily say:
  n qw(v40 n60 n64 n67 d100);
or even the delimiter of your choice, as in
  n qw: v40 n60 n64 n67 d100 :;


The long story is this excerpt from perldoc perldata:

A literal of the form v1.20.300.4000 is parsed as a string composed of
characters with the specified ordinals.  This provides an alternative, more
readable way to construct strings, rather than use the somewhat less
readable interpolation form "\x{1}\x{14}\x{12c}\x{fa0}".  This is useful
for representing Unicode strings, and for comparing version "numbers" using
the string comparison operators, cmp, gt, lt etc. If there are two or more
dots in the literal, the leading v may be omitted.
    print v9786;              # prints UTF-8 encoded SMILEY, "\x{263a}"
    print v102.111.111;       # prints "foo"
    print 102.111.111;        # same
Such literals are accepted by both require and use for doing a version
check.  The $^V special variable also contains the running Perl
interpreter's version in this form.  See perlvar/$^V.

[end excerpt of disturbing new feature]


Well, I knew using all those barewords in the MIDI::Simple docs was bound
to catch up with me some day!

Alternate approach:  patch MIDI/Simple.pm line 631, from this:
    } elsif($arg =~ m<^v(\d+)$>s) {   # numeric volume spec
to this:
    } elsif($arg =~ m<^[vV](\d+)$>s) {   # numeric volume spec
and use V40 instead of v40.
Or, as you noted, just have
   $Volume = 40;



I now see there's another similar subtle error lurking:  n/r/noop accept
'm' as 'middle volume', i.e., between 'mp' and 'mf'.  However, if you try
using a bareword m, Perl will interpret it as the start of a RE, like
m/foo/, so this:
  n m, n60, n64,
will parse just like:
  n m/ n60/ n64
i.e., just like:
  n( $_ =~ / 60/ n64)
which will throw an error.
I think m/.../ is quite old syntax (unlike v12.34.56), but I'm pretty sure
I didn't know about it back when I wrote MIDI::Simple.


>Question 2 of 2:
>Under perl 5.6.1 I had a problem with an unblessed variable $track
>I blessed it and everything worked fine. Alas I don't have the
>code to reproduce the error but here is the diff on Opus.pm
>showing the bless performed at line 411:
>
>318 ruchetta /usr/local/lib/site_perl/MIDI>diff Opus.pm Opus.pm~
>411d410
><     bless $track, "MIDI::Track";

That's in $opus->write_to_handle, where it's iterating over:
  foreach my $track (@{ $opus->{'tracks'} }) {

That shouldn't have to happen -- everything in $opus->tracks() should
really already be a MIDI::Track object -- altho I don't actually enforce
this in the 'tracks' accessor method, and I think maybe I should start.
People have written to me before because they were calling
$opus->tracks($foo, $bar) where they thought $foo and $bar were track
objects, but they weren't -- and then only later, in calling
$opus->write_to_file, do they get a confusing error message.

Do you remember if you had, at some point in your code, a line like
$opus->tracks(@things) ?  Or were you doing things only from inside
MIDI::Simple?

And has anyone else seen this error before?


--
Sean M. Burke    [email protected]    http://www.spinn.net/~sburke/