Clojure - 1个功能的2个版本。哪个更惯用?

时间:2012-02-02 04:10:18

标签: coding-style recursion clojure idioms reduce

这里包含的两个功能中,哪两个更惯用?既不代表可以被认为是好的Clojure的东西?是否有一种更优雅的方式来实现这一目标?寻找对风格/方向的一些建设性批评。

(在github上:https://github.com/jtrim/clojure-sandbox/blob/master/bit-sandbox/src/bit_sandbox/core.clj#L25

此函数的两个版本都采用数字表示的字节和矢量 将字节转换为数字。 e.g。

(bytes-to-num [0 0 0 0])   ;=> number `0`
(bytes-to-num [0 0 0 255]) ;=> number `255`
(bytes-to-num [0 0 1 0])   ;=> number `256`
; etc...

v1:loop / recur

在每个递归级别,有问题的字节 左移一个对应于字节数的数字 给定递归级别,然后添加到运行总和中 返回或传递到另一个级别。

(defn bytes-to-num-v1 [vec-bytes]
  (loop [sum 0, the-bytes vec-bytes]
    (if (empty? the-bytes)
      sum
      (recur
        (+ sum (shifted-byte (first the-bytes) (count (rest the-bytes))))
        (rest the-bytes)))))

v2:reduce

v2使用[sum position]的累加器减少字节向量,其中:

  • sum:移位字节的运行总和
  • position:从零开始的索引(注意:从右边,而不是左边) 向量中的当前字节。用于确定左移位数 有问题的字节。

(defn bytes-to-num-v2 [vec-bytes]
  (first (reduce
    (fn [acc, the-byte]
      [(+ (first acc) (shifted-byte the-byte (last acc))) (dec (last acc))])
    [0 (dec (count vec-bytes))]
    vec-bytes)))

完整性shifted-byte函数的来源:

(defn shifted-byte [num-byte-value, shift-by]
  (bit-shift-left
    (bit-and num-byte-value 0xFF)
    (* shift-by 8)))

1 个答案:

答案 0 :(得分:7)

您尝试将字节转换为无符号大整数,对吧?

在这种情况下,您可能需要以下内容:

(defn bytes-to-num [bytes]
  (reduce (fn [acc x] (+ x (* 256 acc))) bytes))

一般评论:

  • 通常 一个比loop / recur更好,更惯用的选项
  • 如果你能提供帮助,你真的不想拉一个位置指数

或者,您可以使用Java互操作直接使用接受字节数组的BigInteger构造函数。这里唯一的棘手是Java需要签名字节,所以你需要先做一点转换:

(defn to-signed-byte [x] (.byteValue x))

(BigInteger. (byte-array (map to-signed-byte [ 0 0 0 255])))
=> 255