【问题标题】:Clojure - Creating a No Divisors functionClojure - 创建一个无除数函数
【发布时间】:2018-11-09 18:46:18
【问题描述】:

我真的很难做到这一点。函数如下

编写一个名为 no-divisors 的函数?它需要一个输入 n。如果没有介于 2 和 √???? 之间的数字,该函数应该返回 true除n,否则为假。该函数应该同时使用您的 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? 函数都可以完美运行。

【问题讨论】:

  • 您的语法已关闭。 divide( ...) 在 Clojure 中是 (divide ...);命名中还有dividde vs divides?
  • @cfrick 啊,是的!我的错误,只是我没有使用 Clojure 语法。并对我的伪代码中的不一致表示歉意。

标签: clojure


【解决方案1】:

首先,您不能像在其他语言中那样在代码中的任何位置放置括号。它们在评估代码时表示 Clojure(和其他 lisp)中的特定内容,即列表中的第一件事是动词;要调用的函数。嵌套括号意味着对函数结果的重复调用。因此,如果您有一个函数 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 意味着我看到了一件事并期待另一件事。所以真的,这个错误想说的是你写了一个开放的paren(,然后用一个名为数字而不是函数的东西。这看起来很像您写的是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?))

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

希望这会有所帮助。

附:我不确定您对get-divisors 的实现是否完全正确。

【讨论】:

  • 没有除数吗?函数工作,我只是试图用我在 relp.it 上得到的东西运行它并得到一个编译错误
  • @modzking4 我想是的。它确实取决于divide? 函数。我只是将它复制并粘贴到一个 repl 中,然后调用 (no-divisors? 13) 返回 true 和 (no-divisors? 10) 返回 false。你得到了什么错误?
【解决方案2】:

您必须在进行过程中测试您的工作。让我们看看你的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。所以函数的形状可能是...

【讨论】:

    猜你喜欢
    • 2011-02-27
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 2013-12-13
    • 1970-01-01
    • 2015-02-24
    • 2017-10-09
    • 2010-11-21
    相关资源
    最近更新 更多