Can you have hash tables in lisp? - data-structures

Can you have hash tables or dicts in Lisp? I mean the data structure that is a collection of pairs (key, value) where values can be acceded using keys.

Common Lisp has at least four different ways to do that (key value storage):
property lists (:foo 1 :bar 2)
assoc lists ((:foo . 1) (:bar . 2))
hash tables
CLOS objects (slot-value foo 'bar) to get and (setf (slot-value foo 'bar) 42) to set. The slot name can be stored in a variable: (let ((name 'bar)) (slot-value foo name)) .
For simple usage assoc lists or property lists are fine. With a larger number of elements they tend to get 'slow'. Hash tables are 'faster' but have their own tradeoffs. CLOS objects are used like in many other object systems. The keys are the slot-names defined in a CLOS class. Though it is possible to program variants that can add and remove slots on access.

Of course - Common Lisp has hash tables.
(setq a (make-hash-table))
(setf (gethash 'color a) 'brown)
(setf (gethash 'name a) 'fred)
(gethash 'color a) => brown
(gethash 'name a) => fred
(gethash 'pointy a) => nil
Property lists are good for very small examples of demonstrative purpose, but for any real need their performance is abysmal, so use hash tables.

If you're referring to Common Lisp, hash tables are provided by a type called hash-table.
Using these tables involves creating one with function make-hash-table, reading values with gethash, setting them by using gethash as a place in concert with setf, and removing entries with remhash.
The mapping from key value to hash code is available outside of hash tables with the function sxhash.

Clojure has a built-in map type:
user=> (def m {:foo "bar" :baz "bla"})
#'user/m
user=> (m :foo)
"bar"
See http://clojure.org/data_structures

Sure. Here's the SRFI defining the standard hash table libraries in Scheme:
http://srfi.schemers.org/srfi-69/srfi-69.html

There's built-in hash tables, that use a system hash function (typically SXHASH) and where you can have a couple of different equality checkers (EQ, EQL, EQUAL or EQUALP depending on what you consider to be "the same" key).
If the built-in hash tables are not good enough, there's also a generic hash table library. It will accept any pair of "hash generator"/"key comparator" and build you a hash table. However, it relies on having a good hash function to work well and that is not necessarily trivial to write.

In Lisp it's usually called a property list.

Related

Updating list stored in hash table

I have an immutable hash table that contains a series of lists as values. I wrote a procedure so I could add an item to one of the lists, returning a new hash:
(define (update hash key item)
(hash-set hash
key
(cons item
(hash-ref hash key)))))
This seems to work fine, but feels awkward and verbose. Is there a built-in procedure that accomplishes this, or maybe a more idiomatic way of achieving the same thing?
This is as simple as it can get:
(define (update hash key item)
(hash-update hash key (curry cons item) '()))
Explanation:
hash-update returns a new hash with an updated value for the given key - or you can use hash-update! to modify the hash in-place.
hash and key are self-explanatory.
The third parameter is an updater procedure which receives as a parameter the old value, in this case it's a procedure that conses a new item (because the old value was a list); this is set as the new value for the given key.
The last parameter is the default value to be returned in case the key was not found, before calling the updater procedure.

How to add a common prefix/suffix to a list of strings?

How to add a common prefix/suffix to a list of strings?
For example:
From ("abc" "123" "xy")
To ("pre_abc" "pre_123" "pre_xy")
Try
(mapcar (lambda (c) (concat "pre_" x)) '("abc" "123" "xy"))
In Emacs without third-party libraries you use mapcar function to apply a function to every element of the list, as #sds have shown. However if you program in Elisp heavily, i recommend installing 2 third-party libraries, dash.el for list manipulation and s.el for string manipulation. These libraries introduce a huge amount of auxiliary functions with a consistent naming scheme. dash.el also have anaphoric versions for many functions, which makes code even less verbose. So to add a prefix for every string in a list you could use --map and s-prepend (s-append for suffixes):
(--map (s-prepend "x" it) '("a" "b" "c")) ;; => ("xa" "xb" "xc")
The operation to prepend is (concatenate 'string <strings ...)
So you could achieve your goal with
(cl-loop
for item in '("abc" "123" "xy")
collect (concatenate 'string "pre_" item))
A more general way to compose/generate strings would be to use format
using format would be
(cl-loop
for item in '("abc" "123" "xy")
collect (format nil "pre_~S" item))
Note using cl-lib package

Clojure: Accessing Unique Field of a Datatype Directly

Suppose I have a datatype with only one field that holds a sorted map.
(defrecord AdjacencyList [data])
(def adjacency-list (AdjacencyList. (sorted-map 1 {2 100}, 2 {3 -100})))
Now, if I want to manipulate the field and keep its type I must do something like this:
(AdjacencyList. (dissoc (:data adjacency-list) 2))
Is there a way to reference the field by calling the record?
(dissoc adjacency-list 2)
If I needed a regular hash map I could use the record's map implementation but I need a sorted map and I got other similar datatypes using sets and vectors.
A solution would be to use deftype instead and implement the required data structures myself, but I was hoping that wouldn't be necessary.
Clojure's update-in function works on all kinds of associative collections including sorted maps and defrecords:
(update-in adjacency-list [:data] dissoc 2)

Expression that returns all currently scoped symbols in Clojure?

Assume the following,
(in-ns silly.fun)
(def a 1)
(defn fx [b]
((fn [c] (return-all-symbols)) (first b)))
I was wondering if it is possible to have a return-all-symbols function that would return the map of symbols/values currently scoped at its invocation. So, assuming the above was compiled and we were in the 'silly.fun namespace, we could run something like the following.
(fx [:hello]) => {"a" 1, "b" [:hello], "c" :hello}
I would like to use return-all-symbols for debugging purposes. Is return-all-symbols at all possible? If so, what is its implementation?
It's possible, but as you've defined it you'd be pretty sad: you don't want a map with hundreds of entries referring to all the functions in clojure.core! And even if you only look in the current namespace, you forgot to include fx, which is a symbol whose value is a function. Plus there will often be lexical symbols you don't want, introduced by macros. eg, (let [[x y] foo]) would show four symbols available: foo, x, y, and something like vec__auto__4863.
Anyway, you probably have to live with some compromise over those issues, or else (and really I think this is better) specify which symbols you actually want a map of. But to automatically get values for those symbols which are either (a) lexical or (b) defined in the current namespace, and also (c) not mapping to a function, you could use:
(defmacro return-all-symbols []
(let [globals (remove (comp :macro meta val) (ns-publics *ns*))
syms (mapcat keys [globals, &env])
entries (for [sym syms]
[`(quote ~sym) sym])]
`(into {}
(for [[sym# value#] [~#entries]
:when (not (fn? value#))]
[sym# value#]))))
(def a 1)
(defn fx [b]
((fn [c] (return-all-symbols)) (first b)))
(fx [:hello])
;=> {a 1, c :hello, b [:hello]}
Namespaces contain a map with all the currently scoped vars, which gives you part of what you want. It would miss lexicaly scoped symbols from expressions like (let [x 4] (return-all-symbols)) though may still be useful for debugging:
core> (take 2 (ns-map *ns*))
([sorted-map #'clojure.core/sorted-map] [read-line #'clojure.core/read-line])
if you need more than this then you may need a real debugger that uses the java debugging
interface. check out the clojure debugging toolkit
(ns-interns) might be what you want, but using (ns-map) wrapped in (lazy-seq) works good for a big namespace.
1 (ns-map 'clojure.core)
2 {sorted-map #'clojure.core/sorted-map, read-line #'clojure.core/read-line, re-pattern #'clojure.core/re-pattern, keyword? #'clojure.core/keyword?, ClassVisitor clojure.asm.ClassVisitor, asm-type #'clojure.core/asm-type, val #'clojure.core/val, ...chop...}

Access Java fields dynamically in Clojure?

I'm a novice in clojure and java.
In order to access a Java field in Clojure you can do:
Classname/staticField
which is just the same as
(. Classname staticField)
(correct me if I'm wrong)
How can I access a static field when the name of the field in held within a variable? i.e.:
(let [key-stroke 'VK_L
key-event KeyEvent/key-stroke])
I want key-stroke to be evaluated into the symbol VK_L before it tries to access the field.
In this case you might want to do something like the following:
user=> (def m 'parseInt)
#'user/m
user=> `(. Integer ~m "10")
(. java.lang.Integer parseInt "10")
user=> (eval `(. Integer ~m "10"))
10
If you feel like it's a bit hack-ish, it's because it really is such. There might be better ways to structure the code, but at least this should work.
I made a small clojure library that translates public fields to clojure maps using the reflection API:
(ns your.namespace
(:use nl.zeekat.java.fields))
(deftype TestType
[field1 field2])
; fully dynamic:
(fields (TestType. 1 2))
=> {:field1 1 :field2 2}
; optimized for specific class:
(def-fields rec-map TestType)
(rec-map (TestType. 1 2))
=> {:field1 1 :field2 2}
See https://github.com/joodie/clj-java-fields
Reflection is probably the proper route to take, but the easiest way is
(eval (read-string (str "KeyEvent/" key-stroke)))
This will just convert the generated string into valid clojure and then evaluate it.
You can construct the right call as an s-expression and evaluate it as follows:
(let [key-stroke 'VK_L
key-event (eval `(. KeyEvent ~key-stroke))]
....do things with your key-event......)
However, if what you are trying to do is test whether a particular key has been pressed, you may not need any of this: I usually find that it is easiest to write code something like:
(cond
(= KeyEvent/VK_L key-value)
"Handle L"
(= KeyEvent/VK_M key-value)
"Handle M"
:else
"Handle some other key")

Resources