ClojureScript 簡單介紹

ffc8 9年前發布 | 17K 次閱讀 ClojureScript

ClojureScript 簡單介紹

這篇文章經過 Thomas Greco Jérémy Heleine 的同行評議。感謝所有 SitePoint 的評議者們,是你們使 SitePoint 的內容如此的棒!

從幾個月前起,越來越多的開發者秉承著“抱緊 JavaScript 的大腿”的理念,然而,被編譯為 JavaScript 的編程語言與日俱增,其中包含有 Dart、TypeScript、CoffeeScript、ClojureScript 等。

在這篇文章中我們會討論一下 ClojureScript,一種目標為 JavaScript 的新 Clojure 編譯器。我們會探討一下使用 ClojureScript 的好處,以及怎么樣快速的使用 npm 和“你們最愛的”Node.js 庫搭建起它的環境。

為什么使用ClojureScript?

在網上有很多的文章解釋了 ClojureScript 的好處,總的來說有以下幾點:

  • 簡潔性: 從語法角度來說,ClojureScript 是一種基于 Lisp 的語言,這使得它的語法十分簡潔。它的簡潔性使得我們甚至能在本篇文章中完全地解釋它。除此之外,ClojureScript 還提供了幫助我們更方便的異步編程的工具。

  • 安全性: 這意味著更少的漏洞!ClojureScript 和其他的函數編程語言都有很多的特性來幫助我們減少和減輕一些常見的漏洞。

  • 高性能: ClojureScript 使用了Google的Closure編譯器(譯者注:需KX上網),這使得ClojureScript能支持無用代碼清除以及其他的一些特點。

  • 實時編程: ClojureScript 生態圈提供了很多的工具來“實時編程”。這意味著當代碼一改變,在你的項目上就會馬上反應出來。在這篇文章中我們會看下Figwheel使讀者能更好的理解這個概念。

  • 代碼復用性: ClojureScript 能在全局中運行,很多人稱之“同態”。這代表你能在服務器端和客戶端運行相同的代碼,這在 Node.js 的生態系統中已經是個流行的模式了。除此之外,ClojureScript 還能使用 Node.js 和 Java 生態圈當中的庫。

安裝 Clojure(Script) 工具鏈

在這篇文章中,我們將在 Mac OSX 環境中安裝工具鏈。以防萬一,在這里你能找到 ClojureScript wik i中在其他環境下的安裝指南。首先我們將會需要一些系統依賴項,其中一個就是 OSX 下流行的包管理器,Homebrew

安裝最新版本的 Java

ClojureScript 需要最新版本的 Java (在這篇文章完成的時候為 Java8)。如果在運行 lein 這個命令的時候你遇到了一個看起來像這樣的錯誤:

Exception in thread "main" java.util.regex.PatternSyntaxException: 
    Unknown inline modifier near index 2 (?U)^[\p{Alpha}_$]^, compiling:(cljs/util.clj:158:33)

那么你就需要去安裝最新的 Java 了。

首先,讓我們在命令行界面中運行如下命令:

brew tap caskroom/cask
brew install brew-cask

如果終端出現了“already installed”這個錯誤,根據你終端中的引導將鏈接取消。一旦完成,再次安裝。如下命令可以完成這個動作:

brew unlink brew-cask
brew install brew-cask

此時,執行我們需要的最后一個命令:

brew cask install java

安裝Leiningen

Leiningen 是一個 Clojure 項目的構建工具,我們將用它來執行 ClojureScript 代碼并安裝依賴項。這一步假設你已經安裝了 Homebrew

brew install leiningen

如果這步失敗了,也許你需要手動安裝

使用Repl

既然現在我們已經安裝了 Leningen,我們就可以開始熟悉 ClojureScript 的語法了。

執行

lein rep

命令,你應該會得到類似于這樣的輸出:

$ lein repl
nREPL server started on port 58371 on host 127.0.0.1 - nrepl://127.0.0.1:58371
REPL-y 0.3.7, nREPL 0.2.10
Clojure 1.7.0
Java HotSpot(TM) 64-Bit Server VM 1.6.0_65-b14-466.1-11M4716
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=>

我們現在已經在 ClojureScript Repl 中了,這讓我們能快速執行 ClojureScript 并且查看結果。如果要離開 repl 你可以按下 Control+D。

執行這步之后,我們現在已經準備好在 ClojureScript 的語法海洋遨游并做點好玩的事啦!

ClojureScript語法

ClojureScript 是一種函數語言,這代表它使用函數以及有限的額外語言結構。在接下來的模塊中我將會講述這種語言的一些特性。

原生類型

ClojureScript 支持下列的原生類型:

  • 數字

    user=> 1.23
        1.23
  • 字符串

    user=> "foo"
        "foo"
  • 矢量(數組)

    user=> [:bar 3.14 "hello"]
        [:bar 3.14 "hello"]
  • 地圖(混合數組)

    user=> {:msg "hello" :pi 3.14 :primes [2 3 5 7 11 13]}
        {:msg "hello", :pi 3.14, :primes [2 3 5 7 11 13]}
  • 關鍵字(用于訪問地圖)

    user=> :foo
        :foo
  • 集合(唯一數組)

    user=> #{:bar 3.14 "hello"}
        #{"hello" 3.14 :bar}

