I have this list of names and different languages
(setq l '((david spanish german)
(amanda italian spanish english)
(tom german french)))
I want to do the next with a function: for each language, I need every name relationed with every language.
For example, if I call the function with the list L:
(lenguages L)
I want to show this:
( (english (amanda))
(spanish (david amanda))
(italian (amanda))
(german(david tom))
(french(tom))
)
I have an idea of how to do this, but it shows just one item.
(defun lenguages(names)
(cond((null names) nil)
((list (cadar names) (list (caar names))))))
this last function only show (spanish (david))
An iteration-based task like this is best suited to Common Lisp's immensely powerful loop macro. You can read all the details about this macro in the GigaMonkeys book, but we'll just go over the parts you need for this problem here. Let's start with the function definition.
(defun lenguages (names)
...)
Inside this, we want to iterate over the provided list. We also want to collect some keys, so a hash table would be useful to have. Hash tables (called maps or dicts in many other languages) associate keys to values in a time-efficient way.
(loop with hash = (make-hash-table)
for entry in names
for name = (car entry)
do ...
finally ...)
The loop macro is very powerful and has a language all its own. The with clause declares a local variable, in this case a hash table. The first for defines an iteration variable. The loop will run with entry bound to each entry of names and will stop when it runs out of entries. The third line is another local variable, but unlike with, a for variable is rebound every time, so at each iteration name will be the first element of entry. The do block contains arbitrary Lisp code that will be executed each iteration, and finally contains a block of Lisp code to execute at the end of the loop.
Inside the do block, we want to add the person's name to the hash table entry for each language they know, so we need another loop to loop over the known languages.
(loop for lang in (cdr entry)
do (push name (gethash lang hash)))
This loop goes inside the do block of the outer one. For each language in the person's list of known languages, we want to prepend that person's name onto the hash value for that language. Normally, we would have to consider the case in which the hash key doesn't exist, but luckily for us Common Lisp defaults to nil if the hash key doesn't exist, and prepending an element to nil creates a one-element list, which is just what we want.
Now, when this loop is done, the hash table will contain all the languages and keys and lists of people who know them as values. This is the data that you want, but it's not in the format you want. In fact, if we put this in our finally block
(return hash)
We would get some semi-useful output* that tells us we're on the right track.
#S(HASH-TABLE :TEST FASTHASH-EQL ((TOM GERMAN FRENCH) . (TOM TOM))
((AMANDA ITALIAN SPANISH ENGLISH) . (AMANDA AMANDA AMANDA))
((DAVID SPANISH GERMAN) . (DAVID DAVID)))
Instead, let's do one more loop to convert this hash table to the list that you want it to be. Here's what we want in the finally block now.
(return (loop for key being the hash-keys of hash using (hash-value value)
collect (list key value)))
This uses the relatively obscure being syntax for the loop macro, which allows easy iteration over hash tables. You should read this as: for every key-value pair, collect a list containing the key followed by the value into a list, then return the accumulated list. This is yet another of the loop macros interesting features: it tries to provide primitives for common use cases such as accumulating values into a list. And it comes in handy in cases like this.
Here's the complete code block.
(defun lenguages (names)
(loop with hash = (make-hash-table)
for entry in names
for name = (car entry)
do (loop for lang in (cdr entry)
do (push name (gethash lang hash)))
finally (return (loop for key being the hash-keys of hash using (hash-value value)
collect (list key value)))))
That link I provided earlier is to the GigaMonkeys book on Common Lisp, which is available online for free. I strongly encourage reading through it, as it's an amazing reference for all things Common Lisp. Especially if you're just starting out, that book can really set you in the right direction.
* Your output format may vary on this. The implementation chooses how to output structs.
The other answer is fine: here is a version which does not use loop or intermediate hashtables, but instead builds the required association-list directly. It's worth comparing the efficiency of this against the hash-table-based one: it does a lot more searching down lists, but in practice, for small amounts of data such things are often faster (hashtables have nontrivial overhead in many implementations) and it will always use less storage as it builds no structure it does not return.
Note that:
this will return results in a different order in general (it has no dependency on hash ordering);
this will ensure there is only one occurrence of each person for each language: (languages '((david german german))) is ((german (david))) not ((german (david david))) -- it pays some performance cost (which could be ameliorated for large data using more hashtables) for doing this.
So, here it is:
(defun languages (people)
(let ((langs '())) ;the map we are building
(dolist (pl people langs)
(destructuring-bind (person . person-languages) pl
(dolist (lang person-languages)
(let ((entry (assoc lang langs)))
(if (not (null entry))
;; there's an entry for lang: add the person to it
(pushnew person (second entry))
;; there is no entry, create one with person in it
(setf langs `((,lang (,person)) ,#langs)))))))))
(Note also that the loop based version could use loop's destructuring, which might be a little clearer.)
Related
(completing-read
"Complete a foo: "
'(("foobar1" "~/foobar1/") ("barfoo" "/usr/barfoo/") ("foobaz" "/hello/")))
As shown above, I would like to prompt for "foobar1","barfoo", and "foobaz" but getting the paired directory in return.
Moverover, if I have a hash-table like this
(cl-defstruct person ID name)
(setq person-object (make-person :ID 123 :name "foo"))
(setq person-table (make-hash-table))
(pushash (person-ID person-object) person-object person-table)
How can I prompt for the person name but getting a person ID in return?
There's no way to get completing-read to return the value instead of the key, so you have to do the lookup yourself:
(let ((completions '(("foobar1" "~/foobar1/") ("barfoo" "/usr/barfoo/") ("foobaz" "/hello/"))))
(cadr (assoc (completing-read "Complete a foo: " completions) completions)))
As for the hash table, since the name is not the key, you need to iterate through every object in the hash table to find it, using maphash. Since it would be wasteful to keep iterating after you've found what you're looking for, you could use catch and throw, like this:
(catch 'found-it
(maphash
(lambda (key value)
(when (equal (person-name value) desired-name)
(throw 'found-it key)))
person-table))
This will return the person ID, or nil if there's no person whose name equals desired-name.
#legoscia provided a good answer: completing-read does not give you access to the value associated with a key that it uses for completion. E.g., for an alist COLLECTION argument, it does not give you access to the cdr of a chosen alist key.
For an alist you can use assoc to get the first matching alist element, and for a hash table you can maphash or do a get.
But these approaches preclude getting the particular value associated with a particular chosen key occurrence when there are duplicates of the key, that is, when multiple candidates have the same key, or name.
You cannot get the 2nd matching element, or the 13th. In fact, vanilla Emacs completing-read eliminates duplication of completion candidates that have the same key (name). For vanilla Emacs, any information in the cdr of an alist entry is wasted. You can use an alist, for convenience, if you already have one, but if not then you might as well just use a list of names (strings or symbols), not conses.
If you use Icicles then alist entries are not wasted. There is no problem retrieving cdr values. You can easily get to the complete information of a candidate you choose, after completing-read is done.
Icicles does this by using propertized strings as candidates, and by enhancing completing-read so that it can return the complete string, properties and all, that a user chooses. You can recuperate the complete alist entry from the propertized string that is returned.
When is it important to be able to have and use duplicate keys that can have different associated values? And how can a user tell them apart (e.g., in *Completions*), if they are duplicates?
Examples:
Bookmarks that have the same name but are for different targets - for example, for different files with the same relative name in different directories.
Lines or other text in a buffer that match a pattern or that contain a marker. This includes matches in Icicles search, where you can define search contexts any way you like (not just lines). It also includes buffer zones (including restrictions, aka narrowings) and buffer positions (markers).
Candidates that have the same text but whose annotations are different. (User input is not matched against annotations shown in *Completions*.)
Imenu items that have the same name, e.g., multiple definitions of objects (e.g. functions) that have the same name.
Tagged items (e.g. functions) that have the same name.
Candidates that are other Lisp objects, such as frames, that can have the same name.
In Icicles, how does a user choose one among several completion candidates that have the same name?
Users can control the order (sorting) of the candidates, including changing order on the fly. *Completions* shows them to you in a specific order. You can cycle among candidates or choose any of them directly. You are not limited to matching, to choose. (With duplicate candidates, matching can be insufficient to get you to only one of them.)
*Completions* can also show you additional information about candidates, which distinguishes them even when they have the same name/text. Such info could be surrounding text (if the candidates are matching buffer text), or candidate metadata (e.g. file or bookmark attributes).
You can also see important additional information about the current candidate (e.g. during cycling) in the mode line.
You can get additional information (complete *Help*) about the current candidate on demand, by hitting a key.
What do you have to do, to be able to take advantage of this Icicles feature in your own code?
See Defining Tripping Commands for how to define your own commands that let users trip among (explore) candidates might have associated positional or other navigational information. (See Tripping for predefined Icicles tripping commands.)
A brief overview of what to do in your command:
Bind variable icicle-whole-candidate-as-text-prop-p to non-nil.
Set variable icicle-candidates-alist to the alist that you pass to completing-read. This has the effect of encoding, as a text property on the candidate display string, the entire corresponding original alist entry.
Use icicle-get-alist-candidate after calling completing-read, to recover that complete information about the candidate the user chooses, that is, the complete alist element, kncluding the cdr.
(See also: Note to programmers using Icicles.)
http://www.howardism.org/Technical/Emacs/alt-completing-read.html
You have been looking for alt-completing-read !
Simpler version
(let ((choices '(("First" . 'first-choice)
("Second" . 'second-choice)
("Third" . 'third-choice))))
(alist-get
(completing-read "Choose: " choices)
choices nil nil 'equal))
Complex version
(defun alt-completing-read (prompt collection &optional predicate require-match initial-input hist def inherit-input-method)
"Calls `completing-read' but returns the value from COLLECTION.
Simple wrapper around the `completing-read' function that assumes
the collection is either an alist, or a hash-table, and returns
the _value_ of the choice, not the selected choice. For instance,
give a variable of choices like:
(defvar favorite-hosts '((\"Glamdring\" . \"192.168.5.12\")
(\"Orcrist\" . \"192.168.5.10\")
(\"Sting\" . \"192.168.5.220\")
(\"Gungnir\" . \"192.168.5.25\")))
We can use this function to `interactive' without needing to call
`alist-get' afterwards:
(defun favorite-ssh (hostname)
\"Start a SSH session to a given HOSTNAME.\"
(interactive (list (alt-completing-read \"Host: \" favorite-hosts)))
(message \"Rockin' and rollin' to %s\" hostname))"
;; Yes, Emacs really should have an `alistp' predicate to make this code more readable:
(cl-flet ((assoc-list-p (obj) (and (listp obj) (consp (car obj)))))
(let* ((choice
(completing-read prompt collection predicate require-match initial-input hist def inherit-input-method))
(results (cond
((hash-table-p collection) (gethash choice collection))
((assoc-list-p collection) (alist-get choice collection def nil 'equal))
(t choice))))
(if (listp results) (first results) results))))
If I have an atom eg "a4" I need to be able to add 1 to the "4" part to make it a5, however since it is considered a string this is not possible, so if I could split (a4) into ((a)(4)) then I could do my calculations on the 4 then stick them back together again...
However, I am not sure how to split the atom into lists of the atom's word? Is this possible?
Edit: I am currently using common lisp. I have a list of string (a3 d14 c2) etc, but I need to be able to split each of them up, separating the starting letter and the number that proceeds it.
From http://www.thefreedictionary.com/atom
Atom
[..] A part [..] considered to be an irreducible constituent of a specified system. [..]
I'd guess that this definition is what McCarthy has been thinking when he named Lisp's atoms.
Therefore, what you're trying to achieve is extremely uncommon and not how things generally work in (Common, or any) Lisp. Normally you represent data that is separate, such as your token and the number, as two different atoms and connect them e.g. using a cons cell:
(defvar *data* (cons "answer" 42))
*data*
;; => ("answer" . 42)
If you want this to be printed as answer42, well, then you have to print it:
(format t "~a~a" (car *data*) (cdr *data*))
The operation you wanted would then be something like this:
(defun inc-number (cell)
"Please give me a better name and describe here what I do"
(cons (car cell)
(inc (cdr cell))))
That said, it is of course possible to achieve what you wanted:
Using string you can get the string representation of a symbol, with intern you can (sort of) achieve the opposite. Inbetween you can manipulate the string as you like, including splitting it, converting it to a number, etc.
This can be achieved in MACLISP and INTERLISP. The function to convert a symbol in a list is called 'explode' in MACLISP and 'unpack' in INTERLISP; the function to convert a list in a symbol is called 'implode' in MACLISP, and 'pack' in INTERLISP. If your system has a GENSYM function -- a function to create symbols, as symbols are used as variables it is necessary for them to be created on the fly, specially in macro programming -- it may have functions similar to 'implode' and 'explode'.
If you are using common lisp, this google group discussion provides a implementation for 'implode' and 'explode': https://groups.google.com/forum/#!topic/comp.lang.lisp/SXhf78kCI7Q
Does emacs lisp have a function that provides a unique object identifier, such as e.g. a memory address? Python has id(), which returns an integer guaranteed to be unique among presently existing objects. What about elisp?
The only reason I know for wanting a function like id() is to compare objects, and ensure that they only compare equal if they are the same (as in, in the same memory location). In Lisps, this is done a bit differently from in Python:
In most lisps, including elisp, there are several different notions of equality. The most expensive, and weakest equivalence is equal. This is not what you want, since two lists (say) are equal if they have the same elements (tested recursively with equal). As such
(equal (list 1 2) (list 1 2)) => T
is true. At the other end of the spectrum is eq, which tests "identity" rather than equality:
(eq (list 1 2) (list 1 2)) => NIL
This is what you want, I think.
So, it seems that Python works by providing one equality test, and then a function that gives you a memory location for each object, which then can be compared as integers. In Elisp (and at least Common Lisp too), on the other hand, there is more than one meaning of "equality".
Note, there is also "eql", which lies somewhere between the two.
(EDIT: My original answer probably wasn't clear enough about why the distinction between eq and equal probably solves the problem the original poster was having)
There is no such feature in Emacs Lisp, as far as I know. If you only need equality, use eq, which performs a pointer comparison behind the scenes.
If you need a printable unique identifier, use gensym from the cl package.
If you need a unique identifier to serve as an index in a data structure, use gensym (or maintain your own unique id — gensym is simpler and less error-prone).
Some languages bake a unique id into every object, but this has a cost: either every object needs extra memory to store the id, or the id is derived from the address of the object, which precludes modifying the address. Python chooses to pay the cost, Emacs chooses not to.
My whole point in asking the question was that I was looking for a way to distinguish between the printed representations of different symbols that have the same name. Thanks to the elisp manual, I've discovered the variable print-gensym, which, when non-nil, causes #: to be prepended to uninterned symbols printed. Moreover, if the same call to print prints the same uninterned symbol more than once, it will mark the first one with #N= and subsequent ones with `#N#. This is exactly the kind of functionality I was looking for. For example:
(setq print-gensym t)
==> t
(make-symbol "foo")
==> #:foo
(setq a (make-symbol "foo"))
==> #:foo
(cons a a)
==> (#1=#:foo . #1#)
(setq b (make-symbol "foo"))
==> #:foo
(cons a b)
==> (#:foo . #:foo)
The #: notation works for read as well:
(setq a '#:foo)
==> #:foo
(symbol-name a)
==> "foo"
Note the ' on '#:foo--the #: notation is a symbol-literal. Without the ', the uninterned symbol is evaluated:
(symbol-name '#:foo)
==> "foo"
(symbol-name #:foo)
==> (void-variable #:foo)
I wonder if there is a less verbose way than using a loop. Anyway this works for me in CLISP:
(loop for key being the hash-keys of *my-hash* collect key)
I've seen others using maphash, but that involves accumulating each key into a list. Apart from that being more involved than using loop, it also introduces a side-effect, which I try to avoid whenever I can - I prefer functional programming as much as possible :)
Is there anything predefined like this for this common task, even though implementation-specific?
(defun hash-keys (hash-table)
(loop for key being the hash-keys of hash-table collect key))
Common Lisp comes from before "batteries-included" philosophy became prevalent, and most functionality is expected to be provided by third-party libraries and not implementations. While Common Lisp is sometimes called a large language, it is only compared to C and similar, the language itself is quite tiny compared to Python and other languages with massive standard libraries.
For this specific purpose, Alexandria is a commonly used collection of Common Lisp utilities. Among many other things it contains hash-table-keys.
There is no disadvantage in defining
(defun hash-keys (hash-table)
(loop for key being the hash-keys of hash-table collect key))
because in Common Lisp the function is compiled. If your vendor provided this function, it would pretty much do the same thing and not be much more efficient than yours, if at all.
In interpreted languages, nearly anything you write yourself has a performance disadvantage compared to an "intrinsic" routine.
Consing up the contents of a hash is wasteful; loop lets you process the hash without consing up memory. So maybe you want a macro instead (Some Lisps provide a dohash or similar as an extension).
(defmacro do-hash ((key-var val-var hash-expr &optional result-form) &body body)
(let ((hash-var (gensym "HASH-")))
`(loop with ,hash-var = ,hash-expr
for ,key-var being the hash-keys of ,hash-var
for ,val-var being the hash-values of ,hash-var
do (progn ,#body)
finally (return ,result-form))))
Or a hash mapping function:
(defun mapc-hash (hash-table fun)
(loop for key being the hash-keys of hash-table
for value being the hash-values of hash-table
do (funcall fun key value)))
Should the language have every possible gadget like this that anyone can write in a minute?
In Common Lisp, there are included batteries, but they are other kinds of batteries: things that are actually hard to do. For example, a compile function for dynamically compiling code at run time. It would be prohibitively difficult for most users to develop such a thing from scratch compared to pulling keys or values from a hash table in half a dozen different ways.
If you plan to use it more than once, the less lengthy solution is, to write yourself a very short helper function:
(defun hash-table-keys (ht)
(let ((keys nil))
(maphash
#'(lambda (k v)
(declare (ignore v))
(push k keys))
ht)
keys))
As you can see and as other answers have also pointed out, in many cases, it is easier to iterate all entries of a hash table, rather than constructing a filtered list and then iterating over that one.
Using the standard Common Lisp function maphash is useful in both scenarios.
Now this works just fine:
(setq al '((a . "1") (b . "2")))
(assq-delete-all 'a al)
But I'm using strings as keys in my app:
(setq al '(("a" . "foo") ("b" . "bar")))
And this fails to do anything:
(assq-delete-all "a" al)
I think that's because the string object instance is different (?)
So how should I delete an element with a string key from an association list? Or should I give up and use symbols as keys instead, and convert them to strings when needed?
If you know there can only be a single matching entry in your list, you can also use the following form:
(setq al (delq (assoc <string> al) al)
Notice that the setq (which was missing from your sample code) is very important for `delete' operations on lists, otherwise the operation fails when the deleted element happens to be the first on the list.
The q in assq traditionally means eq equality is used for the objects.
In other words, assq is an eq flavored assoc.
Strings don't follow eq equality. Two strings which are equivalent character sequences might not be eq. The assoc in Emacs Lisp uses equal equality which works with strings.
So what you need here is an assoc-delete-all for your equal-based association list, but that function doesn't exist.
All I can find when I search for assoc-delete-all is this mailing list thread:
http://lists.gnu.org/archive/html/emacs-devel/2005-07/msg00169.html
Roll your own. It's fairly trivial: you march down the list, and collect all those entries into a new list whose car does not match the given key under equal.
One useful thing to look at might be the Common Lisp compatibility library. http://www.gnu.org/software/emacs/manual/html_node/cl/index.html
There are some useful functions there, like remove*, with which you can delete from a list with a custom predicate function for testing the elements. With that you can do something like this:
;; remove "a" from al, using equal as the test, applied to the car of each element
(setq al (remove* "a" al :test 'equal :key 'car))
The destructive variant is delete*.
Emacs 27+ includes assoc-delete-all which will work for string keys, and can also be used with arbitrary test functions.
(assoc-delete-all KEY ALIST &optional TEST)
Delete from ALIST all elements whose car is KEY.
Compare keys with TEST. Defaults to ‘equal’.
Return the modified alist.
Elements of ALIST that are not conses are ignored.
e.g.:
(setf ALIST (assoc-delete-all KEY ALIST))
In earlier versions of Emacs, cl-delete provides an alternative:
(setf ALIST (cl-delete KEY ALIST :key #'car :test #'equal))
Which equivalently says to delete items from ALIST where the car of the list item is equal to KEY.
n.b. The answer by Kaz mentions this latter option already, but using the older (require 'cl) names of delete* and remove*, whereas you would now (for supporting Emacs 24+) use cl-delete or cl-remove (which are auto-loaded).
If using emacs 25 or newer you can use alist-get
(setf (alist-get "a" al t t 'equal) t)