For Development HEAD DRAFTSearch (procedure/syntax/module):

12.66 text.edn - EDN parsing and construction

Module: text.edn

EDN (Extensible Data Notation) is a subset of Clojure literals for data exchange. This module provides utilities to read and write EDN format. See https://github.com/edn-format/edn for the details of EDN.

EDNGaucheNote
true#t
false#f
nilnilClojure’s nil is not a symbol but a special value; since Clojure can’t have a symbol named nil, we can map it to Gauche’s symbol nil.
number<real>Integers and floating point numbers. The N and M suffixes in Clojure are ignored.
symbol<symbol>Clojure’s symbol name has some restrictions, so not all Gauche symbols map to EDN symbols. Clojure’s namespace-prefixed symbol, e.g. foo/bar simply maps to Gauche’s symbol foo/bar; we provide utility procedure to extract namespace and basename parts.
keyword<keyword>Clojure has keywords distinct from symbols. They are mapped to Gauche’s keywords (which is a subtype of symbols). Gauche’s keywords can also be symbols, but no Clojure symbols begin with : so there won’t be a conflict.
list<list>Clojure lists are Gauche lists. Note that Clojure doesn’t allow improper lists.
vector<vector>Clojure vectors are Gauche vectors.
map<hash-table>Clojure’s map becomes Gauche’s hashtable with edn-comparator for hashing and comparison.
set<set>Clojure’s set becomes Gauche’s set with edn-comparator for comparison. See scheme.set - R7RS sets for interface of sets.
tagged object<edn-object>Tagged objects are mapped to <edn-object> by default. You can customize the parser/writer to map tagged objects with a specific tag to a specific Gauche objects.

Parsing

Condition Type: <edn-parse-error>

When the parser encounters an error, this condition is thrown. Inherits <error>.

Function: parse-edn :optional iport

{text.edn} Read one EDN representation from the given input port, and returns Gauche object created from it. If iport is omitted, current input port is assumed.

When the parser encounters unparsable sequence, it raises <edn-parse-error>.

Note that iport may be read ahead for characters. Suppose the input consists of abc{:a b}, i.e. a symbol immediately followed by a map. The parser need to read { to know the end of the symbol. The read-ahead brace isn’t pushed back to the iport. So it would be a problem if you keep reading more EDN subsequently. Use parse-edn* if you want to read multiple objects.

Function: parse-edn* :optional iport

{text.edn} Read EDN representations repeatedly from the given input port and returns a list of them. If iport is omitted, current input port is assumed.

When the parser encounters unparsable sequence, it raises <edn-parse-error>.

Function: parse-edn-string str

{text.edn} A convenience procedure to parse EDN representation in a string str, and returns the read object.

When the parser encounters unparsable sequence, it raises <edn-parse-error>.

(parse-edn-string "[1 2 (3 4) {:a 5}]")
 ⇒ #(1 2 (3 4) #<hash-table general 0x1f05780>)

Constructing

Function: construct-edn obj :optional oport

{text.edn} Write out an EDN representation of object obj to the output port oport. If oport is omitted, current output port is assumed.

If obj contains an object that doesn’t have a defined EDN representation, a generic function edn-write is called on it. See Customization heading below. If no method is defined for the object, an error is signaled.

Function: construct-edn-string obj

{text.edn} Returns an EDN representation of obj in a string.

If obj contains an object that doesn’t have a defined EDN representation, a generic function edn-write is called on it. See Customization heading below. If no method is defined for the object, an error is signaled.

(construct-edn-string ’#(1 2 "abc")) ⇒ "[1 2 \"abc\"]"

Utilities

Function: edn-equal? a b

{text.edn} Test equality of two objects that are read from EDN representation.

Variable: edn-comparator

{text.edn} A comparator that uses edn-equal? for the equality predicate. Corresponding has function is also included. EDN maps and sets become Gauche hash-tables and sets with this comparator.

Function: edn-map key value …
Function: edn-set item …

{text.edn} Convenience procedures to create hash-tables and sets compatible for EDN.

Class: <edn-object>

{text.edn} EDN tagged object becomes an instance of this class by default. The instance has the following slots, both are immutable:

Instance Variable of <edn-object>: tag

Object’s tag. A symbol.

Instance Variable of <edn-object>: payload

Object’s payload. Can be any object that can be representable in EDN.

For example, when you read #myobject {:a 1 :b 2}, the tag is myobject and the payload is a hashtable containing mapping {:a 1 :b 2}.

Function: make-edn-object tag payload

{text.edn} Returns a new <edn-object> instance. Note: Arguments are not checked. It’s caller’s responsibility to pass valid arguments to guarantee it’s serializable as EDN.

Function: edn-object? obj

{text.edn} Returns #t iff obj is an instance of <edn-object>.

Function: edn-object-tag edn-object
Function: edn-object-payload edn-object

{text.edn} Returns the tag and the payload of edn-object, respectively.

Function: edn-symbol-prefix symbol
Function: edn-symbol-basename symbol

{text.edn} Return prefix and basename part of the symbol, respectively.

(edn-symbol-prefix 'foo/bar) ⇒ foo
(edn-symbol-basename 'foo/bar) ⇒ bar

(edn-symbol-prefix 'bar) ⇒ #f
(edn-symbol-basename 'bar) ⇒ bar
Function: edn-valid-symbol-name? str

{text.edn} Returns #t iff a string str can be a valid Clojure symbol name. It may have namespace prefix.

Customization

You can map EDN tagged objects to other Gauche objects.

Function: register-edn-object-handler! tag handler

{text.edn} Tag is a symbol, and handler is #f or a procedure that takes a tag symbol and a payload object.

Tag must have a name valid as Clojure symbol, or an error is signaled.

After the parser reads a tagged object with a symbol tag and payload, it calls handler, and the returned object becomes the result of the parser, instead of <edn-object>. Registering #f removes the previously registered handler.

This procedure is thread-safe.

The following example makes EDN #u8vector[1 2 3 4] to be read as #u8(1 2 3 4):

(register-edn-object-handler! 'u8vector
                              (^[tag vec] (vector->u8vector vec)))
Function: edn-object-handler tag

{text.edn} Returns a handler registered with a symbol tag. If a handler is not registered for tag, #f is returned. This procedure is thread-safe.

Generic Function: edn-write obj

{text.edn} Write EDN representation of obj to the current output port. The construct-edn procedure calls this internally.

To write out a Gauche object as EDN tagged object, define a method to this generic function. In the method you can call edn-write recursively to write out components of the object.

The following example writes #u8(1 2 3 4) as EDN #u8vector[1 2 3 4]:

(define-method edn-write ((x <u8vector>))
  (display "#u8vector")
  (edn-write (u8vector->vector x)))


For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT