Blog Posts tagged with: functional

Jun 04 2009

Comments

Introduction to jQuery

jQuery is a powerful JavaScript library for dealing with HTML, events, animations, and Ajax. Unlike many libraries, jQuery puts the browser object model front-and-center through its ubiquitous wrapped element sets. In this talk, you will learn to progressively enhance your web applications the jQuery way: with unobtrusive, functional JavaScript.

Along the way, you will learn how to:

  • select and modify elements with jQuery's powerful selectors
  • use jQuery's utility functions
  • register event handlers, including dynamic ones that track changes to the page over time
  • play nice with other libraries with `noConflict`
  • create Ajax requests that return HTML, JSON, and other data types
  • breathe life into your interface with effects and animations
  • unit test your JavaScript code with Screw.Unit, Smoke, and blue-ridge

Dec 01 2008

Comments

Living Lazy, Without Variables

Programmers coming to functional languages for the first time cannot imagine life without variables. I address this head-on in the Clojure book. In Section 2.7 (free download here), I port an imperative method from the Apache Commons Lang to Clojure. First the Java version:

  // From Apache Commons Lang, http://commons.apache.org/lang/
  public static int indexOfAny(String str, char[] searchChars) {
    if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
      return -1;
    }
    for (int i = 0; i < str.length(); i++) {
      char ch = str.charAt(i);
      for (int j = 0; j < searchChars.length; j++) {
        if (searchChars[j] == ch) {
            return i;
        } 
      }
    }
    return -1;
  }

And now the Clojure code. I have shown the supporting function indexed as well:

  (defn indexed [s] (map vector (iterate inc 0) s))
  (defn index-of-any [s chars]
    (some (fn [[idx char]] (if (get chars char) idx)) 
          (indexed s)))

There are many things I like about the Clojure version, but I want to focus on something I didn't mention already in the book. A reader thought the Clojure version did too much work:

...the [Java] version can be seen as *more efficient* when a match is found because scanning stops right there, whereas "indexed" constructs the whole list of pairs, regardless of whether or not a match WILL be found....

The reader's assumption is reasonable, but incorrect. Clojure's sequence library functions are generally lazy. So the call to indexed is really just a promise to generate indexes if they are actually needed.

To see this, create a logging-seq that writes to stdout every time it actually yields an element:

  (defn logging-seq [s]
    (if s
      (do (println "Iterating over " (first s))
    (lazy-cons (first s) (logging-seq (rest s))))))

Now, you can add logging-seq to indexed so that each element of indexed is of the form [index, element, logged-element].

  (defn indexed [s] (map vector (iterate inc 0) s (logging-seq s)))

Test the modified indexed function at the Clojure REPL:

  user=> (indexed "foo")
  Iterating over  f
  (Iterating over  o
  [0 \f \f] Iterating over  o
  [1 \o \o] [2 \o \o])

As you can see, the indexed sequence is only produced as needed. (At the REPL it is needed to print the return value.)

Finally, you can test indexed-of-any and see that Clojure only produces enough of the sequence to get an answer. For a match on the first character, it only goes to the first character:

  (index-of-any "foo" #{\f})
  Iterating over  f
  0

If there is no match, index-of-any has to traverse the entire string:

  (index-of-any "foo" #{\z})
  Iterating over  f
  Iterating over  o
  Iterating over  o
  nil

So give up on those variables, and live lazy!

Popular Tags