Clojure-创建无除数函数

时间:2018-11-09 18:46:18

标签: clojure

我真的很难做到这一功能。功能如下

  

写一个名为无因数的函数吗?这需要输入n。如果2和√之间的数字均不除n,则函数应返回true,否则返回false。该函数应同时使用get-divisors函数和除法?功能。       提示:您可能需要包装分隔线?匿名函数中的函数,以便您可以传递n的值。

这是我的get-divisors函数:

(defn get-divisors [n]
  (str (range 2 (inc (Math/floor (Math/sqrt n))))))

这是我的divides?函数:

(defn divide [a b]
  (zero? (mod a b)))

我尝试创建一种方法来尝试完成此任务,但是,很遗憾。

这是我尝试过的:

(defn no-divisors [n] 
  divide(n (get-divisors n)))

我收到了输出:

ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn  user/x (form-init5516475059937019181.clj:16)`

我有一个想法,我想与我分享如何创建此任务,但是,因为这是我第一次使用Clojure,所以我不太确定要实现此功能还是可能。非常抱歉,我使用了混合语法,只是到现在为止我还从未使用过Clojure,但这是我的草稿/蓝图:

(defn no-divisors [n]
  resultsArray = []
    def results((get-divisors n))
    for results in get-divisors
      resultsArray.append(results)

      for i=results[0]; i< results.count; i++ 
        divide(n i)
)

我可能走在正确的道路上,或者可能(最有可能)完全错误。对于我可能获得的任何/所有帮助,我深表感谢。只是一点说明,我的get-divisorsdivides?函数都可以正常工作。

2 个答案:

答案 0 :(得分:2)

首先,您不能像在其他语言中那样仅将括号放在代码中的任何位置。它们表示评估代码时Clojure(和其他形式)中特定的内容,即列表中的第一件事是动词。一个要调用的函数。嵌套方括号表示重复调用函数的结果。因此,如果您有一个函数alice返回了这样的函数(请与我保持联系,我正试图解释您得到的错误;)):

(defn alice []
  (fn [] :bob))

然后您可以这样称呼

(alice) ;; => #function[user/alice/fn--6930]

,它将返回您在其中创建的函数,您可以像这样调用该匿名函数:

((alice)) ;; => :bob

实际获得该函数的结果。道歉,如果这有点离谱,但是括号有意思,那就是导致您得到错误的原因:

ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn

这意味着您正在尝试将数字作为函数调用。 clojure.lang.IFn是Clojure所说的“我期待的事情是可以作为函数调用的东西”的方式。通过java.lang.Long,Clojure的均值是“数字”。 ClassCastException意味着我看到了一件事情,并期待着另一件事。因此,实际上,该错误试图说明的是您写了一个开放的括号(,然后跟着一个叫数字而不是函数的名字。这似乎非常像您编写了divide(n (get-divisors n))而不是(divide n (get-divisors n)),因为在求值divide(n (get-divisors n))时,它首先尝试求值divide并发现这是一个函数,但并没有这样做。尝试调用它。然后,它查看下一个格式(n (get-divisors n)),并尝试询问n是什么,并发现它是一个数字,不能将其称为函数。有道理吗?

在您的伪代码中,您有一个数组,您可以在该数组中附加数据以收集结果,同时遍历循环以构建结果。这是解决问题的非常必要的方法,而不是Clojure试图鼓励您解决问题的方法。 Clojure倾向于学习着眼于以数据为中心的解决问题的方法。思考问题的一种方法是用英语表达问题的方式。给定一个数字n,取所有小于其平方根的数字,然后检查是否将它们划分为n。如果该列表为空,则返回true,否则返回false。在Clojure中,您可以编写:

(defn divide? [a b]
  (zero? (mod a b)))

(defn no-divisors? [n]
  (->> (range 2 n)
       (take-while #(< (* % %) n))
       (filter (partial divide? n))
       empty?))

在这里,我们使用->>宏获取2到n之间的数字的惰性序列,然后使用take-while将该序列限制为仅数字平方的序列小于n。然后,我们使用divide?函数检查每个对象是否均分为n,最后询问列表是否为empty?。由于Clojure的序列是惰性的,因此在尝试使用empty?评估结果之前,不会发生任何实际计算,该结果在到达序列中的元素时将停止。这使它比实际遍历整个列表来获得更大的n效率。

希望这会有所帮助。

P.S。我不确定您对get-divisors的实现是否正确。

答案 1 :(得分:0)

您必须在进行过程中测试您的工作。让我们看一下您的get-divisors函数:

(defn get-divisors [n]
  (str (range 2 (inc (Math/floor (Math/sqrt n))))))

让我们尝试一下:

=> (get-divisors 20)
"(2 3 4)"

这是一个字符串,而不是应该的数字集合。删除有害的str呼叫:

(defn get-divisors [n]
  (range 2 (inc (Math/floor (Math/sqrt n)))))

现在

=> (get-divisors 20)
(2 3 4)

好。和一个边缘情况,只是为了确保:

=> (get-divisors 16)
(2 3 4)

再次好!我们可以放心使用此功能。

现在,我们要找出该集合的 none 中是否存在某些错误。有一个方便的函数叫做not-any?。例如,

=> (not-any? even? (range 1 100 2))
true

我们要确定的是n的潜在除数是否没有实际除以n。因此,函数的形状可能是...