Пример из Programming Clojure
От: igna Россия  
Дата: 19.08.10 10:24
Оценка:
Здесь (2.6 Where’s My for Loop?) есть такой пример:

(defn indexed [coll] (map vector (iterate inc 0) coll))

(defn index-filter [pred coll]
  (when pred
    (for [[idx elt] (indexed coll) :when (pred elt)] idx)))

(defn index-of-any [pred coll]
  (first (index-filter pred coll)))


, определяюший функцию index-of-any являющуюся аналогом следующей функции на Java:

public static int indexOfAny(String str, char[] searchChars) {
    if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
        return -1;
    }
    for (int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);
        for (int j = 0; j < searchChars.length; j++) {
            if (searchChars[j] == ch) {
                return i;
            }
        }
    }
    return -1;
}


В отличии от функции на Java ее аналог на Clojure в начале работы строит отображение индекс->значение. Это на самом деле нужно? Разве нельзя написать вот так?:

(defn index-of-any-helper [pred coll idx]
  (when (and pred coll)
    (if (pred (first coll))
      idx
      (recur (butfirst coll) (add idx 1)))))

(defn index-of-any [pred coll]
  (index-of-any-helper pred coll 0))
Re: Пример из Programming Clojure
От: edbond Украина http://edbond.name
Дата: 19.08.10 19:00
Оценка:
Здравствуйте, igna, Вы писали:

I>Здесь (2.6 Where’s My for Loop?) есть такой пример:


I>
I>(defn indexed [coll] (map vector (iterate inc 0) coll))

I>(defn index-filter [pred coll]
I>  (when pred
I>    (for [[idx elt] (indexed coll) :when (pred elt)] idx)))

I>(defn index-of-any [pred coll]
I>  (first (index-filter pred coll)))
I>


I>, определяюший функцию index-of-any являющуюся аналогом следующей функции на Java:


I>
I>public static int indexOfAny(String str, char[] searchChars) {
I>    if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
I>        return -1;
I>    }
I>    for (int i = 0; i < str.length(); i++) {
I>        char ch = str.charAt(i);
I>        for (int j = 0; j < searchChars.length; j++) {
I>            if (searchChars[j] == ch) {
I>                return i;
I>            }
I>        }
I>    }
I>    return -1;
I>}
I>


I>В отличии от функции на Java ее аналог на Clojure в начале работы строит отображение индекс->значение. Это на самом деле нужно? Разве нельзя написать вот так?:


I>
I>(defn index-of-any-helper [pred coll idx]
I>  (when (and pred coll)
I>    (if (pred (first coll))
I>      idx
I>      (recur (butfirst coll) (add idx 1)))))

I>(defn index-of-any [pred coll]
I>  (index-of-any-helper pred coll 0))
I>


