Recursion in SBCL - recursion

I am having an issue with SBCL (on linux) which might be related to tail recursion (not that I'm entirely sure what that is). I am adding the code this time (it looks long but that's because I stretched it all out).
The deal is that I have a function 'compare-pstructs' which compares two structures. The structures, however, may have a list of those same structures as a component. Naturally, this begs for a recursive solution.
A second function 'compare-parses' is called when the above function needs to compare a list of these pstructs. Naturally, the compare-parses function must appeal to the compare-pstructs function again to compare the individual pstructs.
So, it is supposed to bounce back and forth between these functions building up the stack frames and then pop them off as it discovers individual pstructs do or don't match and do the same as whole parses are discovered to match or not.
What actually takes place is that the first time a stack frame is popped, no more recursive calls take place. Stranger yet, the loop that walks down the list of pstructs (in the compare-parses function) continues to iterate, only executing the code below the callback to the compare-pstructs function.
I am going to try combine these into one function, but still, I wonder why it doesn't work as two.
The code follows along with a log. Thanks for looking out, everybody.
-Todd
(defstruct pstruct
syntactic-info ;; A list
dependents ;; A list of more pstructs
)
(defun compare-parses (p1t p2t)
(defparameter idx 0)
(defparameter max-idx (length p1t))
;; If they're not the same length, all bets are off.
(if (not
(equal
(length p1t)
(length p2t)
)
)
(return-from compare-parses NIL)
)
(loop
(print "idx before compare pstructs:")
(print idx)
(if
(null (compare-pstructs (nth idx p1t) (nth idx p2t)))
(return-from compare-parses NIL)
)
(setf idx (1+ idx))
(print "Added one to idx:")
(print idx)
(if (>= idx max-idx)
(return)
)
)
(return-from compare-parses T)
)
(defun compare-pstructs (p1 p2)
(print "P1")
(print p1)
(print "P2")
(print p2)
(if (not (equal (pstruct-syntactic-info p1) (pstruct-syntactic-info p2)))
(return-from compare-pstructs NIL)
)
(if (and
(null (pstruct-dependents p1))
(null (pstruct-dependents p2))
)
(return-from compare-pstructs T)
)
(if (and
(not (null (pstruct-dependents p1)))
(not (null (pstruct-dependents p2)))
)
(return-from compare-pstructs
(compare-parses
(pstruct-dependents p1) (pstruct-dependents p2)
)
)
)
;; If one or the other (not both) dependents is NIL then return NIL.
(return-from compare-pstructs NIL)
)
;; Two structures for test data (notice one has an "X" stuck in it
;; to make the two different.
(defparameter x2
'#S(PSTRUCT
:SYNTACTIC-INFO ("Sfin")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("Ext" "NP" "Pron_PRON" "Pers_PRON" "S"
"Sin1" "1st" "Sin" "NomC")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("PRON" "Pron_PRON"
"Pers_PRON" "Sin1" "S"
"Sin1" "1st" "Sin"
"NomC")
:DEPENDENTS NIL)))
#S(PSTRUCT
:SYNTACTIC-INFO ("Plu" "Sin2" "Sin3" "Sin1" "Pres" "V"
"Trans_V" "TransComp_V" "Intrans_V"
"Ditrans_V" "Inf")
:DEPENDENTS NIL)
#S(PSTRUCT
:SYNTACTIC-INFO ("DNI")
:DEPENDENTS NIL))))
(defparameter y2
'#S(PSTRUCT
:SYNTACTIC-INFO ("Sfin")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("Ext" "NP" "Pron_PRON" "Pers_PRON" "S"
"Sin1" "1st" "Sin" "NomC")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("PRON" "Pron_PRON"
"Pers_PRON" "Sin1" "S"
"Sin1" "1st" "Sin"
"NomC")
:DEPENDENTS NIL)))
#S(PSTRUCT
:SYNTACTIC-INFO ("Plu" "Sin2" "Sin3" "Sin1" "Pres" "V"
"Trans_V" "TransComp_V" "Intrans_V"
"Ditrans_V" "Inf" "X") ;; <=== "X" to make them different
:DEPENDENTS NIL)
#S(PSTRUCT
:SYNTACTIC-INFO ("DNI")
:DEPENDENTS NIL))))
;; Here's the log....
* (compare-pstructs x2 y2)
"P1"
#S(PSTRUCT
:SYNTACTIC-INFO ("Sfin")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("Ext" "NP" "Pron_PRON" "Pers_PRON" "S"
"Sin1" "1st" "Sin" "NomC")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("PRON" "Pron_PRON"
"Pers_PRON" "Sin1" "S"
"Sin1" "1st" "Sin" "NomC")
:DEPENDENTS NIL)))
#S(PSTRUCT
:SYNTACTIC-INFO ("Plu" "Sin2" "Sin3" "Sin1" "Pres" "V"
"Trans_V" "TransComp_V" "Intrans_V"
"Ditrans_V" "Inf")
:DEPENDENTS NIL)
#S(PSTRUCT :SYNTACTIC-INFO ("DNI") :DEPENDENTS NIL)))
"P2"
#S(PSTRUCT
:SYNTACTIC-INFO ("Sfin")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("Ext" "NP" "Pron_PRON" "Pers_PRON" "S"
"Sin1" "1st" "Sin" "NomC")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("PRON" "Pron_PRON"
"Pers_PRON" "Sin1" "S"
"Sin1" "1st" "Sin" "NomC")
:DEPENDENTS NIL)))
#S(PSTRUCT
:SYNTACTIC-INFO ("Plu" "Sin2" "Sin3" "Sin1" "Pres" "V"
"Trans_V" "TransComp_V" "Intrans_V"
"Ditrans_V" "Inf" "X")
:DEPENDENTS NIL)
#S(PSTRUCT :SYNTACTIC-INFO ("DNI") :DEPENDENTS NIL)))
"idx before compare pstructs:"
0
"P1"
#S(PSTRUCT
:SYNTACTIC-INFO ("Ext" "NP" "Pron_PRON" "Pers_PRON" "S" "Sin1" "1st" "Sin"
"NomC")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("PRON" "Pron_PRON" "Pers_PRON" "Sin1" "S"
"Sin1" "1st" "Sin" "NomC")
:DEPENDENTS NIL)))
"P2"
#S(PSTRUCT
:SYNTACTIC-INFO ("Ext" "NP" "Pron_PRON" "Pers_PRON" "S" "Sin1" "1st" "Sin"
"NomC")
:DEPENDENTS (#S(PSTRUCT
:SYNTACTIC-INFO ("PRON" "Pron_PRON" "Pers_PRON" "Sin1" "S"
"Sin1" "1st" "Sin" "NomC")
:DEPENDENTS NIL)))
"idx before compare pstructs:"
0
"P1"
#S(PSTRUCT
:SYNTACTIC-INFO ("PRON" "Pron_PRON" "Pers_PRON" "Sin1" "S" "Sin1" "1st"
"Sin" "NomC")
:DEPENDENTS NIL)
"P2"
#S(PSTRUCT
:SYNTACTIC-INFO ("PRON" "Pron_PRON" "Pers_PRON" "Sin1" "S" "Sin1" "1st"
"Sin" "NomC")
:DEPENDENTS NIL)
"Added one to idx:"
1
"Added one to idx:" <== See how the loop keeps iterating
2
T
*

