Stilistik komparé de Javascript et de Perl

TorgoX on 2005-05-23T10:44:22

Dear Log,

Today was given over to JavaScript and vacuuming. When I wasn't vacuuming, I was leisurely reading Higher-Order Perl and writing some more notes on translating it all to JavaScript.

Today's interesting stuff was mainly yet more cases where the Perl code has push @foo, bar(...) where bar might (directly or indirectly) return an empty list, or one item, or several; and, to make things even more interesting, some of the values returned were arrayrefs, so that I couldn't just say that I'll array-deref whatever values come back. It's not a case of the Perl being bad, or the JavaScript being bad; instead, the trouble is the subtleness of the problems that arise from the apparently safe translation of push @foo, bar(), as foo.push(bar()). In a day or two, I'll put it all up at the usual place.

Then, as I was poking at My RSSs Of Interest, it occurred to me that my XSL tricks do improve things by expressing <lastBuildDate>Mon, 23 May 2005 08:57:22 GMT</lastBuildDate> as "Last feed update: Mon, 23 May 2005 08:57:22 GMT". But, it occurred to me that it's not exactly effortless for people to look at that and say "oh, that just updated", or "that was like ten hours ago"

So I thought how I've already used a bit of JavaScript to moregoodify the data in an RSS feed, and a bit of date-wrangling in JavaScript; so I might as well combine the two past approaches and write some JavaScript to convert "Mon, 23 May 2005 08:57:22 GMT" to a Date object and then to figure out how long ago it was, and then to express that as an approximate time-interval, like "Last feed update: about 9 hours ago".

Then I just got crazy and put some other data off into the title="..." attribute of the wrapper-element around the "ago" phrase, so that mousing over "9 hours ago" shows something like "Sun 22 May 2005 04:58:32 PM ADT (Mon, 23 May 2005 08:58:32 GMT)" (modulo your locale and timezone, etc).

(An example RSS with the feature)


Time zone problem?

vsergu on 2005-05-23T18:26:37

The title I'm getting is "Sun 22 May 2005 08:57:22 PM EDT (Mon, 23 May 2005 08:57:22 GMT)". The difference between EDT and GMT is 4 hours, not 12. But perhaps it's some other EDT you're referring to. (Plus it's confusing to use AM/PM for the EDT times and 24-hour time (apparently) for the GMT.)

Re:Time zone problem?

TorgoX on 2005-05-24T00:18:06

That's very strange. All the time math is done in your browser, which should ideally know its correct TZ offset. But I'll poke around a bit and see if I'm parsing the date wrong or something. What browser are you using?

Re:Time zone problem?

vsergu on 2005-05-24T01:55:03

Firefox on Linux. That was at work. I just tried it at home, also Firefox on Linux, and it's the same.

Re:Time zone problem?

vsergu on 2005-05-24T02:39:04

Argh! If the string begins with '0', parseInt() assumes it's octal, and '08' isn't a valid octal number and thus returns 0. Maybe subtracting 0 (as opposed to adding 0, which will just give string concatentaion) is better than using parseInt() when you're converting strings to numbers.

Re:Time zone problem?

TorgoX on 2005-05-24T04:40:28

D'oh, and just days after I wrote this!!!

It seems that if I pass an explicit ",10" to parseInt(), it doesn't do that crazy octalification thing. There, fixedified!

not in HOP

brev on 2005-05-24T08:24:12

I haven't even finished HOP yet, but I just digested a large Javascript tome for work reasons. JS has a few higher-ordery features that Perl doesn't.

An interesting twist on eval, Function() creates a function reference out of an array of strings.

And this JS 1.5 syntax, which gives an anonymous closure a temporary name so it can refer to itself.

var f = function fact(x) { if (x <=1) return 1; else return x*fact(x-1); }

Despite appearances, there is no fact(). That was just a name for use during the definition of f.

I have tried to do this in Perl and failed. Someone told me one could do it with a Y combinator.

Re:not in HOP

TorgoX on 2005-05-25T02:21:13

One is tempted to do this:
my $f = sub { ($_[0] <=1) ? 1 : ( $_[0] * $f->($_[0] - 1)) };
print $f->(4);
But that doesn't work, because sub is defined outside the scope of $f. So you've got to do this:
my $f;
$f = sub { ($_[0] <=1) ? 1 : ( $_[0] * $f->($_[0] - 1)) };
print $f->(4);
That works!

(GC note: now $f and that sub constitute a circular data structure, so you need to do $f='whatever'; (or just undef($f)) to break the circularity.)

Re:not in HOP

brev on 2005-05-25T03:06:55

Huh. Now I wonder why what I was trying didn't work. That seems relatively straightforward, with the slight inconvenience of defining the variable first.

Callee was another weirdness I noticed too. Thanks.

And with arguments.callee

TorgoX on 2005-05-25T02:29:20

Also:
var f = function (x) { if (x <=1) return 1; else return x * arguments.callee(x-1); };