Venice has a rich set of data types (boolean, string, char, int, long, double, decimal, list, vector, set, and map). All data types share common features:
- they are immutable
- they support equals semantics
- they provide a hash value
- they are comparable (lower, equal, greater)
- collections support persistent manipulation
- they support meta data
Types supported in Venice:
In Venice nil is a value and has a meaning of void. nil can be used for any data type. nil has the same value as null in Java but compared to Java nil is a first class value and has a type (:core/nil).
(def x nil)
(nil? x)
(type nil)
Booleans are defined by the constants true and false.
(and true (== 1 1))
(and false (== 1 1))
(println "abcd")
(println "ab\"cd")
(println "PI: \u03C0") ;; string with unicode escaped characters
(println """{ "age": 42 }""")
(str "ab" "c" "d") ;; => "abcd"
(str/format "value: %.4f" 1.45) ;; "value: 1.4500"
;; char literals
#\A ; => "A"
#\π ; => "π"
#\u03C0 ; => "π"
(char "A") ; => "A"
(char 65) ; => "A"
;; UTF-8 code for "A"
(long #\A) ; => 65
;; Unicode PI
(println #\u03C0)
Based on the Java type Long. long is Venice's standard integer type.
(+ 1 2)
Based on the Java type Integer.
(+ 2I 3I)
Based on the Java type Double.
(+ 1.0 2.0)
Based on the Java type BigDecimal.
(+ 1.0M 2.0M)
Based on the Java type BigInteger.
(+ 1N 2N)
Number types are implicitly coerced to the most complex type in an expression
(+ 1 2.0 1.0M) ;; => 4.0M
(+ 1.0M 2.0 1I) ;; => 4.0M
Keywords (e.g. :a
) are symbolic identifiers.
{:a 100, :b 200}
[:a :b]
Symbols are identifiers that are normally used to refer to function parameters, let bindings, and global vars.
(defn sum [x y] (+ x y))
(def x 100)
(let [a 100]
(println a))
Immutable persistent list.
'(1 2 3)
(list 1 2 (+ 1 2))
(cons 1 '(2 3 4)) ;; => (1 2 3 4)
(conj '(1 2 3) 4) ;; => (1 2 3 4)
(first '(2 3 4)) ;; => 2
(rest '(2 3 4)) ;; => (3 4)
Immutable persistent vector.
[1 2 3]
(vector 1 2 (+ 1 2))
(cons 1 [2 3 4]) ;; => [1 2 3 4]
(conj [1 2 3] 4) ;; => [1 2 3 4]
(first [2 3 4]) ;; => 2
(rest [2 3 4]) ;; => [3 4]
Immutable persistent hash set.
#{1 2 3}
(set 1 2 3)
(cons 3 #{1 2}) ;; => #{1 2 3}
(contains? #{:a :b} :a) ;; => true
Immutable persistent sorted set.
(sorted-set 2 3 1)
(cons 3 (sorted-set 2 1)) ;; => #{1 2 3}
(contains? (sorted-set :a :b) :a) ;; => true
Immutable persistent hash map.
{:a 100 :b 200}
(hash-map :a 100 :b 200)
(cons {:c 3} {:a 1 :b 2}) ;; => {:a 1 :b 2 :c 3}
(get {:a 1 :b 2} :b) ;; => 2
(:b {:a 1 :b 2}) ;; => 2
(assoc {:a 1} :b 2 :c 3) ;; => {:a 1 :b 2 :c 3}
(dissoc {:a 1 :b 2 :c 3} :c :b) ;;=> {:a 1}
Immutable persistent ordered map.
(ordered-map :a 100 :b 200)
(cons {:c 3} (ordered-map :a 1 :b 2)) ;; => {:a 1 :b 2 :c 3}
(get (ordered-map :a 1 :b 2) :b) ;; => 2
(:b (ordered-map :a 1 :b 2)) ;; => 2
Immutable persistent sorted map.
(sorted-map :a 100 :b 200)
(cons {:c 3} (sorted-map :b 2 :a 1)) ;; => {:a 1 :b 2 :c 3}
(get (sorted-map :a 1 :b 2) :b) ;; => 2
(:b (sorted-map :a 1 :b 2)) ;; => 2
Threadsafe mutable stack based on the Java type ConcurrentLinkedDeque.
(stack )
(let [s (stack)]
(push! s 4)
(push! s 3)
(pop! s)
(peek s)) ;; => 4
Threadsafe mutable queue based on the Java type LinkedBlockingQueue.
(queue) ;; unbounded queue
(queue 100) ;; bounded queue
;; asynchronous access
;; offer! returns immediately with false if the queue is full otherwise
;; adds the value to the tail of the queue and returns true
;; poll! returns immediately with nil if the queue is empty
;; otherwise returns the head value
(let [q (queue 10)]
(offer! q 1)
(offer! q 2)
(offer! q 3)
(poll! q)) ;; => 1
;; asynchronous access with timeouts
;; offer! returns false the value cannot be added to the tail of the
;; queue within the given timeout time, otherwise adds the
;; value to the tail of the queue and returns true
;; poll! returns the head value of the queue if one is available
;; within the given timeout time, otherwise returns nil
(let [q (queue 10)]
(offer! q 500 1)
(offer! q 500 2)
(offer! q 500 3)
(poll! q 500)) ;; => 1
;; synchronous access
;; put! adds the value to the tail of the queue, waiting if
;; necessary for space to become available
;; take! returns the head value, waiting if necessary for a head
;; value to become available
(let [q (queue 10)]
(put! q 1)
(put! q 2)
(put! q 3)
(take! q)) ;; => 1