код без указания точки более эффективен или более краткий? - PullRequest
25 голосов
/ 27 июня 2011

Я написал следующий код, который берет кучу точек и рисует их на экране, используя библиотеку глянца.

let s = blocks pes
    pts = map (map mkPt) s  {- stitches to points-}
    lines = map Line pts    {-points to lines -}
    pict = Pictures lines   {- lines to a picture -}
  in do  displayInWindow "My Window" (200, 200) (10, 10) white pict

Работает нормально, но мне приходит в голову, что есть повторяющийся паттерн: цепочка вызовов функций, результат каждого из которых передается в последнем аргументе следующего.Поэтому я рефакторинг, удалив промежуточные переменные, изменив порядок и связав функции с композицией функций ("."), Примерно так:

let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes
                in do  displayInWindow "My Window" (200, 200) (10, 10) white pict

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

Ответы [ 2 ]

31 голосов
/ 27 июня 2011

Несколько быстрых предложений:

let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict

У вас есть некоторые лишние вещи, которые можно удалить сразу:

let pict = Pictures . map Line . (map $ map mkPt) . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict

Вы все равно не избегаете скобок с map (map mkPt) term, так что избавьтесь от $:

let pict = Pictures . map Line . map (map mkPt) . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict

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

let pict = Pictures 
         . map Line 
         . map (map mkPt) 
         . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict

Блок do излишен, потому чтооно имеет только одно утверждение, и вы можете переместить окончательное приложение за пределы определения:

let displayPict = displayInWindow "My Window" (200, 200) (10, 10) white
                . Pictures 
                . map Line 
                . map (map mkPt) 
                . blocks
in displayPict pes

Вы можете объединить два map s:

let displayPict = displayInWindow "My Window" (200, 200) (10, 10) white
                . Pictures 
                . map (Line . map mkPt) 
                . blocks
in displayPict pes

Иногда это также более читабельнодля длинных цепочек использовать оператор обратной композиции из Control.Arrow:

let displayPict = blocks
                  >>> map (Line . map mkPt) 
                  >>> Pictures
                  >>> displayInWindow "My Window" (200, 200) (10, 10) white
in displayPict pes

Но все это необязательно;Приправьте ваш код по вкусу.

Что касается эффективности, я не вижу причин полагать, что эти два будут отличаться, как только оптимизатор GHC завершит работу с кодом.

4 голосов
/ 29 июня 2011

Стиль без точек может быть хорошим, чтобы очень четко показать, что функция - это просто последовательность преобразований на входе.Это действительно легко прочитать что-то вроде:

foo = map show . doThis . doThat . etc

, потому что это выглядит как типичный бессмысленный код, так что кто-то, знакомый с ним, сможет увидеть именно то, что важно, без шума.Сравните это с:

foo x = d
    where
        a = etc x
        c = doThis b
        b = doThat a
        d = map show c

Очевидно, что это немного надумано, но идея в том, что необходимо прочитать дополнительные определения и внимательно изучить их, чтобы понять, что на самом деле делает foo.a используется в качестве аргумента для нескольких вспомогательных функций?Как насчет b?Проходили ли данные через эти вспомогательные функции неожиданным образом?Стиль без точек в данном случае гласит: «Вещи просто преобразуются в конвейер, вам не нужно думать о странностях»

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

...