utils.lisp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. (in-package #:chatikbot)
  2. (defvar *backoff-start* 1 "Initial back-off")
  3. (defvar *backoff-max* 64 "Maximum back-off delay")
  4. (defun loop-with-error-backoff (func)
  5. (let ((backoff *backoff-start*))
  6. (loop
  7. do
  8. (handler-case
  9. (progn
  10. (funcall func)
  11. (setf backoff *backoff-start*))
  12. (error (e)
  13. (log:error e)
  14. (log:info "Backing off for" backoff)
  15. (sleep backoff)
  16. (setf backoff (min *backoff-max*
  17. (* 2 backoff))))
  18. (bordeaux-threads:timeout (e)
  19. (log:error e)
  20. (log:info "Backing off for" backoff)
  21. (sleep backoff)
  22. (setf backoff (min *backoff-max*
  23. (* 2 backoff))))))))
  24. (defun replace-all (string part replacement &key (test #'char=))
  25. "Returns a new string in which all the occurences of the part
  26. is replaced with replacement."
  27. (with-output-to-string (out)
  28. (loop with part-length = (length part)
  29. for old-pos = 0 then (+ pos part-length)
  30. for pos = (search part string
  31. :start2 old-pos
  32. :test test)
  33. do (write-string string out
  34. :start old-pos
  35. :end (or pos (length string)))
  36. when pos do (write-string replacement out)
  37. while pos)))
  38. (defmacro aget (key alist)
  39. `(cdr (assoc ,key ,alist :test #'equal)))
  40. (defun mappend (fn &rest lists)
  41. "Apply fn to each element of lists and append the results."
  42. (apply #'append (apply #'mapcar fn lists)))
  43. (defun random-elt (choices)
  44. "Choose an element from a list at random."
  45. (elt choices (random (length choices))))
  46. (defun flatten (the-list)
  47. "Append together elements (or lists) in the list."
  48. (mappend #'(lambda (x) (if (listp x) (flatten x) (list x))) the-list))