Don't use DEFPARAMETER inside functions. It defines a global variable, which messes up your logic in COMPARE-PARSES since the recursive calls will use the same variables.
Your code is rather unidiomatic Lisp. You shouldn't use IFs and RETURN-FROM like that. Structure the functions into single expressions instead.
(defstruct pstruct
;; Instead of comments to say what type these are,
;; you could use code to tell it.
(syntactic-info nil :type list)
(dependents nil :type list))
;; Since the functions call each other, it's better to declare
;; their ftypes beforehand.
(declaim (ftype (function (list list) boolean) compare-parses)
(ftype (function (pstruct pstruct) boolean) pstruct=))
(defun compare-parses (p1t p2t)
(and (= (length p1t)
(length p2t))
(every #'pstruct= p1t p2t)))
(defun pstruct= (p1 p2)
(and (equal (pstruct-syntactic-info p1)
(pstruct-syntactic-info p2))
(compare-parses (pstruct-dependents p1)
(pstruct-dependents p2))))
Common Lisp also provides some debugging tools, so you don't need to PRINT things. In this case you can use TRACE
CL-USER> (trace compare-parses pstruct=)
CL-USER> (pstruct= *x2* *y2*)
... Prints the trace ...
CL-USER> (untrace compare-parses pstruct=)
If you're using Emacs and Slime/Sly, you can also use the trace dialog for a bit nicer interface.
Also see BREAK, INSPECT, STEP and the Slime equivalents.

Okay, the expert above came up with a solution to my problem. I did make a big mistake using defparameter. I did this here to get rid of the SBCL warnings, and since the HyperSpec said: "defparameter and defvar normally appear as a top level form, but it is meaningful for them to appear as non-top-level forms."
I took this to mean that it would maintain variables at local scope, but this is not true!! Ouch. Anyway, the code didn't work before adding the defparameter macro nor after removing it.
One other mistake seems to be thinking that stretching the code out farther and farther during the debugging process until you end up with something that looks and executes like (ugh) Pascal or Python doesn't help. I am speculating that the optimizer has been hard-coded to expect program flow to be a particular way, and may be unpredictable if code is intentionally inefficient.
My original code was more condensed, but though logically identical, I couldn't get it to work. Of course, at my current level of skill with Lisp I never would have guessed how to condense the code down as far as the expert above did... I mean, "every"? I never knew there was a built-in for that!!

Related

Common Lisp: Zip arbitrary number of lists

Suppose you have a list of lists, e.g. '(("abc" "def" "ghi") ("012" "345" "678") ("jkl" "mno" "pqr")) or '(("ab" "cd" "ef") ("01" "23" "45")).
What would be the canonical way to zip the lists inside the given list?
I.e. how would func be defined such that
(func '(("ab" "cd" "ef") ("01" "23" "45")) :sep "|" :combiner #'concat)
;; => ("ab|01" "cd|23" "ef|45")
(func '(("abc" "def" "ghi") ("012" "345" "678") ("jkl" "mno" "pqr")) ...)
;; => ("abc|012|jkl" "def|345|mno" "ghi|678|pqr")
where concat := (lambda (args) ...) is the function that combines the heads of the respective lists.
Presumably, this type of operation is known as rotation or zipMany (according to the answers for related questions for different languages).
I have something like this (double-apply)
(apply #'mapcar #'(lambda (&rest args) (apply #'concatenate 'string args)) lst)
where lst is '(("ab" "cd" "ef") ("01" "23" "45"))
for example. The combiner would be concatenate. Note that no separator is given in this example implementation.
But this seems awfully convoluted.
So, what would be a canonical implementation for this kind of operation?
For an arbitray number of lists, you'd need to get rid of apply #'mapcar, because otherwise the number of lists would be limited by call-arguments-limit.
One typical way would be to use reduce instead, combining two lists at a time:
(defun zip (list-of-lists &key (combiner #'concat))
(reduce (lambda (list-a list-b)
(mapcar combiner list-a list-b))
list-of-lists))
If you don't like the explicit lambda form, you might like curry, e. g. from alexandria:
(defun zip (list-of-lists &key (combiner #'concat))
(reduce (curry #'mapcar combiner)
list-of-lists))
Other looping constructs are loop, do, dolist, and there are also a few looping libraries, e. g. iterate, for.
Join
(defun %d (stream &rest args)
"internal function, writing the dynamic value of the variable
DELIM to the output STREAM. To be called from inside JOIN."
(declare (ignore args)
(special delim))
(princ delim stream))
(defun join (list delim)
"creates a string, with the elements of list printed and each
element separated by DELIM"
(declare (special delim))
(format nil "~{~a~^~/%d/~:*~}" list))
Goal
don't use &rest args or apply - which would limit our list lengths.
Recursive MAPCARS
(defun mapcars (f l)
(if (null (car l))
'()
(cons (funcall f (mapcar #'car l))
(mapcars f (mapcar #'cdr l)))))
Iterative MAPCARS
(defun mapcars (f l)
(loop for l1 = l then (mapcar #'cdr l1)
while (car l1)
collect (funcall f (mapcar #'car l1))))
Usage
CL-USER 10 > (mapcars (lambda (l) (join l "|")) l)
("abc|012|jkl" "def|345|mno" "ghi|678|pqr")
Your function works, but relies on APPLY.
The number of lists you can pass to apply is limited by CALL-ARGUMENTS-LIMIT, which may be large enough in a given implementation. Your function, however, is supposed to accept an arbitrary number of lists, and so, if you want to code portably, you shouldn't use apply in your case.
Zip
The zip function combines all first elements, then all second elements, etc. from a list of lists.
If your input list of lists is the following:
'((a b c d)
(0 1 2 3)
(x y z t))
Then zip will build the following list:
(list (combine (list a 0 x))
(combine (list b 1 y))
(combine (list c 2 z))
(combine (list d 3 t)))
If you look closely, you can see that you can split the work being done as mapping of the combine function over the transpose of your initial list of lists (viewed as a matrix):
((a b c d) ((a 0 x)
(0 1 2 3) ===> (b 1 y)
(x y z t)) (c 2 z)
(d 3 t))
And so, zip can be defined as:
(defun zip (combine lists)
(mapcar #'combine (transpose lists)))
Alternatively, you could use MAP-INTO, if you care about reusing the memory that is allocated when calling transpose:
(defun zip (combiner lists &aux (transposed (transpose lists)))
(map-into transposed combiner transposed))
Transpose
There are different ways to transpose a list of lists. Here I am going to use REDUCE, which is known as fold in some other functional languages. At each step of reduction, the intermediate reducing function will take a partial result and a list, and produce a new result. Our result is also a list of lists.
Below, I show the current list at each step of reduction, and the resulting list of lists.
First step
(a b c d) => ((a)
(b)
(c)
(d))
Second step
(0 1 2 3) => ((0 a)
(1 b)
(2 c)
(3 d))
Third step
(x y z t) => ((x 0 a)
(y 1 b)
(z 2 c)
(t 3 d))
Note that elements are pushed in front of each lists, which explains why each resulting list is reversed w.r.t. the expect result.
The transpose function should thus reverse each list after performing reduction:
(defun transpose (lists)
(mapcar #'reverse
(reduce (lambda (result list)
(if result
(mapcar #'cons list result)
(mapcar #'list list)))
lists
:initial-value nil)))
Like previously, it might be preferable to avoid allocating too much memory.
(defun transpose (lists)
(let ((reduced (reduce (lambda (result list)
(if result
(mapcar #'cons list result)
(mapcar #'list list)))
lists
:initial-value nil)))
(map-into reduced #'nreverse reduced)))
Example
(transpose '(("ab" "cd" "ef") ("01" "23" "45")))
=> (("ab" "01") ("cd" "23") ("ef" "45"))
(import 'alexandria:curry)
(zip (curry #'join-string "|")
'(("ab" "cd" "ef") ("01" "23" "45")))
=> ("ab|01" "cd|23" "ef|45")
Edit: the other answers already provide example definitions for join-string. You could also use the join function from cl-strings.
How about:
(defun unzip (lists &key (combiner #'list))
(apply #'mapcar combiner lists))
Then you should make join:
(defun join (l &key (sep ", "))
(format nil (format nil "~a~a~a" "~{~a~^" sep "~}") l))
Then either make a wrapper or a lambda for your specific use:
(unzip '(("abc" "def" "ghi") ("012" "345" "678") ("jkl" "mno" "pqr"))
:combiner (lambda (&rest l) (join l :sep "|")))
; ==> ("abc|012|jkl" "def|345|mno" "ghi|678|pqr")
Originally, I tried using backquote and splice ,# and defining a macro to get rid of the applys. But as #coredump pointed out, that bears then other problems.
Anyhow, you need the Pythonic function join() as a combiner, if you want to add separators between the joined elements. concatenate will make the things more complicated if the function should behave in the way you want it to.
Since I use #Sylwester's very elegant join() definition, my answer will be very similar to his. Maybe my answer is the closest to your original example.
(defun join (l &key (sep ", "))
(format nil (format nil "~a~a~a" "~{~a~^" sep "~}") l))
Using this, we can define your func to:
(defun func (lists &key (sep "|") (combiner #'join))
(apply #'mapcar
#'(lambda (&rest args) (funcall combiner args :sep sep))
lists))
Or without apply - how #Rainer Joswig points out - and all previous answerers, too - because it has restriction in number of arguments which it can take (~50):
(defun func (lists &key (sep "|") (combiner #'join))
(reduce #'(lambda (l1 l2)
(mapcar #'(lambda (e1 e2)
(funcall combiner (list e1 e2) :sep sep)) l1 l2))
lists))
Or slightly shorter:
(defun func (lists &key (sep "|") (combiner #'join))
(reduce #'(lambda (l1 l2)
(mapcar #'(lambda (&rest l) (funcall combiner l :sep sep)) l1 l2))
lists))
Testing:
(func '(("abc" "def" "ghi") ("012" "345" "678") ("jkl" "mno" "pqr")))
;; ("abc|012|jkl" "def|345|mno" "ghi|678|pqr")
Note that :sep "" makes join equivalent to the function concatenate.
(func '(("abc" "def" "ghi") ("012" "345" "678") ("jkl" "mno" "pqr")) :sep "")
;; ("abc012jkl" "def345mno" "ghi678pqr")
Thanks to #Sylwester, #coredump and #Rainer Joswig!
Why do not use the &rest in params and return that on the lambda function.
CL-USER> (mapcar (lambda (&rest l) l) '(1 2 3) '(a b c) '("cat" "duck" "fish"))
((1 A "cat") (2 B "duck") (3 C "fish"))
then you can use apply like this:
(apply #'mapcar (lambda (&rest l) l) '(("ab" "cd" "ef") ("01" "23" "45")))
; => (("ab" "01") ("cd" "23") ("ef" "45"))
until here, is what a normal zip would do, now you want to join that sublist into one string, with some custom separator.
for that the best answer is use format, and also like this answer
from stackoverflow here https://stackoverflow.com/a/41091118/1900722
(defun %d (stream &rest args)
"internal function, writing the dynamic value of the variable
DELIM to the output STREAM. To be called from inside JOIN."
(declare (ignore args)
(special delim))
(princ delim stream))
(defun join (list delim)
"creates a string, with the elements of list printed and each
element separated by DELIM"
(declare (special delim))
(format nil "~{~a~^~/%d/~:*~}" list))
Then you only need to use mapcar again on this functions and the result list from zip
(mapcar (lambda (lst) (join lst "|")) '(("ab" "01") ("cd" "23") ("ef" "45")))
; => ("ab|01" "cd|23" "ef|45")

Common Lisp let function

I'm just starting to program in Common Lisp and going back through programs that I coded during some of my previous classes to learn and I am having trouble understanding the problem in my code.
(defun input-1 ()
(defvar *message* (read-line))
(defvar *a-value* (parse-integer(read-line)))
(defvar *b-value* (parse-integer(read-line))))
(defun alphabet (list " " "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m"
"n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"))
(defun alphabet-num (list 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29))
;(defun inverse (value)
; (let ((x 0))
; (loop while (< x 29)
; (print x))))
(defun inverse (value)
(dotimes (x 28)
(when (equal (mod (* x value) 29) 1)
(return-from inverse x))))
(defun get-int (string)
(getf (position string alphabet) alphabet-num))
(defun get-string (int)
(getf (position int alphabet) alphabet))
(defun cipher-calc (character)
(let ((c-int (get-int character))
(f-char ""))
(setf c-int (* *a-value* (- c-int *b-value*)))
(setf f-char (get-string (mod (abs c-int) 29)))))
However, I am getting this error
; in: DEFUN CIPHER-CALC
; (* *A-VALUE* (- C-INT *B-VALUE*))
;
; caught WARNING:
; undefined variable: *A-VALUE*
; (- C-INT *B-VALUE*)
;
; caught WARNING:
; undefined variable: *B-VALUE*
; (GET-INT CHARACTER)
;
; caught STYLE-WARNING:
; undefined function: GET-INT
; (GET-STRING (MOD (ABS C-INT) 29))
;
; caught STYLE-WARNING:
; undefined function: GET-STRING
;
; compilation unit finished
; Undefined functions:
; GET-INT GET-STRING
; Undefined variables:
; *A-VALUE* *B-VALUE*
; caught 2 WARNING conditions
; caught 2 STYLE-WARNING conditions
I find it difficult to believe that you cannot call a function inside of a let block, so I'm assuming I am making an error. Any other tips on my code would be welcome.
Your code:
(defun input-1 ()
(defvar *message* (read-line))
(defvar *a-value* (parse-integer(read-line)))
(defvar *b-value* (parse-integer(read-line))))
DEFVAR is supposed to be used on the top-level and not inside a function. In this case the variables will be defined when the function runs. But when you just compile, evaluate or load such a function, the variable is not defined. Thus the compiler will later warn that in your code these variables are undefined.
When DEFVAR is used at top-level, then Lisp will recognize that there are variable definitions.
(defvar *message*)
(defvar *a-value*)
(defvar *b-value*))
(defun input-1 ()
(setf *message* (read-line))
(setf *a-value* (parse-integer (read-line)))
(setf *b-value* (parse-integer (read-line))))
defvar doesn't do what you think it does. It ensures the variable exist and if it happens to no exist it binds it to the second argument. Thus:
(defvar *test* 5)
(defvar *test* 10) ; already exist, has no effect
*test* ; ==> 5
What you can do is define them like this on the top of your file and use setf in your function:
(defvar *message*)
(defun input-1 ()
(setf *message* (read-line))
...)
After all setting is what you are doing. You are mixing functions and variables with alphabet. Here you could use defparameter. It is like defvar but it always overwrite when you load the file:
(defparameter *alphabet* (list " " "a" "b" ...))

sort any type of list according to a specified function in racket

I am trying to create a function that sorts a given list according to the specified function I have the following code so far:
(: partition1 (All (A) ((A A -> Boolean) (Listof A) -> (Pr (Listof A) (Listof A)))))
(define (partition1 f x)
(match x
('() (Pr '() '()))
((cons hd '()) (Pr (list hd) '()))
((cons hd tl)
(match
(partition1 f tl)
((Pr A B)
(if (f hd (first tl))
(Pr (cons hd A) B)
(Pr A (cons hd B))))))))
(: quicksort1 (All (A) ((A A -> Boolean) (Listof A) -> (Listof A))))
;; sort the items according to the given order and with the quicksort algorithm
(define (quicksort1 f x)
(match x
('() '())
((cons hd tl)
(match (partition1 f tl)
((Pr A B)
(append
(quicksort1 A)
(list hd)
(quicksort1 B)))))))
My goal is to create a goal that does something like this:
> (quicksort string<? (list "a" "g" "h" "q" "w" "z" "x" "m" "n" "p"))
==> (list "a" "g" "h" "m" "n" "p" "q" "w" "x" "z")
BUT, the above function keeps giving me the following error:
match: no matching clause for '("p")
I have tried to do everything I could to eliminate this error, but in vain. I am learning programming on my own at home and would love any and all assistance! Thank you!
The problem is your partitioning function.
It should take a function of just one argument, and you use the function to classify the list elements into those for which it's true and those for which it's false.
Here's a working version in untyped Racket.
It should be easy to modify.
First, partitioning.
Note that a singleton list is not a special case.
(define (partition left? ls)
(match ls
('() (cons '() '()))
((cons hd tl)
(match
(partition left? tl)
((cons l r)
(if (left? hd)
(cons (cons hd l) r)
(cons l (cons hd r))))))))
And if we use the list's head as the pivot element, sorting could look like this:
(define (quicksort compare ls)
(match ls
('() '())
((cons hd tl)
(match (partition (lambda (x) (compare x hd)) tl)
((cons l r)
(append
(quicksort compare l)
(list hd)
(quicksort compare r)))))))
> (quicksort < '(3 4 5 2 1 7 6))
'(1 2 3 4 5 6 7)
> (quicksort string<? '("a" "g" "h" "q" "w" "z" "x" "m" "n" "p"))
'("a" "g" "h" "m" "n" "p" "q" "w" "x" "z")
> (quicksort string>? '("a" "g" "h" "q" "w" "z" "x" "m" "n" "p"))
'("z" "x" "w" "q" "p" "n" "m" "h" "g" "a")

Additional symbol LIST when using ,#

I observed a macro expansion I do not fully understand:
(defmacro test (cons-list)
`(list
,#(mapcar #'(lambda(elem)
elem)
cons-list)))
(defmacro test-2 ()
`(list ,#(list (cons "a" "b"))))
(defmacro test-3 (cons-list)
`(list ,#cons-list))
I'd expect both macros to expand in the same fashion, as I just use mapcar in a fancy way of creating the same list again and then use that list.
But the results observed in SBCL are:
(test (list (cons "a" "b"))) expands to (LIST LIST (CONS "a" "b"))
(test-2) expands to (LIST ("a" . "b"))
(test-3 (list (cons "a" "b"))) again expands to (LIST LIST (CONS "a" "b"))
Why don't these macro expansions behave the same?
Test-2 evaluates the form (list (cons "a" "b")), the other two do not.
Remember: the arguments to a macro are the forms read, unevaluated.
In order to get the same behaviour from test-2, you would have to quote the form: ,#'(list (cons "a" "b")).
EDIT: Here is a step-by-step expansion of test:
`(list
,#(mapcar #'(lambda (elem)
elem)
cons-list))
Removing the backquote syntactic sugar:
(list* 'list (mapcar #'(lambda (elem)
elem)
cons-list)
Argument substitution in your example:
(list* 'list (mapcar #'(lambda (elem)
elem)
'(list (cons "a" "b")))
Evaluate the mapcar form:
(list* 'list '(list (cons "a" "b")))
Evaluate the `list*' form:
'(list list (cons "a" "b"))

Racket - outputting in numerical form the placement of a string within a list (from left to right)

I've been tasked with creating a function that tells the placement in numerical form of a string within a list (from left to right), so that:
(position "a" '("a" "b" "c" "d" "e"))
returns 1
(position "b" '("a" "b" "c" "d" "e"))
returns 2 and
(position "z" '("a" "b" "c" "d" "e"))
returns #f
I've written it as such:
(define (position x L)
(if (pair? L)
(if (equal? x (car L))
1
(+ 1 (position x (cdr L)))
)
#f)
)
Unfortunately,
(position "z" '("a" "b" "c" "d" "e"))
Doesn't work at all since it's trying to add #f to a number. Is there any way out of this pickle?
Your answer is correct, but I'll suggest a different approach: by using a named let for implementing tail recursion we'll obtain a more efficient solution. Also notice how using cond (instead of nesting ifs) simplifies things:
(define (position x L)
(let loop ((L L) (acc 1))
(cond ((null? L) #f)
((equal? x (car L)) acc)
(else (loop (cdr L) (add1 acc))))))
Also, in the SRFI-1 library we can find the function list-index which almost returns what you want, we just have to add one to the result to convert it to a 1-based index:
(require srfi/1)
(define (position x L)
(cond ((list-index (curry equal? x) L) => add1)
(else #f)))
I fixed it by doing:
(define (position x L)
(if (pair? L)
(if (equal? x (car L))
1
(let ((p-cdr-L (position x (cdr L))))
(if p-cdr-L
(+ 1 p-cdr-L)
#f)))
#f))

Resources