简体   繁体   English

将Java概念转换为Clojure

[英]Converting the Java concept into Clojure

I am pretty new with Clojure. 我对Clojure很新。 I have one Java method including a boolean variable and I want to rewrite this method to use it with the same functional in Clojure as well. 我有一个Java方法,包括一个布尔变量,我想重写这个方法,以便在Clojure中使用相同的功能。 But I couldn't find how to set the boolean value true and false in run-time in Clojure. 但我无法在Clojure中找到如何在运行时设置布尔值true和false。

The following snippet basically emphasize only the boolean part, It is difficult to think for me to write this in a functional way. 下面的代码片段基本上只强调布尔部分。我很难想到以函数的方式编写它。

int calculate(...){
  int y = 0;
  boolean flag = false;
  foreach(...){
     if(!flag){
        y = 1;
        flag = true;
     }
     else{
        y = -1;
        flag = false;
     }
  }
  return y;
} 

Here is the my first attempt in Clojure: 这是我在Clojure的第一次尝试:

(defn calculate [...]
    ( ??flag?? -> I do not know which macro I should use over here
      (doseq [x ...]
        (if (false? flag) (do 1 (set the flag true)) 
           (do -1 (set the flag false)))))

How can I implement the same concept in Clojure? 如何在Clojure中实现相同的概念?

For the Java code you have, it looks like the simplest way to translate it into Clojure would be to skip all the iterating and just return the final value: 对于您拥有的Java代码,将其转换为Clojure的最简单方法是跳过所有迭代并返回最终值:

(defn calculate [coll]
  (odd? (count coll)))

If you want something more elaborate I guess you could do something like 如果你想要更精细的东西,我想你可以做点什么

(defn calc [coll flag]
  (if (empty? coll)
    flag
    (recur (rest coll) (not flag))))

and call it with 并称之为

(defn calculate [coll]
  (calc coll false))     

This kind of recursion isn't the most idiomatic style, and it's kind of crazy for this problem, but it demonstrates how instead of mutating variables you write an expression that when evaluated produces the value passed into the next iteration (see the recur call in the example above). 这种递归并不是最惯用的风格,对于这个问题它有点疯狂,但它演示了如何改变变量而不是变量,而是编写一个表达式,当求值时产生传递给下一次迭代的值(参见recur call in上面的例子)。

It would be better style to rewrite this like 重写这样的风格会更好

(defn calculate
  ([coll flag]
    (if (empty? coll)
      flag
      (recur (rest coll) (not flag))))
  ([coll]
    (calculate coll false)))

so there's only one function name to deal with. 所以只有一个功能名称要处理。 (I left the other way in thinking it would likely be clearer to read for somebody new to Clojure.) (我离开了另一个方向,认为对于Clojure的新人来说可能会更清楚。)

I second the comment suggesting you look at 4clojure . 我的第二条评论建议你看看4clojure It's a good way to get practice, and once you have a solution you can learn from what other users did. 这是一种很好的练习方式,一旦你有了解决方案,你就可以从其他用户那里学到东西。

Use loop / recur to emulate iterative statements in Clojure: 使用loop / recur在Clojure中模拟迭代语句:

(defn calculate [...]
  (loop [...
         y    0
         flag false]
    ...
    (if (false? flag)
      (recur ...  1 true)   ;; "loop with x = ..., y = 1 and flag = true"
      (recur ... -1 false)) ;; "loop with x = ..., y = -1 and flag = false"
    ... )

EDIT: let me elaborate. 编辑:让我详细说明。 What I understand from your question is that you have trouble translating mutability-based (Java) code into Clojure. 我从您的问题中理解的是,您无法将基于可变性(Java)的代码转换为Clojure。 This is natural. 这很自然。 Clojure is big on immutability. Clojure在不变性方面很重要。

One way to implement mutability in a Clojure program is to use reference types, in particular atoms . 在Clojure程序中实现可变性的一种方法是使用引用类型,特别是原子 Your piece of code could be written this way in Clojure: 您的代码可以在Clojure中以这种方式编写:

(defn calculate [...]
  (let [y    (atom 0)
        flag (atom false)]
    (doseq [x ...]
      (if (false? @flag)
        (do (reset! y 1)
            (reset! flag true))
        (do (reset! y -1)
            (reset! flag false))))
    (... return some function of y and flag ...)))

It works. 有用。 But heavy use of atoms and side-effects is not idiomatic in Clojure; 但是,在Clojure中,大量使用原子和副作用并不是惯用的; useful at times, yes, but not necessary and cumbersome compared to functional, idiomatic Clojure. 虽然有用,但是,与功能性,惯用的Clojure相比,并不是必需和繁琐的。

A better way to model mutability in the context of iteration is to translate it in terms of recursion, like what I did with loop / recur above. 在迭代的上下文中建模可变性的更好方法是在递归方面对其进行转换,就像我在上面使用loop / recur所做的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM