- •Contents
- •Foreword
- •Acknowledgments
- •Preface
- •Who This Book Is For
- •What Is in This Book
- •How to Read This Book
- •Notation Conventions
- •Web Resources and Feedback
- •Downloading Sample Code
- •Getting Started
- •Why Clojure?
- •Clojure Coding Quick Start
- •Exploring Clojure Libraries
- •Introducing Lancet
- •Wrapping Up
- •Exploring Clojure
- •Forms
- •Reader Macros
- •Functions
- •Vars, Bindings, and Namespaces
- •Flow Control
- •Metadata
- •Wrapping Up
- •Working with Java
- •Calling Java
- •Optimizing for Performance
- •Creating and Compiling Java Classes in Clojure
- •Exception Handling
- •Adding Ant Projects and Tasks to Lancet
- •Wrapping Up
- •Unifying Data with Sequences
- •Everything Is a Sequence
- •Using the Sequence Library
- •Clojure Makes Java Seq-able
- •Adding Properties to Lancet Tasks
- •Wrapping Up
- •Functional Programming
- •Functional Programming Concepts
- •How to Be Lazy
- •Lazier Than Lazy
- •Recursion Revisited
- •Wrapping Up
- •Concurrency
- •The Problem with Locks
- •Refs and Software Transactional Memory
- •Use Atoms for Uncoordinated, Synchronous Updates
- •Use Agents for Asynchronous Updates
- •Managing Per-Thread State with Vars
- •A Clojure Snake
- •Making Lancet Targets Run Only Once
- •Wrapping Up
- •Macros
- •When to Use Macros
- •Writing a Control Flow Macro
- •Making Macros Simpler
- •Taxonomy of Macros
- •Making a Lancet DSL
- •Wrapping Up
- •Multimethods
- •Living Without Multimethods
- •Moving Beyond Simple Dispatch
- •Creating Ad Hoc Taxonomies
- •When Should I Use Multimethods?
- •Adding Type Coercions to Lancet
- •Wrapping Up
- •Clojure in the Wild
- •Automating Tests
- •Data Access
- •Web Development
- •Farewell
- •Editor Support
- •Bibliography
- •Index
- •Symbols
WRAPPING UP 110
In later chapters you will make these functions so much easier to use that Lancet crosses the boundary from an API to a domain-specific language.
Lancet Step 1: Ant Projects and Tasks
Download lancet/step_1_complete.clj
(ns lancet.step-1-complete
(:use clojure.contrib.except))
(def
#^{:doc "Dummy ant project to keep Ant tasks happy" } ant-project
(let [proj (org.apache.tools.ant.Project.)
logger (org.apache.tools.ant.NoBannerLogger.)] (doto logger
(.setMessageOutputLevel org.apache.tools.ant.Project/MSG_INFO) (.setOutputPrintStream System/out)
(.setErrorPrintStream System/err)) (doto proj
(.init)
(.addBuildListener logger))))
(defn instantiate-task [project name] (let [task (.createTask project name)]
(throw-if (nil? task)
IllegalArgumentException (str "No task named " name))
(doto task (.init)
(.setProject project))))
3.6 Wrapping Up
Clojure code can call directly into Java and can implement Java classes and interfaces where necessary. Do not be afraid to drop to Java when you need it. Clojure is pragmatic and does not aspire to wrap or replace Java code that already works.
One part of Java that you will use rarely is the Collections API. Clojure provides a powerful, functional, thread-safe alternative to Java collections: the sequence library. In the next chapter, you will meet Clojure’s ubiquitous sequences.
Prepared exclusively for WG Custom Motorcycles
Report erratum
this copy is (P1.0 printing, May 2009)