Преобразование функции Haskell в Clojure - PullRequest
0 голосов
/ 29 мая 2019

Попытка преобразовать функцию Haskell в Clojure.Но сталкиваюсь с трудностями.Не уверен, что происходит.

Вот рекурсивная функция Haskell.

  mapWidth :: [[Char]] -> Int
  mapWidth [] = 0
  mapWidth (x:xs)
  | length xs == 0 = length x
  | length x /= length (xs!!0) = -1
  | otherwise = mapWidth(xs)

Вот что я пробовал до сих пор:

(defn mapWidth [data_list]
    (def data 0)
    ([[x & xs](seq data_list)](if (= (count x) 0) 
    (data 0)
    (data -1))))
    ([[x & xs](seq data_list)](if not(= (count xs) length (xs!!0))
    (data 0)
    (data -1)
    mapWidth(xs)))

Любая помощь приветствуется.Я довольно плохо знаком с обоими языками.

1 Ответ

9 голосов
/ 29 мая 2019

насколько я вижу, эта функция возвращает длину элемента, если все элементы имеют одинаковую длину. В этом случае это может выглядеть так:

(defn map-len [[x & [y :as xs]]]
  (cond (empty? xs) (count x)
        (not= (count x) (count y)) -1
        :else (recur xs)))

, что является почти точным переписыванием варианта haskell (замена прямого рекурсивного вызова на recur)

(map-len [[1 2] [3 4] [5 6]])
;;=> 2

(map-len [[1 2] [3 4 5] [5 6]])
;;=> -1

бот, поскольку clojure касается операций над последовательностями, вы можете сделать это более идиоматическим образом (как по мне, так и есть):

(defn map-len2 [data]
  (cond (empty? data) 0
        (apply = (map count data)) (count (first data))
        :else -1))

(defn map-len3 [[x & xs]]
  (let [c (count x)]
    (if (every? #(= c (count %)) xs)
      c
      -1)))
...