Я программирую поискового робота в clojure, и это занимает постоянное время независимо от глубины, которую я придаю функции. Это сама функция. (используется clojure soup, но я думаю, что это не имеет значения)
(defn crawl [source current-depth max-depth]
(if (= current-depth 0) (write-to-hf "{" false))
(let [targets (get-links source)]
(write-to-hf (str ":" source " " (seq targets) "\n") true)
(if (< current-depth max-depth)
(map crawl targets (repeat (inc current-depth)) (repeat max-depth))
(if (= current-depth 0)
(do (write-to-hf "}" true)
targets)
targets))))
(write-to-hf - это функция, которая записывает данные в файл, поэтому я думаю, это тоже не имеет отношения к проблеме.)
Когда я тестировал свою функцию в REPL, я писал:
(crawl "http://bg.wikipedia.org" 0 1)
Чтобы распечатать все ссылки, требуется около часа, но если я помещу результат в var, это займет меньше секунды.
(def a (crawl "http://bg.wikipedia.org" 0 1))
Мне это кажется нормальным, потому что операции ввода-вывода являются наиболее затратными по времени, но я попытался проверить, сколько времени требуется, чтобы поместить результат в var с большим количеством уровней глубины рекурсии, и похоже, что он постоянный. Даже делаю:
((crawl "http://bg.wikipedia.org" 0 100000000000))
Занимает то же время.
Может кто-нибудь объяснить мне, почему это константа? Я не могу представить, как брать ссылки с миллиардов и больше страниц из Википедии (это огромный веб-сайт с сотнями ссылок на каждой странице) можно сделать менее чем за секунду.
1 ответ
Эта строка создает ленивую последовательность просканированных ссылок:
(map crawl targets (repeat (inc current-depth)) (repeat max-depth))
Фактическое сканирование происходит, когда ссылки печатаются (в данном случае REPL), поэтому, когда вы просто сохраняете их в var и не смотрите на них, никакой работы не выполняется. Ничего не делать требует примерно постоянного времени. Оберните эту строку в вызове doall
, чтобы сделать его не ленивым
Похожие вопросы
Новые вопросы
function
Функция (также называемая процедурой, методом, подпрограммой, подпрограммой или макросом) — это часть кода, предназначенная для выполнения одной конкретной задачи. Используйте этот тег для вопросов, которые конкретно связаны с созданием или вызовом функций. Чтобы получить помощь в реализации функции для выполнения задачи, используйте вместо нее [алгоритм] или тег для конкретной задачи. Создавая функцию, логику можно изолировать и вызывать многократно.
dorun
здесь более / менее подходящим?