Up: Chapter 7

7.1 Snippets

Lift is built on the Scala programming language. Scala is a hybrid of Functional and Object Oriented. Two core principles of functional programming languages are immutability and transformation.
Immutability means that once a data structure is instantiated, it will not change for its life. More concretely, once you instantiate an object, you can freely pass the object around and the object will always return the same values for all its methods. Java’s String class is immutable. Python requires immutable classes as indexes to dictionaries. Immutability is also very powerful for multithreaded applications because you can pass references to immutable objects across thread boundaries without having to worry about locking or synchronization because you are guaranteed that the objects will not change state.

7.1.1 Snippet NodeSeq => NodeSeq

Transformation provides an alternative to “writing to a stream” for composing web pages. Rather than having tags that cause characters to be streamed as part of the response, Lift loads the view and for each “snippet” encountered in the view, Lift transforms just the markup associated with the snippet invocation into a new set of HTML.
Let’s make it more concrete, here’s some markup:
<span class="foo lift:WhatTime">The time is <span id="current_time">currentTime</span></span>
And the associated snippet:
object WhatTime {
  def render = "#current_time" #> (new Date).toString
}
The resulting markup will look like:
<span class="foo">The time is Mon Dec 06 21:01:36 PST 2010</span>
Let’s walk through how this works. First, the class attribute in the <span> has two classes, foo and lift:WhatTime. Any class attribute that starts with lift: indicates a snippet invocation. A snippet is a function that transforms HTML to HTML, or in Scala, NodeSeq => NodeSeq.
Lift looks up the snippet named WhatTime (See ) which in this case resolves to a singleton and invokes the render method. The render method returns a NodeSeq => NodeSeq built using Lift’s CSS Selector Transforms (See ). The parameter to the function is the Element that caused the snippet invocation with the actual snippet invocation removed from the class attribute:
<span class="foo">The time is <span id="current_time">currentTime</span></span>
The function is then applied and the resulting NodeSeq is inserted in the page where the original Element was. Because the page is composed of immutable XML objects, we can transform NodeSeq => NodeSeq and not worry about anything getting changed out from under us. We also know that we’ve got valid markup through the entire page transformation process.
Further, retaining the page as a well formed XML document allows certain tags to be put in the <head> tag and other tags to be inserted just before the close of the </body> tag (See ).
But the simplicity of the transform is simulateously easy to understand and very powerful.

7.1.2 Snippet instances

The snippet could also be defined as:
class WhatTime {
  private var x = 0
​
  def render = {
    x += 1
    "#current_time" #> ((new Date).toString + " and you’ve seen this message "+x+" times)
  }
}

7.1.3 Multiple methods on a snippet class

7.1.4 Inter-snippet communication

7.1.5 Recursive Snippets

7.1.6 Snippet parameters

Up: Chapter 7

(C) 2012 David Pollak