Clojure Getting Started

this page gives an overview of common closure scripting calls.

The following steps help you write your first clojure script:

1. Get Counterclockwise, the Eclipse plug-in at http://updatesite.counterclockwise.googlecode.com/hg (for more information, see Clojure's getting started page).
2. Then create a new Clojure project and a clojure file.
3. Add the following: (println "Hello, world").
4. Run as > clojure

More detailed info on Clojure syntax, see:

Clojure Philosophy

Clojure is a functional programming language. It 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, in that it doesn't force your program to be referentially transparent, and doesn't strive for 'provable' programs. The philosophy behind Clojure is that most parts of most programs should be functional, and that programs that are more functional are more robust.

The naming convention in Clojure is to use all lowercase with hyphens separating words in multi-word names, unlike the Java convention of using camelcase.

Clojure makes heavy use of lazy evaluation. This allows functions to be invoked only when their result is needed. "Lazy sequences" are collections of results that are not computed until needed. This supports the efficient creation of infinite collections.

Common Syntax

Alternatively, see the Clojure Sample Code.

Built in forms
if : ( if (= 2 2 ) (println "true" ) (println "false" ))
 
str: (str "Value: " 5 )
 
println and def:
(def msg (str "this is four: " 4 ))
   (println msg) ; output: this is four: 4
 
do : ( do (println "Hello." ) (println (+ 4 1 )))
 
when: (when (> 50 (inc 4 ))
            (println "Yes" ))
 
let: (let [color "Red" ] (println (str "Color is: " color)) )
common arithmetic operations
add: (+ 1 2 )
 
to assign the addition to another variable: (def v3 (+ 1 2 ))
 
increment: clojure data types are immutable.
(def incrementor 0 )
(println "incrementor: " incrementor); //0
(println "incrementor: " (inc incrementor)); //1 but incrementor is unchanged
(println "incrementor: " incrementor); //0
 
You need a mutable reference to data, that can change to point to a different value later. Create a ref with ref, and alter a ref with alter. The alter must be inside a transaction, a.k.a. a dosync block.
 
