Skip to content

⚔️ Comparison of some code snippets in the Java and Clojure.

License

Notifications You must be signed in to change notification settings

hellokaton/java-clojure-syntax-comparison

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 

Repository files navigation

Java Clojure Syntax Comparison

License PRs Welcome

Comparison of some code snippets in the Java and Clojure.

  • Java Version: 1.8.0_101
  • Clojure Version: 1.9.0

Contents

📍 Basic

View contents

📚 List

View contents

📚 Array

View contents

🗺 Map

View contents

🎛️ Function

View contents

✈️ Flow Control

View contents

📜 String

View contents

⏱️ Date

View contents

➗ Math

View contents

🔭 IO

View contents

❌ Exception

View contents

❇️ Thread

View contents

📍 Basic

Hello World

Print hello world is the first thing in programming languages 😋

System.out.print("Hello World\n");

System.out.println("Hello World");
Clojure
(print "Hello World\n")
;; => Hello World

(println "Hello World")
;; => Hello World


⬆ Back to top

Comment

// This is a one-line comment

/**
 * This is a multi-line comment
 */
Clojure
; (semicolon) reader macro
; i don't know what I should do

;; The syntax is like a function: (comment & body).
(comment "
    Here are the comments
")

;; This is used to comment out a form. 
;; a corresponding pair of ( and ), or [ and ]. 
;; The form can be nested.
(def my-vec #_[1 2 3] [3 4 5])
;; [1 2 3] was ignored


⬆ Back to top

Variable

String name = "biezhi";
int age     = 2333;
Clojure

In fact, variables cannot be defined in clojure. These values ​​are immutable, like in Java final.

(def name "biezhi")
(def age  2333)

def can be creates and interns or locates a global var with the name of symbol.

(def my-number 234)
;;=> #'user/my-number
;; what's that returned thing, "#'user/my-number" ?

(type #'user/my-number)
;;=> clojure.lang.Var
; it is a Var. you just created the Var, at the same time, `my-number` has been bound to 234.

my-number
;;=> 234
user/my-number
;;=> 234

In other languages, a variable assignment looks like var myvar = "something", @myvar = "something", or String myVar = "something".

Clojure does things in a different way. First, Clojure doesn’t call it a variable assignment. It is a var binding, and this idea is a bit different from assignment in other languages.


⬆ Back to top

📚 List

Create List

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");

List<String> list = Arrays.asList("a", "b", "c");
Clojure

A list uses parentheses as its surrounding delimiters, and so an empty list would look like (), whereas a list with three elements could look like ("a" "b" "c").

(def my-list (list "a" "b" "c"))

;; There is a special function called quote that tells Clojure to just treat the
;; list as data.
(def my-list (quote ("a" "b" "c")))

;; This syntax is actually more code to type than (list "a" "b" "c"),
;; so there is a shortcut for the quote function using the ' character
(def my-list '("a" "b" "c"))

One unique thing about lists is that the first element is always evaluated as a function call, with the remaining elements as arguments. So, defining a list just using () will cause an error.


⬆ Back to top

Add item to List

list.add("d");

list.addAll(newList);
Clojure
;; returns a new collection with the xs 'added'
(conj my-list "d")
;;=> ("d" "a" "b" "c")

(cons "d" my-list)
;;=> ("d" "a" "b" "c")

(concat my-list '("d" "e" "f"))
;;=> ("a" "b" "c" "d" "e" "f")


⬆ Back to top

Get List item

String a = list.get(0);
Clojure
;; get first by list
(first my-list)
;;=> a

;; get first by list
(second my-list)
;;=> b

;; get item by index
(nth my-list 1)
;;=> b


⬆ Back to top

Get List count

int size = list.size();
Clojure
(count '(1 2 3))
;;=> 3


⬆ Back to top

📚 Array

Create Array

String[] fruits = new String[3];
fruits[0] = "peach";
fruits[1] = "pear";
fruits[2] = "apple";

String[] fruits = {"peach", "pear", "apple"};
Clojure
;; Vector []
;; A vector looks like an array and is better for random access.
;; A vector has an index to look up elements at a specific point, speeding up random access
;; Vectors and maps are the most common data structures use to hold data in Clojure

;; you can use the vector function to create a new vector
(def fruits (vector "peach", "pear", "apple"))

;; Usually you just use the [] notation to create a vector to help keep your code readable
(def fruits ["peach", "pear", "apple"])


⬆ Back to top

Get Array item

String pear = fruits[1];
Clojure
(second fruits)
;; => "pear"

(nth fruits 1)
;; => "pear"


⬆ Back to top

Get Array count

int length = fruits.length;
Clojure
(count fruits)
;;=> 3


⬆ Back to top

Two dimensional array

int[][] points = {
                {23, 45},
                {42, 88},
        };

int[] idx = points[0];
Clojure
(def points [[23, 45] [42, 88]])

(first points)
;;=> [23, 45]

(nth points 1)
;;=> [42, 88]


⬆ Back to top

🗺 Map

Create Map

Map<String, Integer> me = new HashMap<>();
me.put("name", "biezhi");
me.put("age", 2333);
Clojure
;; Map {}
;; A key / value pair data structure
;; keys are usually defined as a :keyword, although they can be anything

;; Typicall a :keyword is used for a the key in a map, with the value being
;; a string, number or another keyword
(def me {:name "biezhi",
         :age   2333
         :url   "https://github.com/biezhi"})


⬆ Back to top

Get Map item

me.get("url");
Clojure
(:name me)
;;=> "biezhi"

(get me :name)
;;=> "biezhi"

(me :name)
;;=> "biezhi"


⬆ Back to top

🎛️ Function

Define function

void sayHello() {
    System.out.println("hello");
}
Clojure
;; assign a function to a variable
(defn say-hello [] (println "hello"))

(say-hello)
;; => hello


⬆ Back to top

Function with parameters

void sayHello(String name) {
    System.out.println("hello " + name);
}
Clojure
;; define a function with parameters
(defn say-hello [name] (println (str "hello " name)))

(say-hello "world")
;; => hello world


⬆ Back to top

Anonymous function

Runnable task = () -> System.out.println("Hello Boy.");
task.run();
Clojure
(def say-hello
  (fn []
    (str "hello world")))

;; assign a function to a variable
(def say-hello
 (fn [name]
   (str "Hello " name)))

;; the same but using an anonymous function
(def say-hello
 #(str "hello " %))

;; anonymous function using two arguments
(def hello-doc #(str "Hello " %1 %2))


⬆ Back to top

With return value

String sayHello(String name) {
    return "hello " + name;
}
Clojure
(defn say-hello [name] (str "hello " name))


⬆ Back to top

Higher-order function

public void onConsumer(Consumer<String> consumer) {
    consumer.accept("let's go");
}
   
public Function<String, Integer> myConvert(){
    return Integer::parseInt;
}
Clojure

A higher-order function is:

  • a function that takes one or more functions as arguments
  • or a function that returns a function

In other languages, this feature may have another name. For example, Ruby names it block for a callee function, although the caller doesn’t have specific name.

In Clojure, caller functions are high-order functions while callees don’t have specific names. Some well known higher-order functions are map, reduce, remove, filter, and iterate.

(defn on-consumer [fn] (fn "let's go"))
(on-consumer str)
;;=> "let's go"

(defn my-convert [str] (Integer. str))
(my-convert "123")
;;=> 123


⬆ Back to top

filter

long count = IntStream.of(3, 5, 10, 2, 29, 1, 24, 13)
                      .filter(i -> i < 10)
                      .count();
Clojure

The filter function is a commonly-used higher-order functions. It takes a function as an argument. The filter function works as its name implies. It filters out values in a sequence that don’t meet the given condition. To perform this filtering, filter takes a function and a sequence for its arguments. The function given to the filter must return a truthy value, and is called a predicate function.

The syntax is: (filter pred coll)

(filter #(< % 10) [3 5 10 2 29 1 24 13])
;;=> (3 5 2 1)

(count (filter #(< % 10) [3 5 10 2 29 1 24 13]))
;;=> 4

(filter odd? (range 10))
;;=> (1 3 5 7 9)


⬆ Back to top

✈️ Flow Control

If else

int age = 23;
if (age > 18) {
    System.out.println("You have grown up, don't be like a child again.");
} else {
    System.out.println("Let's learn the cat call together, say 'miao miao miao'.");
}
Clojure

“If it is a good weather, I will go to a park; otherwise, I’ll go to a cafe.” This is called “if-branching” in the programming world. Since the if-branching uses simple conditionals, it is frequently used to divide into two states: true or false.

In Clojure, if is a special form. The syntax is:

(if test then else?) or (if test then)
(def age 14)
(if (> age 18)
  (println "You have grown up, don't be like a child again.")
  (println "Let's learn the cat call together, say 'miao miao miao'."))

In addition, Clojure has a unique way of using the if conditional with the let binding. It is if-let macro, which is useful when we want to use the result of test.

The syntax is:

(if-let bindings then) or (if-let bindings then else & oldform)
(defn weather-is-good?
        [weather]
        (if-let [actual (= :good weather)]
                (str "The weather is good? " actual)
                "The weather is at least not good."))

(weather-is-good? :good)
;;=> "The weather is good? true"

(weather-is-good? :bad)
;;=> "The weather is at least not good."

int temp = 10;
if (temp > 65) {
    System.out.println("I'll enjoy walking at a park.");
} else if (temp > 45) {
    System.out.println("I'll spend time at a cafe.");
} else {
    System.out.println("I'll curl up in my bed.");
}
Clojure
(defn what-to-do
        [temp]
        (cond
         (> temp 65) "I'll enjoy walking at a park."
         (> temp 45) "I'll spend time at a cafe."
         :else "I'll curl up in my bed."))

(what-to-do 70)
;;=> "I'll enjoy walking at a park."

(what-to-do 50)
;;=> "I'll spend time at a cafe."

(what-to-do 30)
;;=> "I'll curl up in my bed."

Clojure has condp macro also. The usage is similar to cond, but it takes a part of test right after the condp.

The syntax is: (condp pred expr & clauses)

(defn what-to-do-p
        [temp]
        (condp < temp
               65 "I'll enjoy walking at a park."
               45 "I'll spend time at a cafe."
               "I'll curl up in my bed"))

(what-to-do-p 70)
;;=> "I'll enjoy walking at a park."

(what-to-do-p 50)
;;=> "I'll spend time at a cafe."

(what-to-do-p 30)
;;=> "I'll curl up in my bed."


⬆ Back to top

Switch

int color = 3;
switch(color) {
    case 3:
        return "red";
    case 2:
        return "blue";
    case 1:
        return "pink";
    default:
        return "#000";
}
Clojure

The case macro is a similar conditional to cond/condp. It branches to multiple clauses. The difference is that case doesn’t evaluate branching expressions. In case, it should be a constant. What we can do with case looks like map (data structure).

The syntax is: (case e & clauses)

(case 3
  3 "red"
  2 "blue"
  1 "pink"
  "#000")
;;=> "red"

(defn cases-to-do [temp]
  (case temp
        :65-80 "I'll enjoy walking at a park."
        :45-64 "I'll spend time at a cafe."
        "I'll curl up in my bed"))

(cases-to-do :65-80)
;;=> "I'll enjoy walking at a park."

(my-cases :45-64)
;;=> "I'll spend time at a cafe."

(my-cases :other)
;;=> "I'll curl up in my bed"

; hash-map can't take a key that doesn't match anything
(my-cases :30) 
;;=> nil


⬆ Back to top

Not

int flag = 2333;

if (flag != 100){
    // do some thing
}
Clojure
(def flag 2333)
(if (not (= 100 flag)) (println "not eq 2333"))
;;=> not eq 2333


⬆ Back to top

And

boolean success = (result.ok && result.code == 200);
Clojure
(and (true? result.ok) (= 200 result.code))


⬆ Back to top

Or

boolean success = (result.ok || result.code == 200);
Clojure
(or (true? result.ok) (= 200 result.code))


⬆ Back to top

For

for (int i=0; i<10; i++){
    System.out.println("i = " + i);
}
Clojure

The for loop is a common concept in computer languages. When we want to apply the same logic (operations) to each element of a given array (vector or list in Clojure), we apply the idea of a for loop to that. In general, this involves incrementing (or decrementing) an index and performing a similar function on each element. However, the way to implement a for loop varies from language to language. Some use an index variable explicitly. Others use an iterator. Some use neither. Clojure takes a very different approach.

Clojure’s for is categorized as a sequence operator, like map(core function) or reduce. More importantly, in Clojure, for is used for list comprehension, which means it creates a list from a given list.

The syntax of the for macro is: (for [binding-form coll-expr filter-expr?] expr)

(for [i (range 10)] 
  (do (println (str "i =" i))))

(for [w ["LOVe" "coding" "hEllo" "worLD!"]]
           (clojure.string/capitalize w))
; like let, *for* takes binding-form
;;=> ("Love" "Coding" "Hello" "World!")

; we can get the same result using the *map* core function
(map clojure.string/capitalize ["LOVe" "coding" "hEllo" "worLD!"])
;;=> ("Love" "Coding" "Hello" "World!")

; include only when length of the word exceeds 5
(for [w ["LOVe" "coding" "hEllo" "worLD!"] :when (> (count w) 5)]
           (clojure.string/capitalize w))
;;=> ("Coding" "World!")

; using let binding
(for [w ["LOVe" "coding" "hEllo" "worLD!"] :let [length (count w)]]
           (str (clojure.string/capitalize w) ": " length))
;;=> ("Love: 4" "Coding: 6" "Hello: 5" "World!: 6")

; when the input consists of multiple vectors
(for [x ["a" "b" "c"]
      y ["a" "b" "c"]
      z ["a" "b" "c"]]
     (str x y z))
;;=> ("aaa" "aab" "aac" "aba" "abb" "abc" "aca" "acb" "acc" "baa" "bab" "bac" "bba" "bbb" "bbc" "bca" "bcb" "bcc" "caa" "cab" "cac" "cba" "cbb" "cbc" "cca" "ccb" "ccc")
String someJoin(String[] coll, String result) {
    if (coll.length == 1) {
        return result + coll[0];
    }
    StringBuilder sbuf = new StringBuilder();
    for (String str : coll) {
        sbuf.append(str).append(", ");
    }
    return sbuf.substring(0, sbuf.length() - 2);
}
Clojure

While for is somewhat like a loop, recur is a real loop in Clojure. recur represents such a remarkable idea that we might even say, “this is Clojure.”

If you have a programming background, you may have heard of tail recursion, which is a major feature of functional languages. This recur special form is the one that implements tail recursion. As the words “tail recursion” indicate, recur must be called in the tail position. In other words, recur must be the last thing to be evaluated.

The syntax of the recur macro is: (recur exprs*)

(defn some-join [coll result]
        (if (= 1 (count coll)) (str result (first coll))
          (recur (rest coll) (str result (first coll) ", "))))

(some-join ["hello" "world" "love" "coding"] "Words: ")
;;=> "Words: hello, world, love, coding"

; when we want to do something just before the recur
; we can use *do*
(defn some-join [coll result]
      (if (= 1 (count coll)) (str result (first coll))
        (do
          (println result)
          (recur (rest coll) (str result (first coll) ", ")))))

(some-join ["hello" "world" "love" "coding"] "Words: ")
;;=> Words:
;;=> Words: hello,
;;=> Words: hello, world,
;;=> "Words: hello, world, love, coding"

; however, just for printing out the process, let binding works
(defn some-join [coll result]
  (let [_ (println result)]
    (if (= 1 (count coll)) (str result (first coll))
      (recur (rest coll) (str result (first coll) ", ")))))

(some-join ["hello" "world" "love" "coding"] "Words: ")
;;=> Words:
;;=> Words: hello,
;;=> Words: hello, world,
;;=> Words: hello, world, love,
;;=> "Words: hello, world, love, coding"

; we attempted the same thing as clojure.string/join function does
(str "Words: " (clojure.string/join ", " ["hello" "world" "love" "coding"]))
;;=> "Words: hello, world, love, coding"


⬆ Back to top

While

int seq = 10;
while (seq > 0) {
    System.out.prinln("seq = " + (seq--));
}
Clojure
(def seq-num (atom 10))
(while (> @seq-num 0)
   (do (println (str "seq = " @seq-num)) (swap! seq-num dec) ))


⬆ Back to top

📜 String

to string

Integer age = 2333;
System.out.println(age.toString());
Clojure
(str 2333)
;;=> "2333"


⬆ Back to top

String append

String a = "hello " + "world " + 2333;

str is a function that turns its arguments into strings.

Clojure
(str "hello " "world " 2333)
;;=> "hello world 2333"

(str :a-keyword)
;;=> ":a-keyword"

(str false)
;;=> "false"

(map str (range 10))
;;=> ("0" "1" "2" "3" "4" "5" "6" "7" "8" "9")

When str is given multiple arguments, then it will concatenate them all into one big string.

(str "I need " 5 " of these")
;;=> "I need 5 of these"

(str "In "
     (rand-nth ["summer" "winter"])
     " I like to go "
     (rand-nth ["swimming" "running"]))
;;=> "In summer I like to go swimming"


⬆ Back to top

String replace

String url = "https://biezhi.me";
System.out.println("New url is: " + url.replace('.', '#');

String str = "A good day to you, sir.  Good day.";
System.out.println("New str is: " + url.replaceFirst("day", "night");

String str = "This is a String to use as an example to present raplaceAll";
System.out.println(str.replaceAll("This", "That"));
Clojure
(clojure.string/replace "https://biezhi.me" #"\." "#")

;; replace with Java method
(.replace "https://biezhi.me" "." "#")

;; Only replace the first match.
(clojure.string/replace-first "A good day to you, sir.  Good day." #"day" "night")
;;=> "A good night to you, sir.  Good day."

;; If there are no matches, return the original string.
(clojure.string/replace-first "A good day to you, sir." #"madam" "master")
;;=> "A good day to you, sir."

;; To title case
(clojure.string/replace "hello world" #"\b." #(.toUpperCase %1))
;;=> "Hello World"

;; replaces all a's with 1 and all b's with 2
(clojure.string/replace "a b a" #"a|b" {"a" "1" "b" "2"})
;=> "1 2 1"


⬆ Back to top

String join

String.join(", ", "jack", "biezhi", "rose", "mark")
Clojure
(clojure.string/join ", " ["jack", "biezhi", "rose", "mark"])
;;=> "jack, biezhi, rose, mark"


⬆ Back to top

String split

"jack, biezhi, rose, mark".split(", ");

"h1e2l3l4o5w6o7r8d9d".split("\\d+");
Clojure
(clojure.string/split "jack, biezhi, rose, mark" #", ")
;;=> ["jack" "biezhi" "rose" "mark"]

(clojure.string/split "h1e2l3l4o5w6o7r8d9d" #"\d+")
;;=> ["h" "e" "l" "l" "o" "w" "o" "r" "d" "d"]

;; Note that the 'limit' arg is the maximum number of strings to
;; return (not the number of splits)
(clojure.string/split "q1w2e3r4t5y6u7i8o9p0" #"\d+" 5)
;;=> ["q" "w" "e" "r" "t5y6u7i8o9p0"]

;; to get back all the characters of a string, as a vector of strings:
(clojure.string/split " q1w2 " #"")
;;=> [" " "q" "1" "w" "2" " "]

;; Note: sequence, in contrast, would return characters.
;; Using lookarounds (lookahead, lookbehind) one can keep the matching characters:
(clojure.string/split " something and ACamelName " #"(?=[A-Z])")
;;=> [" something and " "A" "Camel" "Name "]


⬆ Back to top

String substring

"biezhi".substring(1);
"biezhi".substring(0, 3);
"biezhi".substring(0, 6);
Clojure
(subs "biezhi" 1)
;;=> "iezhi"

(subs "biezhi" 0 3)
;;=> "bie"

(subs "biezhi" 0 6)
;;=> "biezhi"


⬆ Back to top

Clojure Links

About

⚔️ Comparison of some code snippets in the Java and Clojure.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages