Перевернуть строку (простой вопрос) - PullRequest
18 голосов
/ 19 сентября 2011

Есть ли лучший способ сделать это в Clojure?

daniel=> (reverse "Hello")
(\o \l \l \e \H)

daniel=> (apply str (vec (reverse "Hello")))
"olleH"

Вам нужно делать бит apply $ str $ vec каждый раз, когда вы хотите вернуть строку обратно в ее первоначальную форму?

Ответы [ 3 ]

26 голосов
/ 19 сентября 2011

Вам лучше использовать clojure.string/reverse:

user=> (require '[clojure.string :as s])
nil
user=> (s/reverse "Hello")
"olleH"

ОБНОВЛЕНИЕ: для любопытных следуйте фрагментам исходного кода для clojure.string/reverse в обоих Clojure (v1.4) и ClojureScript

; clojure:
(defn ^String reverse
  "Returns s with its characters reversed."
  {:added "1.2"}
  [^CharSequence s]
  (.toString (.reverse (StringBuilder. s))))

; clojurescript
(defn reverse
  "Returns s with its characters reversed."
  [s]
  (.. s (split "") (reverse) (join "")))
18 голосов
/ 19 сентября 2011

ОК, так что было бы легко свернуть вашу собственную функцию с применением внутри или использовать выделенную версию реверса, которая лучше (но только) работает со строками.Тем не менее, здесь нужно подумать о арности (количестве и типе параметров) функции str и о том, что реверс работает с коллекцией.

(doc reverse)

clojure.core/reverse
([coll])
Returns a seq of the items in coll in reverse order. Not lazy.

Это означает, что реверс работает не толькона строки, но и на всех других коллекциях.Однако, поскольку reverse ожидает коллекцию в качестве параметра, он обрабатывает строку как коллекцию символов

(reverse "Hello")

и возвращает ее также

(\o \l \l \e \H)

Теперь, если мы просто подставим функции дляВ коллекции вы можете определить разницу:

(str '(\o \l \l \e \H) )
"(\\o \\l \\l \\e \\H)"

, а

(str \o \l \l \e \H )
"olleH"

Большая разница между ними заключается в количестве параметров.В первом примере str принимает один параметр, набор из 5 символов.Во втором случае str принимает 5 параметров: 5 символов.

Чего ожидает функция str?

(doc str)
-------------------------
clojure.core/str
([] [x] [x & ys])
  With no args, returns the empty string. With one arg x, returns
  x.toString().  (str nil) returns the empty string. With more than
  one arg, returns the concatenation of the str values of the args.

Таким образом, когда вы передаете один параметр (набор), все возвращаемые strToString коллекции.Но чтобы получить желаемый результат, вам нужно передать 5 символов в виде отдельных параметров в str, а не в саму коллекцию.Apply - это функция, которая используется для «проникновения» в коллекцию и осуществления этого.

(apply str '(\o \l \l \e \H) )
"olleH"

Функции, которые обрабатывают несколько отдельных параметров, часто встречаются в Clojure, поэтому полезно понимать, когда и зачем вам нужноиспользовать применить.Другая сторона, которую нужно понять, - почему автор функции str заставил ее принимать несколько параметров вместо коллекции?Обычно есть довольно веская причина.Какой распространенный вариант использования функции str?Конечно, не конкатенация коллекции отдельных символов, а конкатенация значений, строк и результатов функций.

(let [a 1 b 2]
  (str a "+" b "=" (+ a b)))
"1+2=3"

Что если бы у нас была строка, принимающая одну коллекцию в качестве параметра?

(defn str2
  [seq]
  (apply str seq)
  )

(str2 (reverse "Hello"))
"olleH"

Круто, все работает!Но теперь:

(let [a 1 b 2]
  (str2 '(a "+" b "=" (+ a b)))
  )
"a+b=(+ a b)"

Хммм, теперь, как это решить?:)

В этом случае, заставляя str принимать несколько параметров, которые оцениваются до выполнения функции str, дает str самый простой синтаксис.Всякий раз, когда вам нужно использовать str в коллекции, apply - это простой способ преобразовать коллекцию в отдельные параметры.

Создание str, которое принимает коллекцию и оценивает каждую часть внутри, потребует больше усилий, помогитетолько в менее распространенных случаях использования приводят к более сложному коду или синтаксису или ограничивают его применимость.Таким образом, может быть лучший способ перевернуть строки, но лучше всего справиться с реверсом, применить и str.

10 голосов
/ 19 сентября 2011

Apply, как и в обратном порядке, работает с любым секвенируемым типом, а не только с векторами, поэтому

(применить str (обратное "Привет"))

немного короче. Однако clojure.string / reverse должен быть более эффективным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...