你会如何在Ruby和/或Haskell中编写这个Clojure片段?

dno*_*len 10 ruby haskell language-comparisons clojure

我正在研究一个Rails模板,并试图编写一些代码,允许我填充一个表或多列ul标签"从上到下"和"从左到右"跨越我指定的许多列.我刚刚掌握了Ruby,所以我无法理解这一点.我也对这个有用的片段的惯用Haskell版本感到好奇.对Clojure版本的改进表示赞赏:

(defn table [xs & {:keys [cols direction]
                   :or   {cols 1 direction 'right}}]
  (into []
        (condp = direction
          'down (let [c (count xs)
                      q (int (/ c cols))
                      n (if (> (mod c q) 0) (inc q) q)]
                  (apply map vector (partition n n (repeat nil) xs)))
          'right (map vec (partition cols cols (repeat nil) xs))))) 
Run Code Online (Sandbox Code Playgroud)

有了这段代码,我就可以做到以下几点:

(table (range 10) :cols 3)
Run Code Online (Sandbox Code Playgroud)

打印出来的情况如下:

0    1    2 
3    4    5 
6    7    8
9
Run Code Online (Sandbox Code Playgroud)

更棘手的一个:

(table (range 10) :cols 3 :direction 'down)
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

0    4    8    
1    5    9    
2    6        
3    7        
Run Code Online (Sandbox Code Playgroud)

Ant*_*sky 4

我可能会使用Data.List.SplitHackage 的包在 Haskell 中写这样的东西:

import Data.List       (intercalate, transpose)
import Data.List.Split (splitEvery)

data Direction = Horizontal | Vertical deriving (Eq, Read, Show)

table :: Direction -> Int -> [a] -> [[a]]
table Horizontal cols xs = splitEvery cols xs
table Vertical   cols xs = let (q,r) = length xs `divMod` cols
                               q'    = if r == 0 then q else q+1
                           in transpose $ table Horizontal q' xs

showTable :: Show a => [[a]] -> String
showTable = intercalate "\n" . map (intercalate "\t" . map show)

main :: IO ()
main = mapM_ putStrLn [ showTable $ table Horizontal 3 [0..9]
                      , "---"
                      , showTable $ table Vertical   3 [0..9] ]
Run Code Online (Sandbox Code Playgroud)

其中一些内容,例如Direction类型和transpose技巧,源自 jkramer 的答案。我不会在 Haskell 中使用关键字参数来实现类似的东西(它实际上没有这样的东西,但你可以使用 Edward Kmett 的答案中的记录来模拟它们),但我把这些参数放在第一位,因为它对于部分应用程序更有用( defaultTable = table Horizontal 1)。该splitEvery函数只是将列表分成适当大小的列表;其余的代码应该很简单。该table函数返回一个列表的列表;为了获取字符串,该showTable函数会插入制表符和换行符。(该intercalate函数连接列表的列表,将它们与给定的列表分开。它类似于 Perl/Python/Ruby 的join,仅适用于列表而不仅仅是字符串。)