Поиск функции замены в строке в elisp

Я ищу эквивалент replace-regexp-in-string, который просто использует литеральные строки, никаких регулярных выражений.

(replace-regexp-in-string "." "bar" "foo.buzz") => "barbarbarbarbarbarbarbar"

Но я хочу

(replace-in-string "." "bar" "foo.buzz") => "foobarbuzz"

Я пробовал различные функции replace-*, но не могу понять.

Edit

В ответ на сложные ответы я решил сравнить их (да, я знаю, что все тесты ошибочны, но это все еще интересно).

Выходной сигнал benchmark-run равен (time, # garbage collections, GC time):

(benchmark-run 10000
  (replace-regexp-in-string "." "bar" "foo.buzz"))

  => (0.5530160000000001 7 0.4121459999999999)

(benchmark-run 10000
  (haxe-replace-string "." "bar" "foo.buzz"))

  => (5.301392 68 3.851943000000009)

(benchmark-run 10000
  (replace-string-in-string "." "bar" "foo.buzz"))

  => (1.429293 5 0.29774799999999857)

replace-regexp-in-string с цитируемыми regexp-победами. Временные буферы делают замечательно хорошо.

Изменить 2

Теперь с компиляцией! Придется делать 10-кратную итерацию:

(benchmark-run 100000
  (haxe-replace-string "." "bar" "foo.buzz"))

  => (0.8736970000000001 14 0.47306700000000035)

(benchmark-run 100000
  (replace-in-string "." "bar" "foo.buzz"))

  => (1.25983 29 0.9721819999999983)

(benchmark-run 100000
  (replace-string-in-string "." "bar" "foo.buzz"))

  => (11.877136 86 3.1208540000000013)

haxe-replace-string выглядит хорошо

Ответ 1

Попробуйте следующее:

(defun replace-in-string (what with in)
  (replace-regexp-in-string (regexp-quote what) with in nil 'literal))

Ответ 2

s.el библиотека обработки строк имеет s-replace:

(s-replace "." "bar" "foo.buzz") ;; => "foobarbuzz"

Я рекомендую установить s.el из диспетчера пакетов Emacs, если вы работаете со строками в своем Elisp.

Ответ 3

Я бы не надеялся, что это будет быстрее:

(defun haxe-replace-string (string string-a string-b)
  "Because there no function in eLisp to do this."
  (loop for i from 0 upto
        (- (length string) (length string-a))
        for c = (aref string i)
        with alen = (length string-a)
        with result = nil
        with last = 0
        do (loop for j from i below (+ i alen)
                 do (unless
                        (char-equal
                         (aref string-a (- j i))
                         (aref string j))
                      (return))
                 finally
                 (setq result
                       (cons (substring string last (- j alen)) result)
                       i (1- j) last j))
        finally
        (return
         (if result 
             (mapconcat
              #'identity
              (reverse (cons (substring string last) result)) string-b)
           string))))

Becasue replace-regexp-in-string - это нативная функция, но вы никогда не знаете... В любом случае, я написал это некоторое время назад по какой-то причине, поэтому, если вы заполните как сравнение производительности - вы можете попробовать:)

Другая идея, использующая временный буфер:

(defun replace-string-in-string (what with in)
  (with-temp-buffer
    (insert in)
    (beginning-of-buffer)
    (while (search-forward what nil t)
      (replace-match with nil t))
    (buffer-string)))