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

jtr*_*rim 3 recursion reduce coding-style idioms clojure

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

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

这个函数的两个版本都采用数字表示的字节向量,并将字节转换为数字.例如

(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...
Run Code Online (Sandbox Code Playgroud)

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)))))
Run Code Online (Sandbox Code Playgroud)

v2:减少

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)))
Run Code Online (Sandbox Code Playgroud)

shifted-byte完整性功能的来源:

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

mik*_*era 7

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

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

(defn bytes-to-num [bytes]
  (reduce (fn [acc x] (+ x (* 256 acc))) bytes))
Run Code Online (Sandbox Code Playgroud)

普通的留言:

  • 与loop/recur相比,Reduce 通常是一个更好,更惯用的选项
  • 如果你能提供帮助,你真的不想要拉一个位置索引

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

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

(BigInteger. (byte-array (map to-signed-byte [ 0 0 0 255])))
=> 255
Run Code Online (Sandbox Code Playgroud)