Более читаемы функциональный Clojure или обязательный Groovy?

% sudo apt-get install apache2-utils

command-not-found пакет в Ubuntu обеспечивает некоторую гладкую функциональность, где при вводе команды, которая не может быть разрешена к исполняемому файлу (или функция удара или безотносительно) это запросит способные источники и найдет пакет, который содержит двоичный файл, который Вы пытались выполнить. Так, в этом случае я ввел ab в командной строке:


% ab
The program 'ab' is currently not installed.  You can install it by typing:
sudo apt-get install apache2-utils
bash: ab: command not found

15
задан foxdonut 14 November 2009 в 15:31
поделиться

6 ответов

Я не думаю, что существует такая вещь, как внутренняя читабельность. Есть то, к чему вы привыкли, и к чему вы не привыкли. Я смог прочитать обе версии вашего кода ОК. На самом деле мне было бы легче читать вашу версию Groovy, хотя я не знаю Groovy, потому что я тоже потратил десять лет на изучение C и Java и только год на Clojure. Это ничего не говорит о языках, это только говорит обо мне.

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

Если вы провели большую часть своей жизни, читая Java, конечно, то, что похоже на Java, будет легче читать, чем то, что нет. Пока вы не потратите столько времени на изучение языков Lispy, сколько на изучение языков типа C, это, вероятно, останется правдой.

Для понимания языка, помимо прочего, вы должны быть знакомы с:

  • синтаксисом ( [вектор] vs. (список) , дефисы в именах )
  • словарь (что означает сокращения ? Как / где это можно найти?)
  • правила оценки (работает ли обработка функций как объектов? Это ошибка в большинстве языков.)
  • идиомы, например (сначала карта (некоторый набор сокращений с дополнительными накопленными значениями))

Все это требует времени, практики и повторений, чтобы научиться и усвоить. Но если вы потратите следующие 6 месяцев на чтение и написание большого количества Clojure, вы не только сможете понять этот код Clojure через 6 месяцев, но и, вероятно, поймете его лучше, чем сейчас, и, возможно, даже сможете упростить Это. Как насчет этого:

(use 'clojure.contrib.seq-utils)                                        ;;'
(defn positions [coll]
  (mapcat #(repeat (count %) (inc (ffirst %)))
          (partition-by second (indexed coll))))

Глядя на код Clojure, который я написал год назад, я в ужасе от того, насколько он плох, но я могу читать его нормально. (Не сказать, что ваш код Clojure ужасен; у меня не было проблем с его чтением, и я не гуру.)

Возможно, я пойму это лучше, чем сейчас, и, возможно, даже сумею упростить его. Как насчет этого:

(use 'clojure.contrib.seq-utils)                                        ;;'
(defn positions [coll]
  (mapcat #(repeat (count %) (inc (ffirst %)))
          (partition-by second (indexed coll))))

Глядя на код Clojure, который я написал год назад, я в ужасе от того, насколько он плох, но я могу читать его нормально. (Не сказать, что ваш код Clojure ужасен; у меня не было проблем с его чтением, и я не гуру.)

Возможно, я пойму это лучше, чем сейчас, и, возможно, даже сумею упростить его. Как насчет этого:

(use 'clojure.contrib.seq-utils)                                        ;;'
(defn positions [coll]
  (mapcat #(repeat (count %) (inc (ffirst %)))
          (partition-by second (indexed coll))))

Глядя на код Clojure, который я написал год назад, я в ужасе от того, насколько он плох, но я могу читать его нормально. (Не сказать, что ваш код Clojure ужасен; у меня не было проблем с его чтением, и я не гуру.)

22
ответ дан 1 December 2019 в 00:18
поделиться

править: может больше не иметь отношения

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

Я бы также сказал, что версия Groovy, по крайней мере, частично функциональна, поскольку она использует сбор, что действительно map, функция высшего порядка. В нем также есть некоторое состояние.

Вот как я бы написал версию Clojure:

(defn positions2 [coll]
  (let [current (atom 1)
        if-same #(if (= %1 %2) @current (reset! current (inc %3)))]
    (map if-same (cons (first coll) coll) coll (range (count coll)))))

Она очень похожа на версию Groovy в том, что в ней используется изменяемый "

8
ответ дан 1 December 2019 в 00:18
поделиться

Я тоже изучаю Clojure, и мне он очень нравится. Но на этом этапе моей разработки версию Groovy было легче понять. Что мне нравится в Clojure, так это то, что я читаю код и говорю "Ага!" опыт, когда вы, наконец, «поняли», что происходит. Что мне действительно нравится, так это то, что происходит через несколько минут, когда вы понимаете все способы, которыми код может быть применен к другим типам данных без каких-либо изменений в коде. Я сбился со счета, сколько раз я работал с каким-то числовым кодом в Clojure, а затем, немного позже, подумал о том, как этот же код можно использовать со строками, символами, виджетами, ...

Я использую аналогию с изучением цветов. Помните, когда вас познакомили с красным цветом? Вы поняли это довольно быстро - в мире есть вся эта красная фигня. Затем вы услышали термин пурпурный и на какое-то время заблудились. Но опять же, после некоторого большего воздействия, вы поняли концепцию и получили гораздо более конкретный способ описания определенного цвета. Вы должны усвоить концепцию, держать в голове немного больше информации, но в итоге вы получите что-то более мощное и краткое.

3
ответ дан 1 December 2019 в 00:18
поделиться

Я согласен с Тимоти: вы вводите слишком много абстракций. Я переработал ваш код и закончил так:

(defn positions [coll]
  (reductions (fn [[_ prev-score :as prev] [_ score :as curr]] 
                (if (= prev-score score) prev curr))
    (map vector (iterate inc 1) coll)))

Что касается вашего кода,

(defn use-prev [[a b]] (= a b))
(defn pairs [coll] (partition 2 1 coll))
(map use-prev (pairs coll))

можно просто рефакторировать как:

(map = coll (rest coll))
8
ответ дан 1 December 2019 в 00:18
поделиться

Clojure на первый взгляд более запутанный; хотя может быть и более элегантно. ОО - это результат, позволяющий сделать язык более "понятным" на более высоком уровне. Функциональные языки кажутся более "алгоритмическими" (примитивными / элементарными). Это именно то, что я чувствовал в данный момент. Возможно, это изменится, когда у меня будет больше опыта работы с clojure.

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

У меня две проблемы:

  1. Насколько легко с первого взгляда понять, что делает код ?. Это важно для тех, кто сопровождает код.

  2. Насколько легко угадать логику кода? Слишком многословен / многословен ?. Слишком кратко?

«Делайте все как можно проще, но не проще».

Альберт Эйнштейн

4
ответ дан 1 December 2019 в 00:18
поделиться

Groovy также поддерживает различные стили решения этой проблемы:

coll.groupBy{it}.inject([]){ c, n -> c + [c.size() + 1] * n.value.size() }

определенно не переработан, чтобы быть красивым, но не слишком сложным для понимания.

3
ответ дан 1 December 2019 в 00:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: