educated_foo's Journal http://use.perl.org/~educated_foo/journal/ educated_foo'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:32:28+00:00 pudge pudge@perl.org Technology hourly 1 1970-01-01T00:00+00:00 educated_foo's Journal http://use.perl.org/images/topics/useperl.gif http://use.perl.org/~educated_foo/journal/ Correction on platypi (?) http://use.perl.org/~educated_foo/journal/38947?from=rss I can't be bothered to create yet another login on chromatic's site, but want to offer a correction<blockquote><div><p>As the difficulty for creating sane biological taxonomies indicates, the real world does not lend itself to such artificial simplicity. (Extinction of the duck-billed platypus might help, but I'd miss the little guys -- and besides that, I can't give birth to live young myself, so I'm obviously not a mammal.)</p></div></blockquote><p> The duck-billed platypus is a monotreme, an ancient relative of mammals. Before we knew about genes, one might think that it was part duck and part beaver, but we know about genes now, and therefore better understand evolution. It's pretty straightforward to fit it into a phylogeny, and horizontal gene transfer has nothing to do with it. I agree that single inheritance is a crappy way to design software, but this is a bad example.</p> educated_foo 2009-05-10T02:59:57+00:00 journal Test http://use.perl.org/~educated_foo/journal/38907?from=rss <p>Was that a network error, a user error, or did something I posted just get disappeared?</p> educated_foo 2009-05-01T17:17:09+00:00 journal There's a reason... http://use.perl.org/~educated_foo/journal/38525?from=rss <p>In response to chromatic's latest maunderings, there's a reason that the Perl core heeds "the DarkPAN" -- it's the same reason that "the DarkPAN" is still written in Perl. Language implementors have no obligation to maintain backward compatibility, just like language users have no obligation to keep using a language. It's "insane" to think that a script written for Perl 5.6 will work with Perl 5.10, just like it was "insane" to think that a script written to run on HPUX would run on AIX, Solaris, BSD, etc. Perl is great because of its stability, and breaking that because... whatever it is you want... is insane.</p> educated_foo 2009-02-22T03:43:36+00:00 journal TIMTOWTDI in Emacs, too. http://use.perl.org/~educated_foo/journal/35115?from=rss Devel::PerlySense has been getting quite a bit of (apparently well-deserved) attention lately. As the author of <a href="http://search.cpan.org/src/SEANO/Sepia-0.95_03/Sepia.html">Sepia</a>, a long-existing but apparently little-used Emacs Perl development module, I thought now would be a good time to post a diary here. For those of you who tried an earlier version, Sepia is considerably more stable and better-documented in versions 0.9x, but needs more users to acquire polish. <p>Sepia aims to make Emacs the kind of interactive development environment for Perl that it already is for Emacs Lisp. This involves a number of components: </p><ul> <li>Interactive evaluation: Supports both a REPL and a scratch buffer. The REPL uses the Perl debugger hooks to allow breakpoints and recovery from <code>die</code>, and Devel::LexAlias to inspect and change lexicals.</li> <li>Source navigation: Finds definitions, callers, and callees. This is supported by querying the running Perl process rather than through PPI.</li> <li>Documentation: Displays minibuffer documentation (eldoc) for builtins and some user functions, and supports POD browsing.</li> <li>Completion: Completes variable, function, and module names based on the running Perl process.</li> </ul><p> Not having used Devel::PerlySense, I won't try to make a detailed comparison, but my impression is that Devel::PerlySense is geared toward off-line development (uses PPI, has a class browser, etc.), while Sepia is geared toward on-line development (supports interaction, value inspection, debugging). So give both a try, and see which style suits you best.</p> educated_foo 2007-12-16T20:29:11+00:00 journal Defining "DSL", or eternal recurrence in software http://use.perl.org/~educated_foo/journal/33322?from=rss (Inspired by chromatic's recent musings...)<p> I want a function to take the mean of some data:</p><p><div class="quote"><p> <code>$x = mean \@data;</code></p> </div><p>Hm.... I want to ignore NaN and Inf sometimes; I'll add a flag for it:</p><p><div class="quote"><p> <code>$x = mean \@data, 1;</code></p> </div><p>But I may also want to trim outliers; I'll use keyword arguments:</p><p><div class="quote"><p> <code>$x = mean \@data, skipinf =&gt; 1, trim =&gt; 0.1;</code></p> </div><p>Whoa, this is getting complicated; I'll make it an Object:</p><p><div class="quote"><p> <code> $x = new Mean(@data);<br> $x-&gt;{skipinf}=1;<br> $x-&gt;{trim}=0.1;<br> $y = $x-&gt;value</code></p> </div><p>OMG, no encapsulation, I'll make accessors:</p><p><div class="quote"><p> <code>$x = new Mean;<br> $x-&gt;setData(\@data);<br> $x-&gt;setSkipInf(1);<br> $x-&gt;setTrim(0.1);<br> $y = $x-&gt;value</code></p> </div><p>But now I have to do this just to do a simple mean:</p><p><div class="quote"><p> <code>$x = new Mean;<br> $x-&gt;setData(\@data);<br> $y = $x-&gt;value</code></p> </div><p>I know, I'll create a little language for means:</p><p><div class="quote"><p> <code>$x = mean \@data, trim =&gt; 0.1, skipinf =&gt; 1;</code></p> </div><p>Then I can write in the domain terminology, and taking the mean is easy:</p><p><div class="quote"><p> <code>$x = mean \@data;</code></p> </div><p>...and thus we see how "writing interfaces that don't suck" became "creating little languages."</p> educated_foo 2007-05-21T17:54:43+00:00 journal script vs. applescript http://use.perl.org/~educated_foo/journal/21130?from=rss <p>So I need something to kill time during the debates and further<br>increase my level of frustration. Safari doesn't have a saved<br>sessions. Let's try a bit of applescript...<br><code><br>tell application "Safari"<br> &nbsp; &nbsp; &nbsp; &nbsp; set urls to URL of every document<br> &nbsp; &nbsp; &nbsp; &nbsp; -- tbd: how do I write a file in AS?<br>end tell<br></code></p><p>No love -- this only saves the first tab of each window. Curse.<br>Google around a bit. Curse a bit more when I find out what's<br>involved, and when I can't make the cut-and-paste code to write a file<br>work...<br><code><br>#!/usr/bin/env perl</code></p><p><code>sub osascript($)<br>{<br> &nbsp; &nbsp; &nbsp; &nbsp; my $cmd = shift;<br> &nbsp; &nbsp; &nbsp; &nbsp; local *O;<br> &nbsp; &nbsp; &nbsp; &nbsp; open O, "|osascript &gt;<nobr> <wbr></nobr>/tmp/osa.$$";<br> &nbsp; &nbsp; &nbsp; &nbsp; $cmd =~ s/\n/\r/g;<br> &nbsp; &nbsp; &nbsp; &nbsp; print O $cmd;<br> &nbsp; &nbsp; &nbsp; &nbsp; close O;<br> &nbsp; &nbsp; &nbsp; &nbsp; open IN, "/tmp/osa.$$" or die $!;<br> &nbsp; &nbsp; &nbsp; &nbsp; unlink "/tmp/osa.$$";<br> &nbsp; &nbsp; &nbsp; &nbsp; return split<nobr> <wbr></nobr>/\r/, join '', &lt;IN&gt;;<br>}</code></p><p><code>sub get_docs<br>{<br> &nbsp; &nbsp; &nbsp; &nbsp; osascript &lt;&lt;'END';<br>tell application "System Events"<br> &nbsp; &nbsp; &nbsp; &nbsp; set urls to {}<br> &nbsp; &nbsp; &nbsp; &nbsp; tell process "Safari"<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; repeat with w in every window<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tell w<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; repeat with b in every radio button<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; click b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tell application "Safari"<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set urls to urls &amp; (URL of first document)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end tell<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end repeat<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end tell<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end repeat<br> &nbsp; &nbsp; &nbsp; &nbsp; end tell<br> &nbsp; &nbsp; &nbsp; &nbsp; set old_delim to AppleScript's text item delimiters<br> &nbsp; &nbsp; &nbsp; &nbsp; set AppleScript's text item delimiters to return<br> &nbsp; &nbsp; &nbsp; &nbsp; set urls to urls as text<br> &nbsp; &nbsp; &nbsp; &nbsp; set AppleScript's text item delimiters to old_delim<br> &nbsp; &nbsp; &nbsp; &nbsp; urls<br>end tell<br>END<br>}</code></p><p><code>sub restore_docs<br>{<br> &nbsp; &nbsp; &nbsp; &nbsp; my $docthing = '{'.(join ',', map { qq{"$_"} } grep $_, @_).'}';<br> &nbsp; &nbsp; &nbsp; &nbsp; osascript &lt;&lt;END;<br>tell application "System Events"<br> &nbsp; &nbsp; &nbsp; &nbsp; set urls to $docthing<br> &nbsp; &nbsp; &nbsp; &nbsp; tell application "Safari"<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; repeat with u in urls<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; open location u<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end repeat<br> &nbsp; &nbsp; &nbsp; &nbsp; end tell<br>end tell<br>END<br>}</code></p><p><code>@ARGV = grep $_,@ARGV; # wtf: quicksilver passes us an empty arg.<br>if (@ARGV) {<br> &nbsp; &nbsp; &nbsp; &nbsp; $op = shift;<br>} else {<br> &nbsp; &nbsp; &nbsp; &nbsp; $pf = "$ENV{HOME}/.safari-state";<br> &nbsp; &nbsp; &nbsp; &nbsp; if ($0 =~<nobr> <wbr></nobr>/safari-save(?:\.pl)?$/) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $op = 'save';<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; open STDOUT, "&gt;$pf" or die "$0: $pf: $!";<br> &nbsp; &nbsp; &nbsp; &nbsp; } elsif ($0 =~<nobr> <wbr></nobr>/safari-load(?:\.pl)?$/) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $op = 'load';<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; open STDIN, $pf or die $!;<br> &nbsp; &nbsp; &nbsp; &nbsp; } else {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; die;<br> &nbsp; &nbsp; &nbsp; &nbsp; }<br>}</code></p><p><code>if ($op =~<nobr> <wbr></nobr>/^s/) {<br> &nbsp; &nbsp; &nbsp; &nbsp; print STDOUT "$_\n" for get_docs;<br>} elsif ($op =~<nobr> <wbr></nobr>/^l/) {<br> &nbsp; &nbsp; &nbsp; &nbsp; my @docs = map {chomp;$_} &lt;STDIN&gt;;<br> &nbsp; &nbsp; &nbsp; &nbsp; restore_docs(@docs);<br>}<br></code><nobr> <wbr></nobr>...add it to my Quicksilver path. Hack-tastic.</p> educated_foo 2004-10-01T04:27:43+00:00 journal