(def counter (let [count (ref 0 )] #(dosync (alter count inc))))
(println "counter: " (counter)) ; 1
(println "counter: " (counter)) ; 2
 
subtract: (- 4 2 )
multiply: (* 4 2 )
divide: (/ 4 2 )
mod: (mod 4 2 )
power/roots/etc: None. Make your own function via defn.
comparisons
assignment:
(def x 2 )
 
is equal:
( if (= 2 2 ) (println "true" ) (println "false" ))
 
 
>:
(def x 3 )
( if (> x 2 ) (println "true" ) (println "false" ))
<:
(def x 1 )
( if (< x 2 ) (println "true" ) (println "false" ))
 
>=:
(def x 2 )
( if (<= x 2 ) (println "true" ) (println "false" ))
 
<=:
(def x 2 )
( if (<= x 2 ) (println "true" ) (println "false" ))
 
not:
(def x false )
( if (not x ) (println "true" ) (println "false" ))
comment
block:
(comment  
(println "Hello, world" )
)
start of line (given syntactically correct line):
#_ (println "Hello, world" )
 
end of line:
(+ 1 4 ) ; this is a comment
functions
example in c: do_something_with(value1, value2)
 
same c function in clojure: ( do -something-with value1 value2)
 
for example, a function call in clojure: (election-year? 2007 )
 
define a function:
 
(defn election-year?
{:doc "Returns boolean if the year is a presidential election year" }
    [year]
    (zero? (rem year 4 ))
)
 
(println (election-year? 2007 ))
output: false
 
empty arg function:
(defn printAll []
  (sql/with-connection db
     (sql/with-query-results rs [ "select * from users"
       (dorun (map #(println %) rs))))
)
Lists Lists can have zero or more items, enclosed in parentheses. The list's elements are delimited with a space.
vector immutable, between []
list immutable, between ()
map immutable, between {}
sets immutable, between #{}
hash-map immutable, between ()
set
(def myHashMap (hash-map :abby "actor" :ben "builder" ))
get
(println (get myHashMap :abby))
 
output: actor
def 
assoc 
dissoc 
merge- with 
doseq
(def myHashMap (hash-map :abby "actor" :ben "builder" ))
(def newMap (assoc myHashMap :chris "chemist" )) ; create a new map and add chris
(println (get myHashMap :chris)) ; the original myHashMap hasn't changed, output: nil
(println (get newMap :chris)) ; output: chemist
(println (get newMap :abby)) ; output: actor
 
(def smallerMap (dissoc newMap :abby)) ; create a new map and removes abby
(println (get smallerMap :abby)) ; removes abby output: nil
(def mergedMap (merge-with +, smallerMap, {:abby "accountant" }))
(println (get mergedMap :abby)) ; output: accountant
 
(doseq [entry mergedMap]
(println entry)) ; output: [:chris chemist] [:ben builder] [:abby accountant]
looping In the absence of mutable local variables, looping and iteration must take a different form than in languages with built-in for or while constructs that are controlled by changing state. In functional languages looping and iteration are replaced/implemented via recursive function calls. Many such languages guarantee that function calls made in tail position do not consume stack space, and thus recursive loops utilize constant space.
(loop [i 0 ]
   (when (< i 5 )
     (println i)
     (recur (inc i))))
also, dorun and doseq
sequenceSequence is not a data structure but an interface, or view, into a data structure. A sequence can be derived from a collection. The relation between collection and sequence is similar to the relation between database table and database view.

sequence from a map:
(def myHashMap (hash-map :abby "actor" :ben "builder" ))
   (doseq [entry myHashMap]
      (println entry))
 
output:
[:ben builder]
[:abby actor]
 
first: (first '( 1 2 3 ))
   content: 1
 
rest: (rest '( 1 2 3 ))
   content: ( 2 3 )
 
cons (creates a new sequence by adding the first argument to the beginning of the collection that is the second argument):
 
(cons 1 [ 2 3 ])
   content: ( 1 2 3 )
Java integration
General:
(. ( new java.util.Date) (toString))
Automated tests
(use 'clojure.test)
(deftest add-test
; The "is" macro takes a predicate, arguments to it,
; and an optional message.
(is (= 4 (+ 2 2 )))
(is (= 2 (+ 2 0 )) "adding zero doesn't change value" ))
 
(run-tests)
 
Output:
Testing automatedTests
Ran 1 tests containing 2 assertions.
0 failures, 0 errors.

More clojure test examples. More info on clojure tests.

Java integration

General
(. ( new java.util.Date) (toString))
Static methods
(println (. Boolean (valueOf "true" )))
Class and fields
(. Integer MAX_VALUE)
Import
( import '(java.io FileReader))
( new FileReader "source.txt" )
Create instance
( import 'java.util.Date)
(def today ( new Date))
; or
(def today (Date.))
Call instance methods
( import 'java.util.Date)
   (def today (Date.))
     (let [today (Date.)]
       (.getTime today)
       (.getTime today) ; called again to show calling within the let
     )
Call Java static methods
(System/currentTimeMillis)
Chaining
(..
        (Calendar/getInstance)
        (get (Calendar/MINUTE)))
Implementing interfaces and extending classes (use the reify macro):
(def my-obj
   (reify Runnable
      (run [ this ]
          (println "running ..." )
      )
   )
)
(.run my-obj)

MySQL

(Alternatively, see the entire clojure MySQL demo code.)

(ns mySQLTutorial
    (:require [clojure.contrib.sql :as sql]))
 
(def db {:classname "com.mysql.jdbc.Driver"
             :subprotocol "mysql"
             :subname "//localhost:3306/dummy"
             :user "duser"
             :password "dpass" })
 
(defn create-users []
     (sql/create-table
      :people
      [:id :integer "PRIMARY KEY" "AUTO_INCREMENT" ]
      [:fname "varchar(25)" ]
      [:lname "varchar(25)" ]
      [:town "varchar(25)" ]
      )
)
 
(defn drop-users []
    (sql/drop-table :users))
 
;;;;;;;;;inserting data is accomplished via insert-values function;;;;;;;;
(defn insert-user [fname lname town]
    (sql/insert-values :people [:fname :lname :town] [fname lname town]))
 
;;;;;;;;;;;;to update a record
(defn update-person [id attribute-map]
    (sql/update-values :people [ "id=?" id] attribute-map))
;;;;;;;;;;delete a record
(defn delete-person [id]
   (sql/with-connection db
      (sql/delete-rows :people [ "id=?" id])))

Commands

With clojure you can use all the familiar MySQL commands. In the following examples, the commands are wrapped into a def which binds the MySQL command to 'statement' . Then the command is  processed with:  (sql/with-query-results rs [statement]
(defn printAll [table]
    (sql/with-connection db
    (def statement (str "select * from " table ))
    (sql/with-query-results rs [statement]
    (dorun (map #(println %) rs))))
)
;;;;;;;;;;search for all who match a last name
(defn selectLastname [lastName]
   (println "******************" )
      (sql/with-connection db
         (def statement (str "select * from people where lname=\"" lastName "\"" ))
           (sql/with-query-results rs [statement]
             (dorun (map #(println %) rs))))
)
;;;;;;;;;;;;;call a function
(sql/with-connection db
(insert-user "40" "Denver" "Abby" "Smith" )

Join

Do a join between two tables (people and alumni) joining on last name for a specific last name where the tables are:
mysql> select * from people;
+---+--------+-------+-----------+
| id  | fname  | lname  | town        |
+---+--------+-------+-----------+
1 | Abby    | Smith  | Allenwood |
2 | Ben      | Brown | Boston      |
3 | Sandy   | Brown | Chester    |
4 | Charlie  | Brown | Dover       |
+----+-------+-------+-----------+
second table:
mysql> select * from alumni;
+---+-----+--------+-------+-------+
| id  | age | college  | fname | lname |
+---+-----+--------+-------+-------+
1 | 30   | Bacon   | Sandy | Brown |
3 | 21   | Cherry  | Scott  | Brown |
4 | 40   | Denver  | Abby  | Smith  |
+---+-----+--------+-------+-------+
(defn selectLastNameTwoTables [table1 table2 lastName]
  (sql/with-connection db
  (def statement (str "select " table1 ".lname, " table1 ".fname, " table1 ".town, " table2 ".college, " table2 ".age from " table1 ", " table2 " where " table1 ".lname = " table2 ".lname and " table1 ".fname = " table2 ".fname and " table1 ".lname = '" lastName "'" ))
(sql/with-query-results rs [statement]
(dorun (map #(println %) rs))))
)
(selectLastNameTwoTables "people" "alumni" "Brown" )
output:
{:lname Brown, :fname Sandy, :town Chester, :college Bacon, :age 30 }

References

http://clojure.blip.tv/?sort=custom;date=;view=archive;user=clojure;nsfw=dc;s=posts;page=1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值