The less-familiar parts of Lisp for beginners — search

Next in our walk through less commonly covered Lisp features is search.  This isn’t especially mysterious, but it’s good to point it out, so newcomers know it’s there and don’t start writing their own versions of it.  This function locates a subsequence within a sequence.  Most obviously, the programmer can use it to find a substring in a longer string, but note that, with the :key and :test arguments, more general actions are possible.  There are also options to begin the search from someplace other than the beginning of the sequence, or to find the last occurrence, rather than the first occurrence, of the substring.  Here is an example of things that :key and :test can help with:
search.lisp

(defun demo-case-insensitive-search (haystack needle)
  (search needle haystack :key #'char-downcase :test #'char=))

(defun demo-find-n-letter-word (haystack n)
  (let ((pattern (format nil " ~A " 
                         (make-sequence 'string n 
                                        :initial-element #\A))))
    (search pattern haystack :key #'alpha-char-p)))

(defun demo-find-upper-case-of-word (haystack needle)
  (labels
      ((compare-fcn (char-1 char-2)
         (and (upper-case-p char-2)
              (char= (char-upcase char-1) char-2))))
    (search needle haystack :test #'compare-fcn)))

(defun demonstrate ()
  (let ((stringlist (list "alpha"
                          "beta"
                          "gamma"
                          "delta"
                          "epsilon"
                          "ALPHA"
                          "BETA"
                          "GAMMA"
                          "DELTA"
                          "EPSILON"))
        haystack)
    ;; build haystack, separated with blanks, and with leading
    ;; and trailing blanks
    (setf haystack " ")
    (dolist (word stringlist)
      (setf haystack (concatenate 'string haystack word " ")))
    
    (let ((needle "AlPhA"))
      (format t "case-insensitive search~%")
      (format t "searching for ~S in haystack~%" needle)
      (format t "position= ~A~%" 
              (demo-case-insensitive-search haystack 
                                            needle))
      (format t "~%")
      (format t "upper-case search~%")
      (format t "searching for ~S in haystack~%" needle)
      (format t "position= ~A~%" 
              (demo-find-upper-case-of-word haystack 
                                            needle)))

    (format t "~%")
    (format t "Looking for a 7-letter word~%")
    (format t "position= ~A~%" (demo-find-n-letter-word haystack 7))))
      
        

with output:
*slime-repl sbcl*
CL-USER> (demonstrate)
case-insensitive search
searching for "AlPhA" in haystack
position= 1

upper-case search
searching for "AlPhA" in haystack
position= 32

Looking for a 7-letter word
position= 23
NIL

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

反垃圾邮件 / Anti-spam question * Time limit is exhausted. Please reload CAPTCHA.