Monday, December 29, 2008

this is going to be a problem

jes5199@electra:~/code/scala$ time scala hello.scala 
Hello, world!

real 0m24.380s
user 0m0.564s
sys 0m0.036s

Sunday, December 28, 2008

Flickr reverse lookup bookmarklet

flickr reverse lookup bookmarklet

If you're on a flickr jpg and you want to get to the photo's page, click this bookmarklet. It's that simple.

Friday, December 12, 2008

semicolon semicolon

On wednesday, Kim Wallmark, Arlo Belshee, and I entered a quick little programming competition at Cubespace's Coder Social. We were encouraged to pick a programming language that we weren't terribly familiar with -- most of the teams seemed to be Ruby programmers trying Python or Python programmers trying Ruby. That didn't seem like a challenge to us, so we went with F# -- fortunately Kim already had an F# IDE installed, but otherwise none of us had ever used it.
The problems were all from Project Euler, so they were the sorts of things that tend to have deeply recursive solutions. So, in that department, F# was an advantage.
F# has some unpleasant quirks, though:

Monomorphism by default

We had this function:
let fibStep (a,b) = (b,a+b)
By default, it only works on ints! It should be valid for any numeric type! It's just addition! But no, we had to label the parameters:
let fibStep (a : BigInt ,b : BigInt) = (b,a+b)

Crippled type inference

Maybe I've been spoiled by Haskell, but I just assume that if I've got type inference, I've got Hindley–Milner over the entire program. In F#, types are only inferred within the boundaries of a single function. That means more type annotations.

Recursion requires annotation

And for some reason I don't understand, by default recursion is forbidden in a function, unless you define it with the "let rec" keyword. I have no idea why.

Find the missing library

Since F# is on the CLR, it inherits some VM design smells. Where's the Bigint type? Microsoft.FSharp.Math . You know, I would have expected the F# language to have implicit access to the FSharp namespaces. Nope.

Unusual punctuation

We knew about the confused usage of ;; for end of line and ; for comma, and , for a different kind of comma. But we kept having to look up operators (for method names we had autocomplete in the IDE! but dingbats were Google's territory.) I know we got confused on: cons (::), append (@), exponent (**), mod (%).

Cryptic error messages

And when you get it wrong, the interpreter is worthless. It had a tendency to entirely fail to parse our functions, and give us line/column numbers at the end of the code, rather than at the problem spot. I can't remember what the messages we were getting said, but it sure seemed like they just said "This is wrong"

Hard to google

Several times we tried googling some common function names like "head" or "tail" or "append" and found that mixed with the keyword "F#" you get nothing but music results. Way to go, marketing wizards.

Wednesday, December 3, 2008

baby's first spammer

the wiki that I'm hosting ( pdxipedia ) got a nice annoying spam infection. Mediawiki may be the world class software behind Wikipedia, but out of the box it's spambait. We're lucky only one got in (Hi, ! How are things in [consults GeoIP], uh, Saudi Arabia? How's the business of ... jeeze these spams seem to be total nonsense ... search engine disruption? )
Today, I signed up for Project Honeypot, which keeps a blacklist of spammers. There's a plugin for Mediawiki that redirects known spammers away, and it's also supposed to have invisible honeypot links to ensnare unknown robots. The link generation is buggy though, so I'm not brimming with confidence about the whole thing.
So I wrote a script that runs through my Lighttpd access.log files (it probably would work for apache, too), and checks IPs of all the recent visitors against the Project Honeypot blacklist. If there's a match, I use iptables to block that IP. I've got it running once a minute -- that's still enough time for a fast bot to do some damage -- so it's not really going to be a complete solution, but it could potentially prevent denial-of-service caused by a persistent bot.