Clojure - Basic Syntax



In order to understand the basic syntax of Clojure, let’s first look at a simple Hello World program.

Hello World as a Complete Program

Write ‘Hello world’ in a complete Clojure program. Following is an example.

Example

(ns clojure.examples.hello
   (:gen-class))
(defn hello-world []
   (println "Hello World"))
(hello-world)

The following things need to be noted about the above program.

  • The program will be written in a file called main.clj. The extension ‘clj’ is the extension name for a clojure code file. In the above example, the name of the file is called main.clj.

  • The ‘defn’ keyword is used to define a function. We will see functions in details in another chapter. But for now, know that we are creating a function called helloworld, which will have our main Clojure code.

  • In our Clojure code, we are using the ‘println’ statement to print “Hello World” to the console output.

  • We then call the hello-world function which in turn runs the ‘println’ statement.

The above program produces the following output.

Output

Hello World

General Form of a Statement

The general form of any statement needs to be evaluated in braces as shown in the following example.

(+ 1 2)

In the above example, the entire expression is enclosed in braces. The output of the above statement is 3. The + operator acts like a function in Clojure, which is used for the addition of numerals. The values of 1 and 2 are known as parameters to the function.

Let us consider another example. In this example, ‘str’ is the operator which is used to concatenate two strings. The strings “Hello” and “World” are used as parameters.

(str "Hello" "World")

Example

If we combine the above two statements and write a program, it will look like the following.

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)

Output

The above program produces the following output.

Hello World
3

Namespaces

A namespace is used to define a logical boundary between modules defined in Clojure.

Current Namespace

This defines the current namespace in which the current Clojure code resides in.

Syntax

*ns*

Example

In the REPL command window run the following command.

*ns*

Output

When we run the above command, the output will defer depending on what is the current namespace. Following is an example of an output. The namespace of the Clojure code is −

clojure.examples.hello

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)

Require Statement in Clojure

Clojure code is packaged in libraries. Each Clojure library belongs to a namespace, which is analogous to a Java package. You can load a Clojure library with the ‘Require’ statement.

Syntax

(require quoted-namespace-symbol)

Example

Following is an example of the usage of this statement.

(ns clojure.examples.hello
   (:gen-class))
(require ‘clojure.java.io’)
(defn Example []
   (.exists (file "Example.txt")))
(Example)

In the above code, we are using the ‘require’ keyword to import the namespace clojure.java.io which has all the functions required for input/output functionality. Since we not have the required library, we can use the ‘file’ function in the above code.

Comments in Clojure

Comments are used to document your code. Single line comments are identified by using the ;; at any position in the line. Following is an example.

Example

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println "Hello World"))
(Example)

Delimiters

In Clojure, statements can be split or delimited by using either the curved or square bracket braces.

Example

Following are two examples.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (+ 1 2 3)))
(Example)

Output

The above program produces the following output.

6

Example

Following is another example.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println [+ 1 2 3]))
(Example)

Output

The above program produces the following output.

[#object[clojure.core$_PLUS_ 0x10f163b "clojure.core$_PLUS_@10f163b"] 1 2 3]

Whitespaces

Whitespaces can be used in Clojure to split different components of a statement for better clarity. This can be done with the assistance of the comma (,) operator.

For example, the following two statements are equivalent and the output of both the statements will be 15.

(+ 1 2 3 4 5)
(+ 1, 2, 3, 4, 5)

Although Clojure ignores commas, it sometimes uses them to make things easier for the programmer to read.

For instance, if you have a hash map like the following (def a-map {:a 1 :b 2 :c 3}) and ask for its value in the REPL window, Clojure will print the output as {:a 1, :b 2, :c 3}.

The results are easier to read, especially if you’re looking at a large amount of data.

Symbols

In Clojure, symbols are equivalent to identifiers in other programming languages. But unlike other programming languages, the compiler sees symbols as actual string values. As a symbol is a value, a symbol can be stored in a collection, passed as an argument to a function, etc., just like any other object.

A symbol can only contain alphanumeric characters and ‘* + ! / . : - _ ?’ but must not begin with a numeral or colon.

Following are valid examples of symbols.

tutorial-point!
TUTORIAL
+tutorial+

Clojure Project Structure

Finally let’s talk about a typical project structure for a Clojure project. Since Clojure code runs on Java virtual machine, most of the project structure within Clojure is similar to what you would find in a java project. Following is the snapshot of a sample project structure in Eclipse for a Clojure project.

Basic Syntax

Following key things need to be noted about the above program structure.

  • demo_1 − This is the package in which the Clojure code file is placed.

  • core.clj − This is the main Clojure code file, which will contain the code for the Clojure application.

  • The Leiningen folder contains files like clojure-1.6.0.jar which is required to run any Clojure-based application.

  • The pom.properties file will contain information such as the groupId, artifactId and version of the Clojure project.

  • The project.clj file contains information about the Clojure application itself. Following is a sample of the project file contents.

(defproject demo-1 "0.1.0-SNAPSHOT"
   :description "FIXME: write description"
   :url "http://example.com/FIXME"
   :license {
      :name "Eclipse Public License"
      :url "http://www.eclipse.org/legal/epl-v10.html"
   }
   :dependencies [[org.clojure/clojure "1.6.0"]])
Advertisements