Sorting list of cons by second object - sorting

I need to sort list of cons elements by cdr element.
For example:
(aaa.4 bbb.2 ccc.6 ddd.9 eee.3) => (bbb.2 eee.3 aaa.4 ccc.6 ddd.9)
Help me please, i just start learning Lisp.

This (aaa.4 bbb.2 ccc.6 ddd.9 eee.3) is not a list of conses, but a list of symbols named "aaa.4", "bbb.2" etc.
What your text implies is rather something like this:
((aaa . 4)
(bbb . 2)
(ccc . 6)
(ddd . 9)
(eee . 3))
You can sort a list by some key with the key argument to sort:
(sort list #'< :key #'cdr)
Sort may destructively modify the input list in order to create the sorted output list. To protect against that, copy it first:
(sort (copy-list list) #'< :key #'cdr)

Related

Racket: What does it mean to bind names to the index?

I'm writing code where the user picks from a list of choices. I have defined my list in the following:
;contains the options the user can pick
(define choices (list "choice1" "choice2" "choice3" "choice4" "choice5" "choice6" "OPENING VALUE" "HIGHEST VALUE" "LOWEST VALUE" "CLOSING VALUE" "VOLUME OF SHARES" "ADJUSTED CLOSING VALUE"))
My button gets the name from the list from the following code(only showing one example). In this case it takes the third item from the list:
[label (list-ref choices 2)]
and when I want to change the name then I use the line of code:
(send choice-4-9 set-label (list-ref choices 9))
My prof commented that I should bind names to 6 7 etc so your code would be readable. I'm still a little confused on what he meant by that and how I would do so.
He means for each index, define an identifier bound to that index, ideally named after what it means, e.g.:
(define choice1 0)
(define choice2 1)
(define choice3 2)
....
So now you can write [label (list-ref choices choice3)] instead of [label (list-ref choices 2)]. The code is more readable, and easier to change if necessary because you can change the binding of the identifier rather than every place where the number appears in code.
Incidentally, what you're doing now is called using "magic numbers."
The previous answer is good and I have upvoted it. I only want to mention that a common data structure for something like this is an association list, where you associate something like a symbol or number to a value, and then look it up using assq, assv, or assoc depending on the whether your lookup name requires eq?, eqv?, or equal? respectively. Consider:
(define choices
'((shoot . "Shoot!")
(run . "Run away!")
(reload . "Reload")
(appraise . "Search your surroundings")))
(define (get-label choice)
(let ((result (assq choice choices)))
(if (not result)
(error "???") ; handle as you see fit
(cdr result))))
;;;;;;;;;;;;;;;;
Welcome to DrRacket, version 6.4 [3m].
Language: racket/base [custom]; memory limit: 8192 MB.
> (get-label 'shoot)
"Shoot!"
>

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

Using cons, list, append in Scheme

I need to write a code that take a element and add to list that give as input, and return an new list instead of old list.. after than i will do recurssion and i need new list... below code is working fine.. however i try to reduce all set! that because confuse me and sometime i take error that i cannot solve..
How can i do this operation without set! ? I try just cons, list and append but none of them do this job.
(set! list (cons element list))
Thank you..
Just (cons element list) is enough.
Your code is altering the contents of list variable. We don't normally do that, in functional style, and the only way to do this is to use set! as you did.
But to just return the new list, which has a new element on top of it, the call (cons element list) is enough:
...
(let ((newlist (cons element oldlist)))
.....
..... use newlist and oldlist as needed

Scheme: match-lambda syntax error

I am writing a function annotate that uses match-lambda often with recursive calls to annotate. Here is one of the patterns and matches:
(`(,<param> . ,<params> (lambda (,<args>) ,<stmt> . ,<stmts>))
`(CLOSURE ENV ,(append (append `(,<param>) `(,<params>))`(,<args>)) (lambda (ENV) ,(map annotate `(,<stmt> . ,<stmts>)))))
I am getting a complaint that the first use of "." is illegal -- between "param" and "params" -- but I can't figure out why. This pattern and match doesn't get any complaints and seems very similar with regards to the first ".":
(`(λ (,<param1> . ,<params>) ,<stmt> . ,<stmts>)
`(CLOSURE ENV ,(map annotate `(,<param1> . ,<params>)) (λ (ENV) ,(map annotate `(,<stmt> . ,<stmts>)))))
Any advice is appreciated.
Thanks.
The "." is used in Racket and in Scheme to represent "improper lists"; that is, sequences of cons pairs that don't end with "empty". So, for instance,
'(3 4 . 5)
is a shorthand for
(cons 3 (cons 4 5))
The 'dot' is used to mean: "I'm done with the list-like part; here's the final value, use this instead of "empty". For this reason, you can't use the dot just anywhere in the list; it has to be just before a single, final element. In your example, the dot in the pattern precedes a bunch of elements, not just one.
Looking at your example, it looks you want to use the "..." syntax here, e.g.:
(match '(a b c d e)
[`(,x ... d e) 'ok])
(Actually, you can also use dots for infix notation in Racket, but I'm pretty sure that's not what you're trying to do, here.)

Can you have hash tables in lisp?

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.

Resources