The Clojure
Programming Language
Clojure is a dynamic, general-purpose programming language, combining the
approachability and interactive development of a scripting language with an
efficient and robust infrastructure for multithreaded programming. Clojure is a
compiled language, yet remains completely dynamic – every feature supported by
Clojure is supported at runtime. Clojure provides easy access to the Java
frameworks, with optional type hints and type inference, to ensure that calls
to Java can avoid reflection.
Clojure is a dialect of Lisp, and shares with Lisp the code-as-data
philosophy and a powerful macro system. Clojure is predominantly a functional
programming language, and features a rich set of immutable, persistent data
structures. When mutable state is needed, Clojure offers a software
transactional memory system and reactive Agent system that ensure clean,
correct, multithreaded designs.
History & Development Process:
Rich Hickey is the creator of the Clojure language. Before Clojure,
he developed dotLisp, a similar project based on the .NET Framework, and three earlier
attempts to provide interoperability between Lisp and Java: a Java foreign language interface for Common
Lisp (jfli), A Foreign
Object Interface for Lisp (FOIL), and a Lisp-friendly
interface to Java Servlets (Lisplets).
Hickey spent
about 2½ years working on Clojure before releasing it publicly, much of that
time working exclusively on Clojure with no outside funding. At the end of this
time, Hickey sent an email announcing the language to some friends in the
Common Lisp community.
The
development process is community-driven and
is managed at the Clojure Community website. The website contains planning
documents and an issue tracker where bugs may be filed. General development
discussion occurs at the Clojure Dev Google Group.While anyone can submit bug
reports and ideas, to contribute patches one must sign the Clojure Contributor
agreement, JIRA tickets are processed
by a team of screeners and finally Rich Hickey approves the changes
Features:
Clojure
has a set of useful features that together form a simple, coherent, and
powerful tool.
Dynamic Development
Clojure
is a dynamic environment you can interact with. Almost all of the language
constructs are reified, and thus can be examined and changed. You can grow your
program, with data loaded, adding features, fixing bugs, testing, in an
unbroken stream.
Functional Programming
Clojure
provides the tools to avoid mutable state, provides functions as first-class
objects, and emphasizes recursive iteration instead of side-effect based
looping. Clojure is impure, yet stands behind the philosophy that programs that
are more functional are more robust.
LISP
Clojure
is a member of the Lisp family of languages. Many of the features of Lisp have
made it into other languages, but Lisp's approach to code-as-data and its macro
system still set it apart. Additionally, Clojure’s maps, sets, and vectors are
as first class in Clojure as lists are in Lisp.
Runtime Polymorphism
Systems
that utilize runtime polymorphism are easier to change and extend. Clojure
offers simple, powerful and flexible mechanisms for runtime polymorphism.
Clojure’s protocols and datatypes features add mechanisms for abstraction and
data structure definition with no compromises vs the facilities of the host
platform.
Concurrent Programming
Clojure
simplifies multi-threaded programming in several ways. Because the core data
structures are immutable, they can be shared readily between threads. Clojure,
being a practical language, allows state to change but provides mechanism to
ensure that, when it does so, it remains consistent, while alleviating
developers from having to avoid conflicts manually using locks etc.
Hosted on the JVM
Clojure
is designed to be a hosted language, sharing the JVM type system, GC, threads
etc. All functions are compiled to JVM bytecode. Clojure is a great Java
library consumer, offering the dot-target-member notation for calls to Java.
Clojure supports the dynamic implementation of Java interfaces and classes.
Example:
Hello world:
(println "Hello world!")
Defining a
function:
(defn square [x]
(* x x))
GUI
"Hello world" by calling the Java Swing library:
(javax.swing.JOptionPane/showMessageDialog nil
"Hello World" )
Using Unicode (Hello
δΈ– ("World") using the CJK code point for that word):
(println (str "Hello, " \u4e16)) ;
to the console
(javax.swing.JOptionPane/showMessageDialog nil
(str "Hello, " \u4e16 "!")); using Java GUI
A thread-safe generator
of unique serial numbers (though, like many other Lisp dialects, Clojure has a
built-in gensym function that it uses internally):
(let [i (atom 0)]
(defn
generate-unique-id
"Returns
a distinct numeric ID for each call."
[]
(swap!
i inc)))
An anonymous
subclass of java.io.Writer that
doesn't write to anything, and a macro using it to silence all prints within
it:
(def bit-bucket-writer
(proxy
[java.io.Writer] []
(write
[buf] nil)
(close
[] nil)
(flush
[] nil)))
(defmacro noprint
"Evaluates
the given expressions with all printing to *out* silenced."
[&
forms]
`(binding
[*out* bit-bucket-writer]
~@forms))
(noprint
(println
"Hello, nobody!"))
10 threads
manipulating one shared data structure, which consists of 100 vectors each one
containing 10 (initially sequential) unique numbers. Each thread then
repeatedly selects two random positions in two random vectors and swaps them.
All changes to the vectors occur in transactions by making use of Clojure's software
transactional memory system.
(defn run [nvecs nitems nthreads niters]
(let
[vec-refs (->> (range (* nvecs nitems)) (partition nitems) (map (comp
ref vec)) vec)
swap #(let [v1 (rand-int nvecs)
v2 (rand-int nvecs)
i1 (rand-int nitems)
i2 (rand-int nitems)]
(dosync
(let [tmp (nth @(vec-refs
v1) i1)]
(alter (vec-refs v1) assoc i1
(nth @(vec-refs v2) i2))
(alter (vec-refs v2) assoc i2
tmp))))
report #(let [derefed (map deref vec-refs)]
(prn derefed)
(println "Distinct:"
(->> derefed (apply concat) distinct count)))]
(report)
(dorun
(apply pcalls (repeat nthreads #(dotimes [_ niters] (swap)))))
(report)))
(run 100 10 10 100000)
Output of
prior example:
([0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16
17 18 19] ...
[990 991 992 993 994 995 996 997 998 999])
Distinct: 1000
([382 318 466 963 619 22 21 273 45 596] [808
639 804 471 394 904 952 75 289 778] ...
[484 216 622 139 651 592 379 228 242 355])
Distinct: 1000
For more information, please visit : www.programmingyan.com
No comments:
Post a Comment