English 中文(简体)
Help translating this Java codeblock to Clojure?
原标题:
  • 时间:2009-11-16 20:14:01
  •  标签:
  • java
  • clojure

I m getting my feet wet with Clojure, and trying to get used to functional programming.

I ve been translating various imperative functions from other languages into their Clojure equivalents -- and so far everything has been going well. However, I ve now run into a sticking point and I have no idea how to translate this Java method into idiomatic Clojure.

At first "map" seemed like the right tool, but after playing with it a bit I m not so sure. Can someone show me how to write this function in Clojure?

Thanks!

public String calculateChecksum(String str)
{
    String hash = "bjytk3lfj%3jklDskj";
    int key = 1690912;

    for(int i=0; i < str.length(); i++) {

        key = key ^ (int)(hash.charAt(i%hash.length()))^(int)(str.charAt(i));
        key = key>>>23|key<<9;

    }return "8"+toHex8(key>>>(8&255))+toHex8(key&255);

}
最佳回答

We re just past Hallow een, and it s... the night of the living n00bs!

I have just a few days of Clojure programming under my belt. This effort is closer to "real" Clojure, and at least it compiles. It also produces a result, but probably not the correct one. More after this:

(ns erikcw)

(defn toHex8 [n] (format "%08x" n))        ; Just a guess!

                                           ; can t use str, that s predefined.
(defn calculateChecksum [url]               ; I renamed the arg to url so I can use strn later.
  (loop [strn url                          ; this will loop over chars in strn.
         hash (cycle "bjytk3lfj%3jklDskj") ; now hash repeats for as long as you need it.
         key 1690912]                      ; modifying key along the way.
    (prn strn key)                           ; debug print.
    (let [k2 (bit-xor (bit-xor key (int (first hash))) (int (first strn)))
          k3 (bit-or (bit-shift-right k2 23) (bit-shift-left k2 9))]
      (if (empty? (rest strn))
        (str "8" (toHex8 (bit-shift-right k3 8)) (toHex8 (bit-and k3 255)))
        (recur (rest strn) (rest hash) k3)))))

(prn (calculateChecksum "HowNowBrownCow"))

I don t know what the toHex8 function does, so I wrote a function that prints its argument as an 8 digit hex number. Just to get the dang thing to compile.

Rather than use an index to pull characters out of hash and strn, I treat both as sequences of characters and deal with only their head elements in each iteration. hash is infinitely long, thanks to (cycle).

The bit operations have names starting with "bit-".

Because integers can become arbitrarily large in Clojure, the resulting number becomes bigger with every character thanks to the << 9. That s probably not intended.

Anyway, some spoilsport just posted what will probably be a correct answer. Still, this was fun, I hope I managed to share a little of the effort with you.

Edit: Because Dave Ray is insisting on using (reduce), I ve done another solution:

(defn next-key [key str-hash]
  (let [str1 (first str-hash)
        hash1 (second str-hash)
        k2 (bit-xor (bit-xor key hash1) str1)]
        (bit-or (bit-shift-right k2 23) (bit-shift-left k2 9))))

(defn calculateChecksum2 [url]
  (let [kk
    (reduce next-key 1690912
      (partition 2                ; (72 98) (111 106) (119 121) ...
        (map int                  ; 72 98 111 106 119 121
          (interleave url (cycle "bjytk3lfj%3jklDskj"))))) ; "HbojwyNt..."
  ]
  (str "8" (toHex8 (bit-shift-right kk 8)) (toHex8 (bit-and kk 255)))))

(prn (calculateChecksum2 "HowNowBrownCow"))

This one is a little easier to read and needs no loop. next-key could have been dragged inside the main function but I find things easier to understand like this.

We have a list of hash values and one of string values. To make reduce work I had to crunch them up into a single list; see comments.

We still have the problem that the original algorithm wasn t intended to work with integers of unlimited size, plus a possible parenthesization problem in its last line. You may want to build your own truncating bit-twiddling functions.

问题回答

Clojure does not expose the >>> operator, so a direct translation is not possible.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签