4 ms·
How do I know that ("jane" "jim") is a list (like ["jane", "jim"] in JSON) rather than an associative array (like {"jane": "jim"} in JSON)? S-exs can represent
by mypalmike 10y ago
How do I know that ("jane" "jim") is a list (like ["jane", "jim"] in JSON) rather than an associative array (like {"jane": "jim"} in JSON)? S-exs can represent the difference certainly, but not in a way that is as clearly readable by humans.
The difference between lists and associative arrays is quite unambiguous and readable in JSON. This helps make the language editable by non-expert users, which is a critical benefit.
- db48x 10y agoIn general if you're making an alist in Lisp then you're going to use keys for which comparisons are cheap; you would use atoms instead of strings as the keys: '((name "Jane") ...) instead of '(("name" "Jane") ...). Strings must be compared byte-by-byte, atoms are interned and compared by pointer identity. In fact, in some Lisps (such as Common Lisp) you would probably use a special type of atom called a keyword. Keywords are just atoms with a colon at the front to indicate that they belong to the special KEYWORD package; code in two different packages can then compare them without any namespacing fuss. It would look like '((:name "Jane") ...). Lisp just takes the logic out of the syntax and puts it into the semantics of the language.
- lispm 10y agoWhat you call 'atom' is actually called 'symbol' in Lisp. Keywords are in Common Lisp a subset of symbols, those who are in the package 'KEYWORD'. Keywords also have themselves as value. Thus keywords evaluate to themselves. 'atom' means something else: 'not cons'. Anything that is not a cons cell (the two-pointer building block of linked lists) is an atom: numbers, characters, strings, symbols, arrays, ... Thus a string is an atom, too. CL-USER 1 > (typep "foobar" 'atom) T CL-USER 2 > (typep 4 'atom) T CL-USER 3 > (typep 'foobar 'atom) T CL-USER 4 > (typep '(foo . bar) 'atom) NIL True though, symbols (not atoms) are often used as keys for key/value data structures like assoc lists, property lists, hash tables, CLOS instances and others. Common Lisp also allows symbols to have arbitrary names. It uses | and \ as escape characters in symbols. CL-USER 11 > '((person |Marvin Minsky|) (|KNOWN FOR| |Artificial Intelligence Research|) (lab |MIT AI Lab|)) ((PERSON |Marvin Minsky|) (KNOWN\ FOR |Artificial Intelligence Research|) (LAB |MIT AI Lab|)) CL-USER 12 > (setf mm *) ((PERSON |Marvin Minsky|) (KNOWN\ FOR |Artificial Intelligence Research|) (LAB |MIT AI Lab|)) CL-USER 13 > (assoc '|KNOWN FOR| mm) (KNOWN\ FOR |Artificial Intelligence Research|) Symbols are by default interned in a special data structure and are looked up at read-time. Thus they are compared by pointer identity. In Common Lisp this data structure is called a package and there can be more than one package.
- db48x 10y agoYes, "symbol" is the correct term. Must have been a brain fart.
- kazinator 10y agoYou simply know that: ("jane" "jim") is a list, because that's the overwhelming convention in Lisp dialects. A common notation for vectors, used in Scheme and Common Lisp, is the hash-left-paren: #(1 2 3) ;; unambiguously a vector #() ;; empty vector There is no standard for notating a hash table; it is dialect specific. For instance, in the Racket language, they use #hash, #hasheq and #hasheqv prefixes: http://docs.racket-lang.org/reference/reader.html#%28part._parse-hashtable%29 http://docs.racket-lang.org/reference/reader.html#%28part._p... The hash contents are using the same syntax as an association list (list of dotted pairs). In TXR Lisp, I invented a different notation: a #H prefix which is followed by a compound S-expression. The first element of the S-expression is a list of optional attributes of the hash, and the remaining elements are the key-value pairs. For example: #H((:equal-based) ("jane" "jim") ("alice" "bob")) #H(() (:jane 3) (:jim 5) (:alice 7)) equal-based is needed if the keys are aggregate objects like strings, lists and vectors. In Racket these would be: #hash(("jane" . "jim") ("alice" . "bob")) #hasheq((#:jane . 3) (#:jim . 5) (#:alice . 7)) ;; keywords are #: in Racket If you want interoperable S-exps that include literals for associative arrays, you have to pick the way some dialect does it, or roll your own, and customize the reader accordingly. Or else, a decent, portable solution for general data exchange is just to use association lists, like this, which use a notation that is common to many Lisp dialects: (("jane" . "jim") ("alice" . "bob")) Though it is not denote an optimized associative array structure, the syntax (at least when it is not empty) clearly conveys that it is associative. The software which processes this can convert it to a hash table, knowing that an associative list is expected for that datum in that position of the syntax. That is to say, we use the representation of an inefficient association list (which, if used "as is" the way it comes out of the parser implies linear searching for keys) and let the applications optimize that as they see fit.