runrig's Journal http://use.perl.org/~runrig/journal/ runrig's use Perl Journal en-us use Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners. 2012-01-25T02:14:33+00:00 pudge pudge@perl.org Technology hourly 1 1970-01-01T00:00+00:00 runrig's Journal http://use.perl.org/images/topics/useperl.gif http://use.perl.org/~runrig/journal/ Gearman fun and frustration http://use.perl.org/~runrig/journal/40265?from=rss <p>I've been using <a href="http:///">Gearman</a> a lot lately with <a href="http://search.cpan.org/dist/Gearman-XS/">Gearman::XS</a>. In an effort to reduce boilerplate, I've released <a href="http://search.cpan.org/dist/GearmanX-Starter/">GearmanX::Starter</a> to launch Gearman workers.</p><p>Other features of the module are signal handling, where if a worker gets a SIGTERM, it'll finish any current task before terminating. To get this to work, I had to use Perl::Unsafe::Signals, otherwise you could not terminate the process while the worker was waiting for a job. It would only terminate after getting a new task from the server (causing the task to fail).</p><p>I had an interesting issue converting a worker script to using my GX::S module though...One line had <code>$job-&gt;send_complete(1);</code> which tells gearman to send the result "1" and a status of "complete" to the client. However, I was getting an error of "gearman_con_flush:write:14" when the worker was trying to wait for the next job. This didn't happen before I started using GX::S, but it was fixed when I changed the code to <code>$job-&gt;send_complete("1");</code> (with quotes). I can not come up with a simple test case, but just in case someone else has the same issue, here's the possible work around.</p><p>Update: This is with Gearman::XS 0.7. It doesn't seem to occur with 0.8, so perhaps it's time to upgrade<nobr> <wbr></nobr>:-)</p> runrig 2010-03-24T18:24:03+00:00 journal Runrig's thousand island salad bar dressing http://use.perl.org/~runrig/journal/39868?from=rss <p>I haven't seen any recipe posts for quite a while (perhaps for good reason), so I'll go ahead and break that streak.</p><p>Ever been to a salad bar where you pay by the ounce (or whatever unit of weight your locality uses)? And then they also make you weigh the salad dressing with the rest of the salad, adding $0.50-$1.00 or more to the cost? Well, say no more! Just go over to the condiments, grab 4 packets of mayo, 2 packets of relish, and 2 packets of ketchup (adjust packets to taste), blend together w/your fork, and enjoy w/your salad.</p><p>I don't know how economical this is if they charge 5-10p (as they sometimes did last time I was in the UK) for condiment packets. And if they don't make you weigh the salad dressing, why are you putting it on <em>before</em> weighing it? 8-)</p> runrig 2009-11-09T23:48:21+00:00 journal Still no Strawberry for me http://use.perl.org/~runrig/journal/39447?from=rss <p>I'd really like to try out <a href="http://strawberryperl.com/">Strawberry Perl</a>, but it'll have to wait 'till I get around to installing it at home, where I do a lot less perl than at work. 'Cuz you need admin rights to install strawberry, and they don't hand that out for work laptops.</p><p> <a href="http://www.activestate.com/">ActiveState Perl</a>, on the other hand, does install without admin privs, though with some caveats. ".pl" files don't get associated with Perl, and the global PATH does not get updated.</p><p>So, a few workarounds. I create a shortcut to "cmd.exe" that executes <code>%SystemRoot%\system32\cmd.exe<nobr> <wbr></nobr>/v:on<nobr> <wbr></nobr>/s<nobr> <wbr></nobr>/k "set PATH=C:\bin;C:\msys\1.0\bin;C:\Perl\site\bin;C:\Perl\bin;!PATH!"</code>, which sets the path to all my favorite places before starting up "cmd.exe". And since you can't doubleclick on a ".pl" file to run it (file extension association, remember?), the pl2bat program becomes more useful, except that it doesn't work, because PATH is not set, so you have to add the path to perl.exe inside the pl2bat program. Last (though not due to admin issues), you need to set the HTTP_PROXY environment variable ('http://user:password@proxyhost', if it's authenticated, which it is for me) for ppm to work, except that it so happens that in my case, setting HTTP_PROXY interferes with Informatica, so I set it in a BEGIN block inside the ppm program itself.</p> runrig 2009-08-11T17:54:00+00:00 journal Perl, SSH, and Windows http://use.perl.org/~runrig/journal/39346?from=rss <p>It's been a while since I've used SSH...most companies I've worked at just use plain telnet. And SSH is one of those things that once set up, you forget about, so you keep having to relearn it. I got two logins set up with public key auth, but a third would only work with a password. I finally learned about the StrictModes setting in the sshd config...the permissions on my home directory were 777. Changed it to not be world-writable and now the public key auth works.</p><p>And I've set up my work provided Windows laptop with Perl (of course), Vim, MSYS, and Firefox. I wanted to automate some SFTP file transfers, and was not having any luck/progress with Net::SFTP or Net::SFTP::Foreign and their dependencies. Then a post on perlmonks directed me to Net::SSH2, which does ssh, scp, and sftp. Net::SSH2 is definitely the easiest to get working on Windows.</p> runrig 2009-07-24T16:39:35+00:00 journal New Job http://use.perl.org/~runrig/journal/39345?from=rss I haven't said anything about it here, but I've been out of work for a while. Until recently. And I don't even have to relocate or commute 100 miles...the new job is just down the street from the old job. In retrospect, I'm glad I didn't get those other positions I interviewed for, even though I was completely qualified for them, and at the time, I thought I really wanted them<nobr> <wbr></nobr>:-) It's like Adam Corolla said during his last radio show..."It's all for the best...eventually" runrig 2009-07-24T16:02:01+00:00 journal Support gauntlet http://use.perl.org/~runrig/journal/38675?from=rss <p> When you're able to re-create a bug in a 3rd party app, you may think that the hard part is over. Just submit your bug to support, along with a test case, and you're done. </p><p>Nope.</p><p>Now you need to get the first-level support to understand what the problem is, and is not. Then you need to explain to the 2nd level support what the problem is, and is not. Then you need to get them to actually follow the instructions in your test case. The test case involved perl. It was my mistake assuming that they actually know how to use perl. I'm pretty sure that they do use perl, but when they ask "Can you send us the DBI library", I have doubts. I'm still waiting for them to tell me that it's a feature, not a bug. </p> runrig 2009-03-20T20:29:57+00:00 journal Blowing your stack on exit http://use.perl.org/~runrig/journal/38627?from=rss I seriously doubt you'll ever have to worry about this in "real" code, but some comments last night at a talk about "Garbage Collection" got me thinking. The comments were to the effect of how, once, some perl program had lots of data structures and took a "long time" to exit because it first had to clean up all the reference counts. So I tried to come up with a worst case, and threw this together to make a ref to a ref to a ref etc...and was surprised by the result. It didn't take all that long to exit when n was 1 million, but when I bumped it to 2 million, I got a core dump, not when trying to build the data structure, but when the program was exiting. Well, yeah, duh, I guess the reference (un)counting is recursive<nobr> <wbr></nobr>:-)<blockquote><div><p> <tt>my $n = 2_000_000;<br> <br>my $s = "hello";<br>my $t = deepref(\$s, $n);<br>print "Made ref: ";<br>my $p = scalar(&lt;STDIN&gt;);<br> <br>sub deepref {<br>&nbsp; my ($s,$n) = @_;<br>&nbsp; my $r = \$s;<br>&nbsp; for (1..$n) {<br>&nbsp; &nbsp; my $t = $$r;<br>&nbsp; &nbsp; $r = \\$t;<br>&nbsp; }<br>&nbsp; return $r;<br>}</tt></p></div> </blockquote> runrig 2009-03-10T17:34:05+00:00 journal Friends don't let friends... http://use.perl.org/~runrig/journal/38101?from=rss ...make the homepage of their company website:<blockquote><div><p> <tt>&lt;SCRIPT language="javascript"&gt;<br>&nbsp; &nbsp; window.location.href="home/";<br>&lt;/SCRIPT&gt;</tt></p></div> </blockquote><p>Really, if you want to tell everyone how wonderful your company is, it should be at least just a little bit functional without JavaScript. I wonder if they'll care...</p> runrig 2008-12-16T18:20:25+00:00 journal Saving the planet (and some $$$) http://use.perl.org/~runrig/journal/37564?from=rss <p>Update: I've decided the sub-title of this post is "I still don't want a pickle: s/motor/bi/"</p><p>It's about an 8 mile drive to work, and I decided that it was time to see about riding my bike instead. And there's all sorts of reasons for doing it, and people ask ("But what about...") about all sorts of reasons for not doing it. But the biggest reason is that instead of dreading the drive home and wondering if I should take the freeway or surface streets (and not caring much more about the trip <em>to</em> work), I actually look forward to the commute, each way, whether it's cold and foggy, or hot and sweltering (I'm not yet prepared for rain, so I'll drive if that's the case, 'cuz you know that in Southern California we're afraid of melting if it rains, even a little).</p> runrig 2008-09-28T17:47:16+00:00 journal I Don't Want A Pickle http://use.perl.org/~runrig/journal/37563?from=rss <p>Once upon a time <a href="http://en.wikipedia.org/wiki/Marine_Corps_Air_Station_El_Toro">there was a marine base</a>. And it was decommissioned. And there was some discussion over what to do with the space left by the decommissioned marine base. Some people wanted an airport, some people wanted a park. There was a vote. <a href="http://www.ocgp.org/gpb/default.asp">And the park people won.</a> </p><p>And <a href="http://www.arlo.net/">Arlo Guthrie</a> <a href="http://www.ocgp.org/news/displaynews.asp?NewsID=116">played</a> while a big orange balloon went up and down. And everyone who "thought that guy was dead"[1] got to hear Alice's Restaurant (for free!), and lots of other songs and stories, and it was funny, and entertaining, and a wonderful time was had by all. But we didn't get there early enough to get passes for the Orange Balloon<nobr> <wbr></nobr>:-(</p><p>So a few weeks later, we went back earlier to get passes, rode the Orange Balloon, and listened to some more music (a <a href="http://www.petejacobsbands.com/">"Wartime Radio Revue"</a>, which was cool, but not Arlo Guthrie...<nobr> <wbr></nobr>:-), and a wonderful time was had by all (again)<nobr> <wbr></nobr>:-)</p><p>[1] I called my wife Friday morning when I heard on the radio about the show:</p><ul> <li>Me: "Hey, Arlo Guthrie is playing tomorrow night"</li> <li>Her: "Isn't he dead?"</li> </ul><p>The first thing he said onstage was "I bet some of you heard about this and said "I thought that guy was dead..."</p> runrig 2008-09-28T17:37:13+00:00 journal PowerCenter XML http://use.perl.org/~runrig/journal/37562?from=rss <p>Everyone I talk with says that mucking with the XML exported by Informatica's PowerCenter is not recommended, or that they tried and failed...so I had no choice but to ignore that advice when we were upgrading from version 7 to 8. I think the advice must be from people who don't quite know what they're doing, and/or "parse" with grep/awk/sed.</p><p>I've been messing with more XML in the last few weeks than I have in the last few years. <a href="http://stackoverflow.com/questions/51198/what-etl-tool-do-you-use#67784">I have my own (shared) opinion about Informatica/ETL</a> (and I've taken up <a href="http://use.perl.org/~Aristotle/journal/37454">Aristotle's call to action</a>), but at least it provides an opportunity to practice some XML-fu. Most transformations were simple changing of some attributes, but there was one issue where after importing into v8, if you delete a group from a Union transformation, the GUI crashes. So I created a Union transformation from scratch, exported it, and compared it to what I was importing, and hey, there was some stuff missing! So I wrote the following:</p><blockquote><div><p> <tt>&nbsp; # Fix Union transformations<br>&nbsp; my $union_cnt;<br>&nbsp; for my $trans (<br>&nbsp; &nbsp; $root-&gt;findnodes(q[<br>&nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>//TRANSFORMATION[@TYPE="Custom Transformation" and @TEMPLATENAME="Union Transformation"]<br>&nbsp; &nbsp; ])<br>&nbsp; ) {<br>&nbsp; &nbsp; $union_cnt++;<br>&nbsp; &nbsp; my $name = $trans-&gt;getAttribute('NAME');<br>&nbsp; &nbsp; my $parent = $trans-&gt;parentNode();<br>&nbsp; &nbsp; print "X: Fixing Union transformation $name\n";<br>&nbsp; &nbsp; my @output;<br>&nbsp; &nbsp; for my $field (<br>&nbsp; &nbsp; &nbsp; $trans-&gt;findnodes(q[<br>&nbsp; &nbsp; &nbsp; &nbsp; TRANSFORMFIELD[@GROUP="OUTPUT"]/@NAME<br>&nbsp; &nbsp; &nbsp; ])<br>&nbsp; &nbsp; ) {<br>&nbsp; &nbsp; &nbsp; push @output, $field-&gt;value();<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; my %dep;<br>&nbsp; &nbsp; my $dep_cnt;<br>&nbsp; &nbsp; for my $field (<br>&nbsp; &nbsp; &nbsp; $trans-&gt;findnodes(q[<br>&nbsp; &nbsp; &nbsp; &nbsp; TRANSFORMFIELD[@PORTTYPE="INPUT"]<br>&nbsp; &nbsp; &nbsp; ])<br>&nbsp; &nbsp; ) {<br>&nbsp; &nbsp; &nbsp; my $name&nbsp; = $field-&gt;getAttribute('NAME');<br>&nbsp; &nbsp; &nbsp; my $group = $field-&gt;getAttribute('GROUP');<br>&nbsp; &nbsp; &nbsp; my $dep_group = $output[$dep{$group}++];<br>&nbsp; &nbsp; &nbsp; my $new = $trans-&gt;addNewChild( '', 'FIELDDEPENDENCY' );<br>&nbsp; &nbsp; &nbsp; $new-&gt;setAttribute( 'INPUTFIELD', $name );<br>&nbsp; &nbsp; &nbsp; $new-&gt;setAttribute( 'OUTPUTFIELD', $dep_group );<br>&nbsp; &nbsp; }<br>&nbsp; }<br>&nbsp; $_-&gt;unbindNode() for $root-&gt;findnodes('//text()');</tt></p></div> </blockquote><p>Warning: this code is not endorsed or guaranteed by anyone for anything!</p><p> The removing of all text nodes was so that the result would stay pretty-printed after output (is there a better/easier way?):</p><blockquote><div><p> <tt>&nbsp; eval { $doc-&gt;toFile($file, 1) } or die "Could not write to $file: $@";</tt></p></div> </blockquote><p>And there are no text nodes with anything but whitespace anyway. XML::LibXML seemed hard to use at first, but once you get used to how the docs are arranged (and learn some XPath), it's quite easy.</p> runrig 2008-09-28T17:18:01+00:00 journal Suck followup http://use.perl.org/~runrig/journal/37560?from=rss It may not have been blogged about in the most diplomatic way, but to follow up on <a href="http://use.perl.org/~runrig/journal/37136">my previous post</a>, I followed <a href="http://use.perl.org/comments.pl?sid=40595&amp;cid=64328">btilly's diplomatic advice</a> pretty much, and found out that the code was written by a college intern, who was now gone, but a couple of other developers were now reponsible for maintaining (or rewriting) it, and were glad to get some advice and feedback. runrig 2008-09-28T16:46:53+00:00 journal You suck or silence? http://use.perl.org/~runrig/journal/37136?from=rss When someone posts a "utility" on the company intraweb, and it's perl, and it's about 900 lines long, with no strict or warnings, has no indentation, needlessly builds strings and splits to an array when qw() would've been appropriate, needlessly uses ".*" in regular expressions, (mis)uses subroutine prototypes, has lots of repeated code that could be factored into subroutines, and lots of other things you'd expect to see in the sort of code that has all the previous issues, <em>and you've already written a library to do the same thing</em> and more (in fewer lines...though slightly more if you count the documentation), what do you do? runrig 2008-08-09T02:17:40+00:00 journal Novell Netware checksum http://use.perl.org/~runrig/journal/37015?from=rss <p>Dear lazyweb,</p><p>When I rightclick on a file on my work Windows system and go to File-Properties, there's a "NetWare Version" tab which has a "View Version, Copyright, and Check Sum Info" button. When you click that, you get a 48-bit checksum of the file in hex. Does anyone know how this checksum is calculated, or even how to find an external exe to run (or a dll and how to use it) to get this value? I've tried comparing the value against as many known checksum algorithms as possible before tearing my hair out.</p><p>Update: and why I want this? We are currently required to enter this value into some document, and the only way to cut n paste it is via screen copy...you can not copy just the text.</p><p>Update: nevermind...we have switched to using <a href="http://sourceforge.net/projects/jacksum/">Jacksum</a>.</p> runrig 2008-07-25T23:00:54+00:00 journal So long its been good to know you http://use.perl.org/~runrig/journal/36804?from=rss The internet is a strange universe where we mostly know one another (or don't really know one another) through bits and bytes and blog entries and email. It was through <a href="http://www.perlmonks.org/">PerlMonks</a> that I first knew of <a href="http://use.perl.org/~VSarkiss">VSarkiss</a>, and found that he lived relatively nearby, and we met up once. It was about a year ago (more or less) that he came to be working at the same place I was through a different consulting agency (though it's a big company so I didn't see him much). Then he disappeared, I emailed him and never heard back, and finally just recently I got around to asking someone about him, and was told that he passed away. So long Vahe...<nobr> <wbr></nobr>:'-( runrig 2008-06-29T01:05:03+00:00 journal Building perl and libs on HP-UX http://use.perl.org/~runrig/journal/35908?from=rss I must keep this somewhere in one place semi-permanent...boring stuff plus hoops to jump through to get XML(LibXML and LibXSLT), and DBD::Oracle and DBD::Sybase working on HP-UX (I have no explanation for having to run 'perl Makefile.PL' over and over). I don't remember if I needed to use 'chatr' to change some of the shared libraries to get them to load:<blockquote><div><p> <tt>----------------------------------------<br>Notes on Building perl 5.10.0 and various<br>libraries on HP-UX (11.11)<br> <br>All of the following was installed under<br>/users/foo<br>Adjust all prefix parameters accordingly<br>to install in another directory (or remove<br>to install in default location).<br>----------------------------------------<br> <br>First perl itself:<br> <br>&gt; which cc<br>must be<nobr> <wbr></nobr>/opt/softbench/bin/cc compiler<br>(default HP<nobr> <wbr></nobr>/usr/bin/cc compiler will not work)<br>(gcc compiler can work, but everything here was done<br>with softbench compiler).<br> <br># Add prefix to install in non-standard path<br>sh Configure -Dprefix=/users/foo<br> <br>keep default of building non-threaded perl, but<br>add '-lcl -lpthread' to beginning of libraries to include.<br>(So that DBD::Oracle will build dynamically later).<br> <br>make<br>make test<br>make install<br> <br>----------------------------------------<br>XML::LibXML and XML::LibXSLT:<br>----------------------------------------<br>First install shared libraries:<br> <br>install binaries of zlib(libz), iconv, and gettext<br>libraries, unless you really feel like building them<br>(install in local directory if necessary..e.g./users/foo/lib<br>and include files in<nobr> <wbr></nobr>/users/foo/include).<br> <br>Build source for libxml library:<br>Set env variables:<br>export CC=cc<br>export LDFLAGS="-L/users/foo/lib -I/users/foo/include"<br> <br>./configure --prefix=/users/foo --without-threads --without-thread-alloc --with-iconv=/users/foo --with-zlib=/users/foo<br> <br>make<br>make install<br> <br># Fix permission on config info file:<br>chmod +x<nobr> <wbr></nobr>/users/foo/bin/xml2-config<br> <br>----------------------------------------<br>Build source for libxslt library:<br>Set env variables:<br>export CC=cc<br>export LDFLAGS="-L/users/foo/lib -I/users/foo/include"<br> <br>./configure --prefix=/users/foo<br>make<br>make install<br> <br># Fix permission on config info file:<br>chmod +x<nobr> <wbr></nobr>/users/foo/bin/xslt-config<br> <br>----------------------------------------<br>Build source for XML::LibXML::Common:<br>perl Makefile.PL<br>&nbsp; (doesn't always work first time..repeat until Makefile is created)<br> <br>make<br>make test<br>make install<br> <br>----------------------------------------<br>Build source for XML::NamespaceSupport:<br> <br>perl Makefile.PL<br>make<br>make test<br>make install<br>----------------------------------------<br>Build source for XML::SAX:<br> <br>perl Makefile.PL<br>make<br>make test<br>make install<br>----------------------------------------<br>Build source for XML::LibXML:<br> <br>perl Makefile.PL (repeat until Makefile is created)<br>make<br>make test<br>make install<br>----------------------------------------<br>Build source for XML::LibXSLT:<br> <br>Change the following lines (this might be fixed in a future<br>version):<br>#xsystem("$Config{make} $file test 'OTHERLDFLAGS=$opt'");<br>xsystem("$Config{make} $file test");<br> <br>#$result = try_link(&lt;&lt;"SRC", $libs);<br>$result = try_link(&lt;&lt;"SRC", undef);<br> <br>perl Makefile.PL LIBS=-L/users/foo/lib INC="-I/users/foo/include -I/users/foo/include/libxml2"<br>make<br>make test<br>&nbsp; (a couple of tests, e.g. exslt tests, will fail, install exslt library<br>&nbsp; if you need exslt)<br>make install<br>----------------------------------------<br>Build source for DBI<br> <br>perl Makefile.PL<br>make<br>make test (many tests are skipped)<br>make install<br>----------------------------------------<br>Build source for DBD::Oracle (1.20)<br> <br>perl Makefile.PL<br> <br>edit Makefile:<br># Look for<br>$(LD) -Wl,+b"$(LD_RUN_PATH)"&nbsp; $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB)&nbsp; \<br># Remove "-Wl,"<br>$(LD) +b"$(LD_RUN_PATH)"&nbsp; $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB)&nbsp; \<br> <br>make<br>make test<br>&nbsp; (many 'connects' fail unless you set env vars for a test db)<br>&nbsp; (many charset tests skipped on old versions of Oracle)<br>make install<br>----------------------------------------<br>Build source for DBD::Sybase (1.08)<br> <br>Edit Sybase.pm:<br># Look for:<br>sub dl_load_flags { if($^O eq 'aix') { 0x00 } else { 0x01 }}<br># Change to:<br>sub dl_load_flags { if($^O eq 'aix') { 0x00 } else { 0x00 }}<br> <br>update: patch to display line numbers on RaiseError:<br>***<nobr> <wbr></nobr>../DBD-Sybase-1.08/dbdimp.c Thu Apr 19 11:31:19 2007<br>--- dbdimp.c&nbsp; &nbsp; Thu Jun 19 14:09:45 2008<br>***************<br>*** 545,550 ****<br>--- 545,551 ----<br>&nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retcode = CS_SUCCEED;<br> <br>+&nbsp; &nbsp; &nbsp; &nbsp;sv_catpv(DBIc_ERRSTR(imp_dbh), " ");<br>&nbsp; &nbsp; &nbsp; &nbsp; return retcode;<br>&nbsp; &nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; if(srvmsg-&gt;msgnumber) {<br> <br>perl Makefile.PL (prompts for test server/db and user/passwd)<br>make<br>make test<br>make install</tt></p></div> </blockquote> runrig 2008-03-14T21:53:01+00:00 journal Hey buddy http://use.perl.org/~runrig/journal/35784?from=rss I received a pleasant surprise when I got home today. "Close your eyes and hold out your hands," my wife and daughter said. A new CD. For me<nobr> <wbr></nobr>:) And I'd never heard of it. I really like Ry Cooder, but I haven't been paying attention lately to what he's been doing, so <a href="http://en.wikipedia.org/wiki/My_Name_Is_Buddy">My Name Is Buddy</a> was a complete revelation. It's great...there's a song about a pig named J. Edgar Hoover (uh huh, it's just about the pig, yeah, right). There's a socially relevant story line about a cat, a mouse, and a toad...but I'm just going to enjoy the music for the first 3 or 4 or 7 listens. And it's got two (count'em!), Two Seegers playing on the album. And in a great confluence of synergistic coincidence, there was a great show on PBS tonight about Pete Seeger ("The Power of Music"). If anyone can stop a war with a banjo, he can<nobr> <wbr></nobr>:-) runrig 2008-02-28T07:40:05+00:00 journal Local "network" printer http://use.perl.org/~runrig/journal/35716?from=rss <p>My wife just bought a Dell laptop with Windows Vista...the Desktop is Windows XP with a printer connected directly to it, and the printer was configured to be "shared". Tried to get the printer working from the laptop...click "add a printer", then "Is this a local or network printer?". Well, it's on the network, it sure doesn't seem local, but the network discovery thing doesn't find it, and you get "Access Denied" when trying to connect to it. Google, google, and low and behold, it's really a "local" printer, though you do give it the "\\systemname\printername" path in one of the entry fields.</p><p>Very intuitive. Also, the salesman who was trying to sell us another printer when buying the laptop was telling us "the old printer probably won't work...there probably no printer driver for Vista...". BS.</p><p>Of course, my wife needed something printed out right now because she was going out right now, and another option was to export the Word document to PDF, and email it to ourselves and print it out at the other computer. But Word didn't natively export to PDF, you had to install a Microsoft Plug-in for that, and you needed the "validation code" that came with word to install it, and we didn't have that handy. Eventually, I did also install <a href="http://sourceforge.net/projects/pdfcreator">PDFCreator</a>, but that was around the same time I found out about the "Local Printer" thing.</p><p>What would we do without the internet? Spend useless hours on hold with Technical Support probably.</p> runrig 2008-02-21T17:39:14+00:00 journal XSLT sort puzzle http://use.perl.org/~runrig/journal/35426?from=rss <p>Following up on <a href="http://use.perl.org/~runrig/journal/33883">previous XML sorting efforts</a>, where I mostly wanted to sort by tag name, then by NAME attribute, but for some elements, there were other attributes that I wanted to sort by. I first did the tag_name/NAME_attribute sort with <a href="http://search.cpan.org/dist/XML-Filter-XSLT">XML::Filter::XSLT</a> then sorted by the other odd elements using <a href="http://search.cpan.org/dist/XML-Filter-Sort">XML::Filter::Sort</a>. </p><p>Out of curiosity, I wanted to try to do it all with XSLT, so I came up with:</p><blockquote><div><p> <tt>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br>&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"<br>&nbsp; &nbsp; &nbsp;version="1.0"&gt;<br> <br>&lt;xsl:output method="xml" version="1.0"<br>encoding="iso-8859-1" indent="yes" omit-xml-declaration="no"/&gt;<br> <br>&lt;xsl:template match="/"&gt;<br>&nbsp; &lt;xsl:copy&gt;<br>&nbsp; &nbsp; &lt;xsl:apply-templates/&gt;<br>&nbsp; &lt;/xsl:copy&gt;<br>&lt;/xsl:template&gt;<br> <br>&lt;xsl:template match="//*"&gt;<br>&nbsp; &lt;xsl:copy&gt;<br>&nbsp; &nbsp; &lt;xsl:apply-templates select="@*"/&gt;<br> <br>&nbsp; &nbsp; &lt;xsl:apply-templates select="D"&gt;<br>&nbsp; &nbsp; &nbsp; &lt;xsl:sort select="@FOO"/&gt;<br>&nbsp; &nbsp; &lt;/xsl:apply-templates&gt;<br> <br>&nbsp; &nbsp; &lt;xsl:apply-templates select="*[not(self::D)]"&gt;<br>&nbsp; &nbsp; &nbsp; &lt;xsl:sort select="name()"/&gt;<br>&nbsp; &nbsp; &nbsp; &lt;xsl:sort select="@NAME"/&gt;<br>&nbsp; &nbsp; &lt;/xsl:apply-templates&gt;<br> <br>&nbsp; &lt;/xsl:copy&gt;<br>&lt;/xsl:template&gt;<br> <br>&lt;xsl:template match="@*|node()"&gt;<br>&nbsp; &lt;xsl:copy&gt;<br>&nbsp; &nbsp; &lt;xsl:apply-templates select="@*|node()"/&gt;<br>&nbsp; &lt;/xsl:copy&gt;<br>&lt;/xsl:template&gt;<br> <br>&lt;/xsl:stylesheet&gt;</tt></p></div> </blockquote><p>Which sorts "D" elements by the FOO attribute, and everything else by tag name then NAME attribute. The difference between this and my previous method is that now "D" tags will come before "A" tags (and any others), whereas before they were still sorted by tag name. I think I can get the former two-pass approach behavior in one XSLT document, but for now, it's more trouble than it's worth. It would be easy if you could define a sort callback function....<nobr> <wbr></nobr>:-)</p> runrig 2008-01-19T00:15:23+00:00 journal Burnin' Vinyl http://use.perl.org/~runrig/journal/35247?from=rss <p>Today is the day I'm glad I never got rid of all my vinyl. Though I haven't heard any of it for about 12 years, I've managed to to hang on to most of it...and the irony is that although my wife is the one who has encouraged jettisoning the records, she's the one who gave me the turntable w/the USB connection (big thank you to you dear).</p><p>So, what to record first? A while back, I did sell my copy of <a href="http://www.amazon.com/Generic-Flipper/dp/B000002LTK/">Generic Flipper</a>, and I'm still kicking myself for that, though I do still have <a href="http://www.geocities.com/flipper_still_rule/flipperltd.html">Public Flipper Limited</a>, but that's not exactly a family friendly album (I'll record that one some late night or when no one's home). I've also got some 78's of <a href="http://www.amazon.com/Violin-Sonata-Kreutzer-Digital-Remaster/dp/B0011XHENG">Yehudi and Hephzibah Menuhin playing Beethoven's Sonata No. 9 in A (Op. 47 "Kreutzer Sonata")</a>, but I don't yet have a 78 needle, so I'll leave that one for now. And besides, Amazon seems to have it, though I'm not sure if their 6:48 version is what I have (what is the play time of 4 78 disks anyway?).</p><p>So first up on the platter is <a href="http://www.rockabillyeurope.com/artists/jon.htm">Jon and the Nightriders</a>, which seems to have been never released to CD, though it's the greatest surf album ever recorded...IMHO<nobr> <wbr></nobr>:-) Hmmm, if it says on the album "Unauthorized copying, hiring, lending, public performance, and broadcasting of this record would be appreciated", I wonder if that includes permission to post one or two tunes on YouTube? Well, until I figure that out, this disk join my other two new disks/presents in heavy rotation on my car stereo...<a href="http://www.google.com/search?q=moby+grape">Moby Grape</a>(Listen My Friends) and <a href="http://www.myspace.com/cowboynationfans">Cowboy Nation</a>(Journey Out of Time).</p> runrig 2007-12-30T23:45:18+00:00 journal Free (as in beer) Music Scoring http://use.perl.org/~runrig/journal/34877?from=rss <p>My daughter is in the school jazz band. She plays french horn. As you might imagine, there isn't much jazz band music written for french horn. The instructor has some trombone music in the same range, but trombone is written in concert pitch with a bass clef, horn is an F instrument written with a treble clef.</p><p>I did not want to manually write the notes with pencil and paper, I wanted some sort of "music scoring language" for the computer. At first, I thought of XML (why?), searched for Music and XML, and found a ".org" whose website looked like an advertisement for the company who had come up with this flavor of XML. And the XML was verbose, and I was not looking forward to entering all that cruft.</p><p>Then I think I searched for "music scoring opensource", and came up with <a href="http://lilypond.org/">LilyPond</a>. And I looked at the language, and it was (sometimes) as dense as a perl regular expression. To enter a run of quarter notes, you just enter them "c d e f g". To make them eighth notes, just add the duration to the first one: "c8 d e f g". It gets somewhat ugly when you mark up a note...to make the c staccato and mark it as (dynamic) forte it would be "c8-.\f" (the "f" appears below the note, the "." appears above or below the note depending on stem direction). Dynamics like "f" (in the previous example) and "sfz" are built in, but for "sffz" you have to create a "custom dynamic."</p><p>Text markup is ugly too...I wanted to add a "D.S. (w/symbol) al Coda (w/symbol)" above the staff with "(No repeat)" underneath it, and this is what I came up with (it's attached to a rest note):</p><blockquote><div><p> <tt>&nbsp; r1^\markup { \hspace #3.0 \tiny \center-align {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ \line { "D.S. " \musicglyph #"scripts.segno" " al Coda&nbsp; " \musicglyph #"scripts.coda" } }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ "(No Repeat)" }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} }</tt></p></div> </blockquote><p>You can create macros, and that's what I think I would do next time for the musicglyphs above. Also, glissandos (rising or falling pitch to or from a note) must have starting and ending notes, but sometimes the start or end pitches are indeterminate, so you have to create an "invisible note" and modify the duration of the notes (here the starting note is 9/10 the normal value, so the invisible end note is 1/10 the same value, and the style is a "zigzag" line instead of a straight line):</p><blockquote><div><p> <tt>\once \override Glissando #'style = #'zigzag<br>&nbsp; c4*9/10-&gt;\glissando<br>&nbsp; &nbsp; \hideNotes g4*1/10 \unHideNotes</tt></p></div> </blockquote><p>I had two pieces (each two pages) to transcribe, the first one took me 10 hours or so (big learning curve), the next took less than an hour (it had less text markup). When I was done, I compared the trombone music against the original, corrected my typos(**), then I wrapped the whole thing in a "\transpose f c' {<nobr> <wbr></nobr>... }", changed the bass clef to treble, and I had some nice new jazz for horn<nobr> <wbr></nobr>:-) </p><p>Oh yeah, and it has a Scheme based scripting language (which I have not begun to look at), and outputs pdf, postscript (w/direct links to modify the postscript output), and other formats.</p><p>(**) Along with the usual typos, before I learned about the hideNotes thing, I had a glissando between a note and a rest, which worked fine for trombone in that instance, but when transposed to horn, it was a glissando up instead of down, so I had to learn all about the hiding notes thing to fix it<nobr> <wbr></nobr>:-)</p> runrig 2007-11-11T17:10:11+00:00 journal Map first post http://use.perl.org/~runrig/journal/34524?from=rss <p>While clicking on some YAPC photos on <a href="http://www.flickr.com/">Flickr</a>, I noticed the "(map)" link (I may have been vaguely aware of it in the past, but I actually noticed it this time), and then I was clicking around various photos of Paris (at first YAPC photos, then anything in the neighborhood...BTW I may be visiting next year), then I thought "Hey, why don't I map some of my crappy photos". <a href="http://www.flickr.com/photos/55335872@N00/345964330/map/?view=everyones">So</a> <a href="http://www.flickr.com/photos/55335872@N00/345965606/map/?view=everyones">I</a> <a href="http://www.flickr.com/photos/55335872@N00/346827953/map/?view=everyones">did</a>. I even got first post in a very low density area<nobr> <wbr></nobr>:-)</p><p>I recently tried to make it to the top of the "hill" <a href="http://use.perl.org/~runrig/journal/32085">again</a> (no camera this time though), but it was 90-100 degrees (32-38C), I ran out of water (down to my last pint), and "only" made it to the main divide again. On the map, there are quite a few photos at the peak, but I'd bet that that person drove up...</p> runrig 2007-09-23T07:55:03+00:00 journal Cwd::chdir not useless after all http://use.perl.org/~runrig/journal/34498?from=rss Prior to today, I always considered Cwd::chdir() rather pointless. It keeps $ENV{PWD} up to date. But if you wanted $ENV{PWD}, why not just call Cwd::cwd() (unless maybe you wanted PWD when the program started, but then you wouldn't need Cwd at all)? Well, we had this awful code:<blockquote><div><p> <tt>open( FH, "pwd|" ) or die "....: $!";<br>my $dir = &lt;FH&gt;;<br>chomp $dir;</tt></p></div> </blockquote><p>It was awful, but it worked, at least until we migrated this code to a system where '/foo/bar' was a symbolic link to '/foo/blah/bar' (and there was logic that depended on stuff being in '/foo/bar'). pwd in<nobr> <wbr></nobr>/foo/bar from the command line returned<nobr> <wbr></nobr>/foo/bar. But pwd from within perl returned<nobr> <wbr></nobr>/foo/blah/bar. Cwd::cwd() also returned<nobr> <wbr></nobr>/foo/blah/bar. But $ENV{PWD} returned<nobr> <wbr></nobr>/foo/bar. And we chdir'd a lot. So Cwd::chdir() saved us from changing some hardcoded<nobr> <wbr></nobr>/foo/bar's, and gave me an excuse to replace the awful code above with:</p><blockquote><div><p> <tt>my $dir = $ENV{PWD};</tt></p></div> </blockquote><p>And actually, the code is really just trying to recursively search directories, so I really ought to use File::Find...but that's more refactoring than I'm willing to do at this point<nobr> <wbr></nobr>:-)</p> runrig 2007-09-20T22:28:34+00:00 journal WE OWN UR HOMEPAGE http://use.perl.org/~runrig/journal/34374?from=rss I understand it's their (work's) computer and they can do anything they want to it, but I was using <a href="http://use.perl.org/~TorgoX/journal/29369">TorgoX's homepage</a> on Firefox (I also copied his Unicode Sliderule locally, and use that in the homepage link), when an update was pushed to my computer from the company servers. After which I noticed that the homepage had changed to the company's intranet main page (which I have as a bookmark, but which I rarely want to see at all, let alone when I start up Firefox). Also, when I reset the home page through the normal Tools-&gt;Options, it didn't stick, and would revert when I restarted. I saw a suspicious entry in user.js, changed that, and now all is well. For now. runrig 2007-09-07T18:48:26+00:00 journal I give up -- it's a SCSL http://use.perl.org/~runrig/journal/34289?from=rss <p>Tired of trying to educate the masses on what kind of language Perl is? I hereby dub Perl and any other language that wants to join the party as a SCSL, which stands for So-Called Scripting Language. If you want to wordify the acronym, I tentatively suggest "scuzzle".</p><p>Whenever the word "script" is used in reference to one of these languages, it is implied that what is really meant is "so-called script". It'll even be ok to say "I'm writing a scuzzle" (you don't have to say "I'm writing a scuzz", cuz that just doesn't sound right...though maybe "I'm writing some scuzz"...that sounds better).</p><p>You just wait, within 5 years, it'll be common usage. We'll just have to avoid association with the current (informal) definition of scuzzle...or maybe not...<nobr> <wbr></nobr>.oO( That's one hairy-ass language )...I'm liking this idea more and more<nobr> <wbr></nobr>:-)</p> runrig 2007-08-30T19:43:28+00:00 journal XML parser errors http://use.perl.org/~runrig/journal/34181?from=rss A colleague was developing a PowerCenter transfer with an XML file as the source. She kept getting an error, with a reference to a line number in the file. But there didn't appear to be anything wrong with the indicated line. I ran the file through libxml (via perl), and it gave me a different line number as the error. Then the error was obvious...the encoding claimed to be UTF-8, but there were characters such as &#235; and &#196; in the file. Changing the encoding to ISO-8859-1 seemed to fix it, I'm not sure yet if the supplier of the file will fix it, or if we'll have to fix their tag-soup gunk (there is as yet no perl involved in the process, so I'm not sure if <a href="http://use.perl.org/~grantm/journal/33887">Grant's Rule</a> applies). I went to google to see about any other info with regard to PowerCenter, XML, and line numbers, and not far from the top of the list was my own posts here on use.perl. Now with this post, I may show up even higher<nobr> <wbr></nobr>:-) runrig 2007-08-22T21:27:30+00:00 journal More XML Sorting http://use.perl.org/~runrig/journal/33883?from=rss <a href="http://use.perl.org/~runrig/journal/33854">A few days ago</a> I thought I had it all nailed, sorting the elements, but then I noticed this pattern in the XML (seems like a badly designed schema, oh well):<blockquote><div><p> <tt>&lt;a NAME="A"&gt;<br> &lt;b NAME="B"&gt;<br>&nbsp; &nbsp;&lt;c NAME="FOO"/&gt;<br>&nbsp; &nbsp;&lt;d NAME="FOO"/&gt;<br>&nbsp; &nbsp;&lt;c NAME="BAR"/&gt;<br>&nbsp; &nbsp;&lt;d NAME="BAR"/&gt;<br> &lt;/b&gt;<br>&lt;/a&gt;</tt></p></div> </blockquote><p>In one doc, the FOO's came first, and in the other, the BAR's came first. <a href="http://search.cpan.org/dist/XML-Filter-Sort">XML::Filter::Sort</a> didn't handle sorting non-contiguous elements, nor sorting by element name. I briefly looked into patching it to handle that case, but decided against bloating a nice, simple, module API.</p><p>I remembered that XSLT could sort, so I started looking into that, and tried the first thing that came up when you search CPAN for XSLT, <a href="http://search.cpan.org/dist/XML-XSLT">XML::XSLT</a>. No matter what I tried, though, nothing worked. Then as a last resort I read the fine docs and saw that "sort" was not yet implemented (update: also, it seemed to be applying templates from the bottom up -- see xslt below)</p><p>Then I tried <a href="http://search.cpan.org/dist/XML-Filter-XSLT">XML::Filter::XSLT</a> which was based on <a href="http://search.cpan.org/XML-LibXSLT">XML::LibXSLT</a> (and libxslt), which I had much higher hopes for. I had trouble at first getting it to sort by element name while preserving the attributes (which I could never quite find a full example of), but finally came up with this:</p><blockquote><div><p> <tt>my $sorter = XML::Filter::XSLT-&gt;new(Source =&gt; {String =&gt; &lt;&lt;'EOT'});<br>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br>&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"<br>&nbsp; &nbsp; &nbsp;version="1.0"&gt;<br> <br>&lt;xsl:output method="xml" version="1.0"<br>encoding="iso-8859-1" indent="yes" omit-xml-declaration="no"/&gt;<br> <br>&lt;xsl:template match="/"&gt;<br>&nbsp; &lt;xsl:apply-templates select="@*|node()"/&gt;<br>&lt;/xsl:template&gt;<br> <br>&lt;xsl:template match="/a/b"&gt;<br>&nbsp; &lt;xsl:copy&gt;<br>&nbsp; &nbsp; &lt;xsl:apply-templates select="@*"/&gt;<br>&nbsp; &nbsp; &lt;xsl:apply-templates&gt;<br>&nbsp; &nbsp; &nbsp; &lt;xsl:sort select="name()"/&gt;<br>&nbsp; &nbsp; &nbsp; &lt;xsl:sort select="@NAME"/&gt;<br>&nbsp; &nbsp; &lt;/xsl:apply-templates&gt;<br>&nbsp; &lt;/xsl:copy&gt;<br>&lt;/xsl:template&gt;<br> <br>&lt;xsl:template match="@*|node()"&gt;<br>&nbsp; &lt;xsl:copy&gt;<br>&nbsp; &nbsp; &lt;xsl:apply-templates select="@*|node()"/&gt;<br>&nbsp; &lt;/xsl:copy&gt;<br>&lt;/xsl:template&gt;<br> <br>&lt;/xsl:stylesheet&gt;<br>EOT</tt></p></div> </blockquote><p>One interesting effect was that the encoded characters in the attributes (</p><blockquote><div><p> <tt>&amp;#xA;, &amp;#xD;, and &amp;#x9;</tt></p></div> </blockquote><p>), were now coming out as unencoded characters, where previously they were just coming out as spaces. I'm still not sure what the best way would be to preserve the encoding, if I happened to care about preserving them...</p> runrig 2007-07-25T16:53:46+00:00 journal Comparing XML docs http://use.perl.org/~runrig/journal/33854?from=rss <p>I've found a workaround for one of <a href="http://use.perl.org/~runrig/journal/33842">yesterday's annoyances</a>, at least the one where a "folder compare" function (not really a file directory) in Informatica PowerCenter doesn't really compare everything in the folders. You can export folders as XML documents, so that's what I did, and then used <a href="http://search.cpan.org/dist/XML-Diff/">XML::Diff</a> to compare the documents.</p><p>Except that some of the elements in one document are not in the same order as the other document, and although I don't care, XML::Diff does. There are some commercial tools that will compare unordered XML elements, and I ran across one that I guess was free <a href="http://pages.cs.wisc.edu/~yuanwang/xdiff.html">but is no longer.</a> </p><p>So it was <a href="http://search.cpan.org/dist/XML-Filter-Sort/">XML::Filter::Sort</a> to the rescue (thank you <a href="http://use.perl.org/~grantm/">grantm</a> - and all the other XML folks), and I just sorted all the elements where I didn't care about the order, and then diffed the results. Several of the elements where just sorted by the name attribute, so I made a bunch of sorters in one go:(Updated code: Needed "./" prefix on NAME)</p><blockquote><div><p> <tt>my @sorters = (<br>&nbsp; map {<br>&nbsp; &nbsp; XML::Filter::Sort-&gt;new(<br>&nbsp; &nbsp; &nbsp; Record =&gt; $_,<br>&nbsp; &nbsp; &nbsp; Keys =&gt; [ ['./@NAME'] ],<br>&nbsp; &nbsp; )<br>&nbsp; )&nbsp; @list_of_elements<br>);</tt></p></div> </blockquote><p>I also wrote my first actual XML::SAX parser for the task of deleting some attributes where I didn't care about differences in values.</p><p>And some of the attributes had encoded control characters in them e.g. <code>&#10;&#13;</code>, and those just came out as spaces, and for the purposes of this, I didn't care, but in other situations, I might care, so I'm wondering if there's a way to preserve those. Though I hear from a reliable secondhand source that there is no reliable way to preserve them<nobr> <wbr></nobr>:-(</p> runrig 2007-07-21T01:48:33+00:00 journal PowerCenter annoyances (part 1) http://use.perl.org/~runrig/journal/33842?from=rss <p>Who designs these UI's anyway? I want to edit 8 fields to be all the same. Can I edit one and then cut and paste? Noooo....I have to click on a button, select something from a drop down list (that has hundreds of items in it), and then click "Ok".</p><p>I'm starting to think it might be easier to "Export Objects" as XML, edit the file, and then "Import Objects".</p><p>And then, after editing and saving, I do a "Folder Compare" against a previously identical folder, and they don't show any differences. What are we supposed to be comparing? If it can't find differences, how can I rely on it? (I know, export both folders as XML and then do a diff...I'm sure everyone will love that<nobr> <wbr></nobr>:-)(Update: I do now see in the docs that a Folder Compare doesn't compare objects that deeply...hmmm, should I point this out to everyone who's relying on some things to be identical, or allow them to live in blissful ignorance?)</p><p>(update: and I won't even go into the utter pointlessness and uselessness of the whole tool...other than having a pretty GUI to make the PHB's go ooh and ahhh)</p> runrig 2007-07-18T18:53:10+00:00 journal Adventures in functional idiocy http://use.perl.org/~runrig/journal/33835?from=rss <p>I'm no functional guru (but that doesn't stop me from trying), and I was curious about the hamming numbers (numbers with only 2, 3, and/or 5 as prime factors) and the code from MJD's book, and after a brief digression into <a href="http://en.wikipedia.org/wiki/Regular_number"> Wikipedia</a> (mental note to self...must work <a href="http://en.wikipedia.org/wiki/Syntonic_comma">syntonic comma</a> into casual conversation), I started thinking about MJD's code ( Fair use license verbage: from Higher-Order Perl by Mark Dominus, published by Morgan Kaufmann Publishers, Copyright 2005 by Elsevier Inc):</p><blockquote><div><p> <tt>sub scale {<br>&nbsp; my ($s, $c) = @_;<br>&nbsp; transform { $_[0]*$c } $s;<br>}<br>my $hamming;<br>$hamming = node(1,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; promise {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; merge(scale($hamming, 2),<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; merge(scale($hamming, 3),<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scale($hamming, 5),<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;))<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;);</tt></p></div> </blockquote><p>I thought hmmm, I wonder (just for fun) if I can get rid of that cyclical reference. So I pull everyone's favorite combinator out of <a href="http://search.cpan.org/dist/Moose-Autobox/">Moose::Autobox::Code</a> (and modify it to make it non-OO) and try this:</p><blockquote><div><p> <tt>sub u {<br>&nbsp; &nbsp; my $f = shift;<br>&nbsp; &nbsp; sub { $f-&gt;($f, @_) };<br>}<br> <br>sub Y {<br>&nbsp; &nbsp; my $f = shift;<br>&nbsp; &nbsp; u(sub { my $h = shift; sub { $f-&gt;(u($h)-&gt;())-&gt;(@_) } })-&gt;();<br>}<br> <br>my $hamming = Y( sub {<br>&nbsp; my $h = shift;<br>&nbsp; sub {<br>&nbsp; &nbsp; node(1,<br>&nbsp; &nbsp; &nbsp; promise {<br>&nbsp; &nbsp; &nbsp; merge(scale($h, 2),<br>&nbsp; &nbsp; &nbsp; merge(scale($h, 3),<br>&nbsp; &nbsp; &nbsp; scale($h, 5),<br>&nbsp; &nbsp; ))})<br>&nbsp; }<br>});</tt></p></div> </blockquote><p>And get:</p><blockquote><div><p> <tt>Not an ARRAY reference at C:/Perl/site/lib/HOP/Stream.pm line 127.</tt></p></div> </blockquote><p>Oh crap, I forgot, a HOP::Stream isn't a function, stupid, it's an array reference (C'mon, can't I just make shit up and expect the computer to know what I mean?). Let's try something else:</p><blockquote><div><p> <tt>my $mk_hamm = Y( sub {<br>&nbsp; my $h = shift;<br>&nbsp; sub {<br>&nbsp; &nbsp; my $s = node(1, $h);<br>&nbsp; &nbsp; node(1,<br>&nbsp; &nbsp; &nbsp; promise {<br>&nbsp; &nbsp; &nbsp; merge(scale($s, 2),<br>&nbsp; &nbsp; &nbsp; merge(scale($s, 3),<br>&nbsp; &nbsp; &nbsp; scale($s, 5),<br>&nbsp; &nbsp; ))})<br>&nbsp; }<br>});<br>my $hamming = $mk_hamm-&gt;();</tt></p></div> </blockquote><p>And get this:</p><blockquote><div><p> <tt>1<br>2<br>2<br>3<br>3<br>4<br>4<br>5<br>5<br>6<br>6<br>8<br>8<br>9<br>9<br>10<br>10<br>12<br>12</tt></p></div> </blockquote><p>Hey, that's close! Hmm, what happens if I try this (let's just make more shit up):</p><blockquote><div><p> <tt>my $mk_hamm = Y( sub {<br>&nbsp; my $h = shift;<br>&nbsp; sub {<br>&nbsp; &nbsp; my $s = node(0, $h);<br>&nbsp; &nbsp; node(1,<br>&nbsp; &nbsp; &nbsp; promise {<br>&nbsp; &nbsp; &nbsp; merge(scale($s, 2),<br>&nbsp; &nbsp; &nbsp; merge(scale($s, 3),<br>&nbsp; &nbsp; &nbsp; scale($s, 5),<br>&nbsp; &nbsp; ))})<br>&nbsp; }<br>});</tt></p></div> </blockquote><p>And we get:</p><blockquote><div><p> <tt>1<br>0<br>2<br>0<br>3<br>0<br>4<br>0<br>5<br>0<br>6<br>0<br>8<br>0<br>9<br>0<br>10<br>0<br>12<br>0<br>15</tt></p></div> </blockquote><p>Hey, now all I have to do is change this line:</p><blockquote><div><p> <tt>#my $hamming = $mk_hamm-&gt;();<br>my $hamming = filter { $_[0] &gt; 0 } $mk_hamm-&gt;();</tt></p></div> </blockquote><p>And we get the right output. But that's still not quite satisfying, due to the extra cruft that we have to filter out. The "node" being assigned in the original is the same reference as in all of the merge clauses, so let's try just skipping the original node and just merge all the other streams that do have the same node as a basis:</p><blockquote><div><p> <tt>my $mk_hamm = Y( sub {<br>&nbsp; my $h = shift;<br>&nbsp; sub {<br>&nbsp; &nbsp; my $s = node(1, $h);<br>&nbsp; &nbsp; merge(scale($s, 2),<br>&nbsp; &nbsp; merge(scale($s, 3),<br>&nbsp; &nbsp; scale($s, 5),<br>&nbsp; &nbsp; ))<br>&nbsp; }<br>});<br>my $hamming = $mk_hamm-&gt;();</tt></p></div> </blockquote><p>And all we're missing is the initial "1" in the stream:</p><blockquote><div><p> <tt>2<br>3<br>4<br>5<br>6<br>8<br>9<br>10<br>12</tt></p></div> </blockquote><p>So, let's just "unshift" the "1" back on after the fact by changing this line:</p><blockquote><div><p> <tt>#my $hamming = $mk_hamm-&gt;();<br>my $hamming = node(1, $mk_hamm-&gt;());</tt></p></div> </blockquote><p>And it works! I'm still not altogether sure exactly what was going on with the previous versions, but I'm too tired now to figure it out. G'nite.</p> runrig 2007-07-18T06:20:21+00:00 journal