Clojure fast food tutorial (1) - Lisp dialect running on JVM

Clojure fast food tutorial (1) - Lisp dialect running on JVM

As the most widely used programming language for virtual machines so far, Java has led to the prosperity of the language family on the JVM.
Groovy, a dynamic language designed for the JVM, is currently mainly used in the Gradle compilation environment; there are also dynamic languages ​​such as Jython and JRuby implemented on the JVM, and there are powerful mixed languages ​​such as scala.
Among them, clojure is a special one, it is a dialect of Lisp language on JVM.

call java using clojure

First, let's take a look at how to use clojure to call java methods.
With this weapon, we have the strong support of the class library of the entire java world.

First, let's look at an example to do the simplest multiplication of two large integers. Written in Java like this:

import java.math.BigInteger;

public class Test {
    public static void test(){
        BigInteger bi1 = new BigInteger("1234567890");
        BigInteger bi2 = new BigInteger("9876543210");
        System.out.println(bi1.multiply(bi2));
    }
}

Writing it in Clojure can be a little uncomfortable at first, and it will look like this:

(ns .test2)
(import java.math.BigInteger)

(println (.multiply (new BigInteger "1234567890") (new BigInteger "9876543210")))

This can make code completion a little difficult because at the time of writing .multiply, it is not known to which object or class it is applied. But Clojure is this style, function name, operator first.

Clojure's improvements to Lisp

As a Lisp dialect running on the JVM, the first advantage of Clojure is that it can seamlessly call the Java API. In addition, in response to the problem of many parentheses in Lisp, Clojure has ()added two types []of {}parentheses in addition to those commonly used in S expressions.

()Represents a list, []represents a vector, and {}is used to represent a hash table.
Also, #{}used to represent a collection.

user=> (class [])
clojure.lang.PersistentVector
user=> (class ())
clojure.lang.PersistentList$EmptyList
user=> (class {})
clojure.lang.PersistentArrayMap
user=> (class #{})
clojure.lang.PersistentHashSet

Survive in Clojure

View Help - clojure.repl/docMacros

The doc macro is used to view documentation for constants, special tables, functions, or macros. We will use it frequently in future programming.

example:

user=> (doc doc)
-------------------------
clojure.repl/doc
([name])
Macro
  Prints documentation for a var or special form given its name

list

In Lisp, list data and code are represented in the same way as S-expressions. An S-expression can be understood as a parenthesized expression that is evaluated with the first symbol.
So, if we want to avoid a list from being evaluated, we have two options:

  1. Use the list function to generate a list
  2. Use the quota special table to avoid being evaluated

example:

user=> (list 1 2 3)
(1 2 3)
user=> (doc list)
-------------------------
clojure.core/list
([& items])
  Creates a new list containing the items.
nil
user=> (quote (2 3 4))
(2 3 4)
user=> (doc quote)
-------------------------
quote
  (quote form)
Special Form
  Yields the unevaluated form.

  Please see http://clojure.org/special_forms#quote
nil
user=> '(3 4 5)
(3 4 5)

The "'" symbol is shorthand for quote.

List operations

The most commonly used car and cdr in lisp are not supported in clojure, let alone caddr and the like.

If you want to get the header, you need to use the first function, for example:

user=> (first (list 2 3 4))
2

Conversely, take the part other than the header and use the rest function, for example:

user=> (rest (list 2 3 4))
(3 4)

If you get the last element, you can use the last function to get the last element, for example:

user=> (last '(5 6 7))
7

In general, if we want to take the element of the nth subscript, we can use the nth function:

user=> (nth (list 8 9 10) 2)
10

Although there is no car and cdr, there are still cons functions that connect fist and rest together:

user=> (cons 1 '(2 3 4))
(1 2 3 4)

vector

Vectors are somewhat similar to arrays, optimized for random access to elements. Clojure uses square brackets to denote vectors.
Since it is not an S-expression, there is no need to quote.
The first, last, nth and rest functions still work for vectors.

user=> (first [1 2 3 4])
1
user=> (nth [4 5 6 7] 3)
7
user=> (rest [3 4 5 6])
(4 5 6)

But please note that rest returns not a vector, but a sequence type.
We can use the class function to see the specific type:

user=> (class (rest '(1 2 3)))
clojure.lang.PersistentList
user=> (class (rest [1 2 3]))
clojure.lang.PersistentVector$ChunkedSeq

hash table

After the parentheses and square brackets are used up, it is time for the curly brackets to come into play. That's right, curly brackets are used to denote a hash table. example:

{:name "hello", :age 18}

Access uses the name of the key as the function name to get the value, for example:

user=> (:name {:name "Hello", :age 18})
"Hello"

gather

What should I do if all the small and middle curly brackets are used up, so I have to add a "#" before the curly brackets. example:

user=> #{ 1 2 3}
#{1 3 2}

Elements in a collection cannot be repeated. If you want to build a set, you can use the sorted-set function.

user=> (sorted-set 1 2 2 3)
#{1 2 3}

variable binding

A value can be bound to a global variable using the def special table.
The data structures learned earlier can now be used to bind to variables.
def can be bound multiple times, the most recently bound value shall prevail. example:

user=> (def a '(1 2 3))
#'user/a

define function

As a dialect of Lisp, functions are an essential skill that must be learned in the survival stage.

We use the fn special table to define the function. If it is used as a function object, or called a lambda expression, it is not necessary to define a name.

For example, let's define an anonymous function for squaring:

user=> (fn [i] (* i i))
#object[user$eval17$fn__18 0x7f284218 "user$eval17$fn__18@7f284218"]

There is nothing special about functions, and they can also be bound to a variable with def. This is how we usually define functions:

user=> (def sqr (fn [i] (* i i)))
#'user/sqr
user=> (sqr 4)
16

We can also use defn macros to define functions:

user=> (defn sqr3 [i] (* i i i))
#'user/sqr3
user=> (sqr3 4)
64

Through the defn macro, you can also provide documentation for the function, and then the documentation can be viewed through the doc function. example:

user=> (defn succ "return next x" [x] (+ x 1))
#'user/succ
user=> (doc succ)
-------------------------
user/succ
([x])
  return next x
nil

summary

  • Clojure is a dialect of Lisp that runs on the JVM. There are still some differences from Lisp, such as the use []of , {}, #{}to represent vectors, hash tables and sets. For example, car, cdr, setq, etc. are not supported.
  • Clojure supports referencing java packages via import macros
  • Clojure can create java objects through new special table
  • The clojure.core/doc function is used to view the help documentation
  • def special table for binding variables
  • The fn special table is used to define functions, mainly used to define anonymous functions
  • defn macros can define documentation for functions

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325696880&siteId=291194637