全都是函數

函數是 ClojureScript 的基礎組件。你甚至是通過內置的 defn 函數來定義自己的函數。

下面是一個函數定義的例子。我們要定義一個叫 myfunction 的函數。這個函數有一個參數,叫 argument1,然后簡單的返回這個參數。這個函數沒啥用,但是可以很好的為我們示范語法。

user=> (defn myfunction [argument1] argment1)

估計你會覺得這個語法有些怪異,下面是 Javascript 的等價代碼:

function myfunction(argument1){
    return argument1;}

通過圓括號把函數名和參數包含起來的方式來調用函數。

user=> (myfunction "hello world")
"hello world"

在非函數式編程語言里,可以使用特殊的“操作符”或者關鍵字。例如 Javascript 中,通常可以用到 + - == if。但是在 ClojureScript 和其他基于 Lisp 的語言里,沒有特殊的操作符,只有常規的函數。

If 表達式是一個函數:

user=> (if true "do true stuff here" "do false stuff here")
"do true stuff here"

數學表達式也是函數,如下所示:

user=> (+ 2 3)
5
user=> (* 2 3)
6

關于更多的 Javascript 與 ClojureScript 的等價代碼的示例,可以參考這個網站

創建一個 Node.js-Clojure 項目

創建一個 ClojureScript 項目是十分方便的,Leningen 提供了項目模版來激起你的興趣并使你能迅速地掌握怎么運行一個樣板化項目。

模版是一種讓我們實驗并熟悉一些功用和設置的很好的資源。Clojars.org上有許多的模版,同時,你也可以在網上找到其他一些。在我們的項目當中,我們將使用 Nodejs Figwheel 項目模版

首先,讓我們在命令行界面中運行如下命令來開始:

$ lein new figwheel-node hello-world

這會在 ./hello-world 目錄下創建一個新的 ClojureScript 項目。這篇文章的余下部分將假設項目名稱是 hello-world,當然了,如果你想的話你可以使用其他名字,但我建議你保留這個項目名,如此一來你可以跟著文章走并且不需要害怕有什么東西會出錯。

接下來,進到我們創建的目錄當中并安裝 npm 依賴項:

$ cd hello-world
$ npm install

Points of Interest

The project folder contains a few files. In this section I want to highlight some important concepts about them:

  • package.json: This should be familiar from Node.js projects. Our npm dependencies will be added here.

  • project.clj: This file is the ClojureScript project configuration file. This is ClojureScript’s version of package.json, where we configure Clojure dependencies and compilation targets. This file also contains project details like title and description.

  • figwheel.js: This file is specific to Figweel projects. It is the bootstrap file for our project. It points Figwheel to our source code so that it can monitor it for updates. We’ll be running it with node figwheel.js.

  • ./src/hello-world/core.cljs: This is our entry-point source file. This is where we’ll start the project. Think of it similar to an index.js file in a Node.js project.

The core.cljs file contains the following content. I’ve added comments to it so that you can understand what’s going on:

;; This defines a namespace and necesscary dependencies for the current file
(ns hello-world.core
  (:require [cljs.nodejs :as nodejs]))

;; This updates the default println method to write to Node.js stdout
(nodejs/enable-util-print!)

;; The main function of the module
;; it prints "Hello World!" to stdout
(defn -main []
  (println "Hello world!"))

;; *main-cli-fn* is a semi-magic var that's used to set the entry
;; *point for a node app
(set! *main-cli-fn* -main)

Running the Project

To execute the current project, open a terminal window and move to our hello-world project directory. Then, execute the following:

lein figwheel

This will start Figwheel waiting for updates to build. Leave this terminal running and open a separate terminal. In this new terminal move again to the project directory and execute the command:

node figwheel.js

You should see the output “Hello world” as reported below:

$ node figwheel.js
Hello world!
Figwheel: trying to open cljs reload socket
Figwheel: socket connection established

Using Express.js for a Webserver

Now that we have the base of a ClojureScript project setup, let’s start working with some familiar libraries in a new terminal. In our hello_world directory execute the command:

npm install --save express

Then we need to update ./src/hello-world/core.cljs as follows:

(ns hello-world.core
  (:require [cljs.nodejs :as nodejs]
            [clojure.string :as string]))

(nodejs/enable-util-print!)

(defonce express (nodejs/require "express"))
(defonce http (nodejs/require "http"))
(defonce server-port 3000)

(def app (express))

(. app (get "/hello"
      (fn [req res] (. res (send "Hello world")))))

(def -main
  (fn []
    (doto (.createServer http #(app %1 %2))
      (.listen server-port))))
      (.listen server))))
    (println (string/join " " ["Server running on" server-port]) )
    

(set! *main-cli-fn* -main)

Now when you run node figwheel.js on the project, you should see an output saying running on 3000. If you visit the URL http://localhost:3000/hello, you should see the outcome of the express route saying “Hello world.”

Conclusions

In this article we’ve discussed how to setup a new ClojureScript project and install a popular Node dependency in it. This gives us a great base to get more familiar with ClojureScript as a language. I’ve also put together the source code for this project that you can find on Github. It goes a bit beyond this article and demonstrates how to integrate React server side rendering.

 本文由用戶 ffc8 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!