Wednesday, June 8, 2011

Agreement that FB API Sucks

Here's a post with a thoughtful discussion about the badness of the FB API--the Graph API in particular.

    Facebook Developer Documentation

    I'm writing a small Facebook application.  So, of course, I'm reading their developer documentation, and I'm finding it's frequently just wrong!

    From: http://developers.facebook.com/docs/reference/fbml/iframe/

    That's a screenshot of a widget that's supposed to show you the results of loading an fb:iframe into your canvas page...  Facebook can't even figure out how to do it!!

    </rant>

    Facebook is pushing out updates to its platform at a ridiculous pace.  While this is a good thing for user applications (ie. Gmail, flickr, etc.), it is destructive for bodies of code intended to be platforms for 3rd party development.  This is especially true if the documentation can't keep pace with the change.

    I've worked with poorly documented software libraries in the past.  The key difference here is I had the code available to read.  I could always find out what I actually needed to pass into the code to make it work...  Facebook's source code is not available.  The only window into the platform is the documentation.

    This is not the first Facebook Canvas application I've done.  Given the option, I will not make Facebook applications in the future.  Dealing with the api churn and poor documentation is such a time sink that it quickly becomes a net loss.

    Monday, May 30, 2011

    And the discussion of #(%1 %2) continues!

    <tomoj> #(%1 %2) seems like it should have a name somehow
    <amalloy> &(-> inc (.invoke 1))
    <sexpbot> ⟹ 2
    <amalloy> often almost as good as giving it a name
    <tomoj> #(apply % %&) ?
    <tomoj> does that do what I think it does
    <amalloy> no
    <amalloy> &(#(apply % %&) println 1)
    <sexpbot> ⟹ 1 nil
    <amalloy> oh. huh. maybe it does?
    <amalloy> tomoj: i have a bad habit of asserting you are
    wrong. i hope you don't mind
    <tomoj> (apply #(apply % %&) f x y z) is (f x y z)
    <tomoj> if people agree with me I see no real
    need for them to say anything to me mostly
    <amalloy> tomoj: sure. it's just that usually i'm *wrong* when i
    tell you you're wrong :P
    <tomoj> er
    <tomoj> (f x y z) is (#(apply % %&) f x y z), right
    <amalloy> tomoj: i assumed %& was "all the arguments", not "all
    the args i haven't touched yet"
    <amalloy> but apparently it's not
    <amalloy> &'#(% %&)
    <sexpbot> ⟹ (fn* (p1__17398#
    rest__17399#))
    <amalloy> &'#(%2 %&)
    <sexpbot> ⟹ (fn*
    (p2__17407# rest__17408#))
    <tomoj> wacky
    <amalloy> tomoj: how so?
    <tomoj> the one disappears
    <amalloy> well, naturally
    <tomoj> that's interesting..
    <amalloy> you're not
    referring to it, and %& can't somehow include it
    <tomoj> yeah
    <clojurebot> excusez-moi
    <tomoj> so is (#(apply % %&)
    #(apply % %&) f x y z) also (f x y z)
    <amalloy> *blink*
    <tomoj> &(#(apply % %&) #(apply % %&)
    #(apply % %&) #(apply % %&) + 1 2 3)
    <sexpbot> ⟹ 6
    <amalloy> i guess it must be
    <tomoj> what is that strange thing
    <amalloy> a delegator?
    <tomoj> it's $
    <amalloy> tomoj: i guess. but $ is only useful because of its
    order of precedence
    <amalloy> in a lisp it's not much good
    <amalloy> i guess you can combine it with apply to get out
    something useful
    <tomoj> well, `($) ($) ($) ($) (+) 1 2` is 3
    <amalloy> &(apply #(apply % %&) [+ 1 2)
    <sexpbot> ⟹ 3 ; Adjusted to (apply (fn* (apply p1__17442# rest__17443#)) )
    <tomoj> huh..
    <tomoj> so.. (partial apply #(apply (resolve %) %&)) is almost like eval
    <tomoj> but no macros, no special forms
    ERC>

    UPDATE: As amalloy later said, this doesn't resolve the other arguments, so it wouldn't work as an eval.  Wow, is it close though :-p

    A neat tidbit from #clojure

    On the #clojure channel of irc.freenode.org opqdonut_ posted this fun little tidbit:

    Saturday, May 28, 2011

    Some Clojure experiments

    I was playing with the labrepl project, and doing some basic looping/recursion exercises.  In doing those exercises I wrote the following three functions to find the minimum and maximum values in a sequence:



    I then wrote this timing function:



    I ran 1000 iterations of that loop for each of the three functions. I was saddened to see how much slower the version that manipulates maps was compared to the other two. Here are the resulting average times:
    • minmax-1 => 0.3881 msecs
    • minmax-2 => 0.2400 msecs
    • minmax-3 => 1.8923 msecs
    While I was disappointed by the performance of minmax-3, it was cool to see how fast destructuring is.  Especially considering that destructuring is very idiomatic Clojure and used frequently.

    Clojure Videos

    Here's a great list of videos discussing Clojure.

    Friday, May 27, 2011

    Clojure & Google App Engine

    So, I've recently (re)discovered Clojure. Things have matured quite nicely since last I took a look at it.

    Right now I'm using it to develop a quick Facebook canvas application for a friend of mine. I'd like to upload a screencast detailing how to do this. I don't know when I'll get that done but it would be quite nice.

    Relevant Clojure libraries:


    I'm still developing this, and I'm also fairly unfamiliar with the Clojure library ecosystem.  There are sure to be more relevant libraries soon!

    It's so awesome to have a lisp that embraces the modern world!