2015-10-20 17:26:37 +03:00
|
|
|
---
|
|
|
|
language: edn
|
|
|
|
filename: learnedn.edn
|
|
|
|
contributors:
|
|
|
|
- ["Jason Yeo", "https://github.com/jsyeo"]
|
2017-09-08 02:34:29 +03:00
|
|
|
- ["Jonathan D Johnston", "https://github.com/jdjohnston"]
|
2015-10-20 17:26:37 +03:00
|
|
|
---
|
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
Extensible Data Notation (EDN) is a format for serializing data.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
2017-09-08 02:34:29 +03:00
|
|
|
EDN is a subset of the syntax used by Clojure. Reading data defined by EDN is
|
|
|
|
safer than that defined by the full Clojure syntax, especially from untrusted
|
|
|
|
sources. EDN is restricted to data, no code. It is similar in intent to JSON.
|
|
|
|
Though it is more commonly used in Clojure, there are implementations of EDN
|
|
|
|
for many other languages.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
The main benefit of EDN over JSON and YAML is that it is extensible. We
|
2015-10-20 17:35:07 +03:00
|
|
|
will see how it is extended later on.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
2016-02-13 10:04:31 +03:00
|
|
|
```clojure
|
2015-10-20 17:26:37 +03:00
|
|
|
; Comments start with a semicolon.
|
2015-10-31 03:33:13 +03:00
|
|
|
; Anything after the semicolon is ignored.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;; Basic Types ;;;
|
|
|
|
;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2015-10-28 12:46:57 +03:00
|
|
|
nil ; also known in other languages as null
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
; Booleans
|
|
|
|
true
|
|
|
|
false
|
|
|
|
|
|
|
|
; Strings are enclosed in double quotes
|
|
|
|
"hungarian breakfast"
|
|
|
|
"farmer's cheesy omelette"
|
|
|
|
|
2017-08-23 11:14:39 +03:00
|
|
|
; Characters are preceded by backslashes
|
2015-10-20 17:26:37 +03:00
|
|
|
\g \r \a \c \e
|
|
|
|
|
2015-10-28 12:51:18 +03:00
|
|
|
; Keywords start with a colon. They behave like enums. Kind of
|
2015-10-28 12:46:57 +03:00
|
|
|
; like symbols in Ruby.
|
2015-10-20 17:26:37 +03:00
|
|
|
:eggs
|
|
|
|
:cheese
|
|
|
|
:olives
|
|
|
|
|
2015-10-28 12:46:57 +03:00
|
|
|
; Symbols are used to represent identifiers. They start with #.
|
2017-08-23 11:14:39 +03:00
|
|
|
; You can namespace symbols by using /. Whatever precedes / is
|
2015-10-28 12:46:57 +03:00
|
|
|
; the namespace of the name.
|
2015-10-20 17:26:37 +03:00
|
|
|
#spoon
|
|
|
|
#kitchen/spoon ; not the same as #spoon
|
|
|
|
#kitchen/fork
|
|
|
|
#github/fork ; you can't eat with this
|
|
|
|
|
|
|
|
; Integers and floats
|
|
|
|
42
|
|
|
|
3.14159
|
|
|
|
|
2015-10-28 12:46:57 +03:00
|
|
|
; Lists are sequences of values
|
2015-10-20 17:26:37 +03:00
|
|
|
(:bun :beef-patty 9 "yum!")
|
|
|
|
|
|
|
|
; Vectors allow random access
|
|
|
|
[:gelato 1 2 -2]
|
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
; Maps are associative data structures that associate the key with its value
|
2015-10-20 17:26:37 +03:00
|
|
|
{:eggs 2
|
|
|
|
:lemon-juice 3.5
|
|
|
|
:butter 1}
|
|
|
|
|
|
|
|
; You're not restricted to using keywords as keys
|
|
|
|
{[1 2 3 4] "tell the people what she wore",
|
|
|
|
[5 6 7 8] "the more you see the more you hate"}
|
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
; You may use commas for readability. They are treated as whitespace.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
; Sets are collections that contain unique elements.
|
|
|
|
#{:a :b 88 "huat"}
|
|
|
|
|
2015-10-20 17:35:07 +03:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;; Tagged Elements ;;;
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
; EDN can be extended by tagging elements with # symbols.
|
|
|
|
|
|
|
|
#MyYelpClone/MenuItem {:name "eggs-benedict" :rating 10}
|
|
|
|
|
|
|
|
; Let me explain this with a clojure example. Suppose I want to transform that
|
2015-10-31 22:27:44 +03:00
|
|
|
; piece of EDN into a MenuItem record.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
(defrecord MenuItem [name rating])
|
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
; To transform EDN to clojure values, I will need to use the built in EDN
|
2015-10-20 17:26:37 +03:00
|
|
|
; reader, edn/read-string
|
|
|
|
|
|
|
|
(edn/read-string "{:eggs 2 :butter 1 :flour 5}")
|
|
|
|
; -> {:eggs 2 :butter 1 :flour 5}
|
|
|
|
|
|
|
|
; To transform tagged elements, define the reader function and pass a map
|
|
|
|
; that maps tags to reader functions to edn/read-string like so
|
|
|
|
|
|
|
|
(edn/read-string {:readers {'MyYelpClone/MenuItem map->menu-item}}
|
|
|
|
"#MyYelpClone/MenuItem {:name \"eggs-benedict\" :rating 10}")
|
|
|
|
; -> #user.MenuItem{:name "eggs-benedict", :rating 10}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
# References
|
|
|
|
|
|
|
|
- [EDN spec](https://github.com/edn-format/edn)
|
|
|
|
- [Implementations](https://github.com/edn-format/edn/wiki/Implementations)
|
|
|
|
- [Tagged Elements](http://www.compoundtheory.com/clojure-edn-walkthrough/)
|