еще много вариантов есть:
;; clojure 1.2
 (letfn [(pred [elt] (= elt \d))]
   (first (remove nil?
                  (map-indexed #(when (pred %2) %1) "abcdef")))))

я думаю лучше писать короткие функции, которые можно использовать в других местах.
Re[2]: Пример из Programming Clojure
От: igna Россия  
Дата: 20.08.10 04:54
Оценка:
Здравствуйте, edbond, Вы писали:

E>я думаю лучше писать короткие функции, которые можно использовать в других местах.


А строить отображение индекс->значение на самом деле нужно?
Re[3]: Пример из Programming Clojure
От: edbond Украина http://edbond.name
Дата: 20.08.10 09:47
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, edbond, Вы писали:

E>>я думаю лучше писать короткие функции, которые можно использовать в других местах.
I>А строить отображение индекс->значение на самом деле нужно?

Нужно помнить, что map, filter и многие другие функции ленивые, поэтому отображение будет построено только до
получения результата. Зато алгоритм выглядит понятней и читается легко.
Re[4]: Пример из Programming Clojure
От: igna Россия  
Дата: 20.08.10 11:14
Оценка:
Здравствуйте, edbond, Вы писали:

E>Нужно помнить, что map, filter и многие другие функции ленивые, поэтому отображение будет построено только до получения результата.


Что в зависимости от задачи может дать экономию от почти ста процентов до почти нуля. Рассмотрим вариант "почти нуля". Потребует ли такая реализация больше времени выполнения по сравнению с той, которую привел я?
Re[5]: Пример из Programming Clojure
От: edbond Украина http://edbond.name
Дата: 07.09.10 14:30
Оценка: 4 (1)
Здравствуйте, igna, Вы писали:

I>Здравствуйте, edbond, Вы писали:

E>>Нужно помнить, что map, filter и многие другие функции ленивые, поэтому отображение будет построено только до получения результата.
I>Что в зависимости от задачи может дать экономию от почти ста процентов до почти нуля. Рассмотрим вариант "почти нуля". Потребует ли такая реализация больше времени выполнения по сравнению с той, которую привел я?

Используйте time http://clojuredocs.org/v/1527 чтобы сравнить время выполнения:
(ns indexed-test
  (:require [clojure.contrib.string :as s]))

(def test-string (s/repeat 50000 "abcdef"))

;; --------------------

(defn index-of-any-helper [pred coll idx]
  (when (and pred coll)
    (if (pred (first coll))
      idx
      (recur pred (rest coll) (inc idx)))))

(defn index-of-any [pred coll]
  (index-of-any-helper pred coll 0))

;; --------------------

(defn index-of-any2 [pred coll]
  (first (remove nil?
                 (map-indexed #(when (pred %2) %1) coll))))

;; --------------------

(defn indexed [coll] (map vector (iterate inc 0) coll))

(defn index-filter [pred coll]
  (when pred
    (for [[idx elt] (indexed coll) :when (pred elt)] idx)))

(defn index-of-any3 [pred coll]
  (first (index-filter pred coll)))


indexed-test> (time (dotimes [i 100] (index-of-any #(= % \z) test-string)))
; Evaluation aborted.
; не дождался, как и (index-of-any #(= % \z) test-string)

indexed-test> (time (dotimes [i 100] (index-of-any2 #(= % \z) test-string)))
"Elapsed time: 16539.669432 msecs"
nil
indexed-test> (time (dotimes [i 100] (index-of-any3 #(= % \z) test-string)))
"Elapsed time: 19222.019552 msecs"
nil
Re[6]: Пример из Programming Clojure
От: edbond Украина http://edbond.name
Дата: 09.09.10 19:01
Оценка:
Здравствуйте, edbond, Вы писали:

E>Здравствуйте, igna, Вы писали:


I>>Здравствуйте, edbond, Вы писали:

E>>>Нужно помнить, что map, filter и многие другие функции ленивые, поэтому отображение будет построено только до получения результата.
I>>Что в зависимости от задачи может дать экономию от почти ста процентов до почти нуля. Рассмотрим вариант "почти нуля". Потребует ли такая реализация больше времени выполнения по сравнению с той, которую привел я?

E>Используйте time http://clojuredocs.org/v/1527 чтобы сравнить время выполнения:

E>
E>(ns indexed-test
E>  (:require [clojure.contrib.string :as s]))

E>(def test-string (s/repeat 50000 "abcdef"))

E>;; --------------------

E>(defn index-of-any-helper [pred coll idx]
E>  (when (and pred coll)
E>    (if (pred (first coll))
E>      idx
E>      (recur pred (rest coll) (inc idx)))))

E>(defn index-of-any [pred coll]
E>  (index-of-any-helper pred coll 0))

E>;; --------------------

E>(defn index-of-any2 [pred coll]
E>  (first (remove nil?
E>                 (map-indexed #(when (pred %2) %1) coll))))

E>;; --------------------

E>(defn indexed [coll] (map vector (iterate inc 0) coll))

E>(defn index-filter [pred coll]
E>  (when pred
E>    (for [[idx elt] (indexed coll) :when (pred elt)] idx)))

E>(defn index-of-any3 [pred coll]
E>  (first (index-filter pred coll)))
E>


E>
E>indexed-test> (time (dotimes [i 100] (index-of-any #(= % \z) test-string)))
E>; Evaluation aborted.
E>; не дождался, как и (index-of-any #(= % \z) test-string)

E>indexed-test> (time (dotimes [i 100] (index-of-any2 #(= % \z) test-string)))
E>"Elapsed time: 16539.669432 msecs"
E>nil
E>indexed-test> (time (dotimes [i 100] (index-of-any3 #(= % \z) test-string)))
E>"Elapsed time: 19222.019552 msecs"
E>nil
E>


И самый короткий вариант:
(defn index-of-any [pred coll]
  (first (clojure.contrib.seq/positions pred coll)))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.