使用另一种方法中定义的方法

Dav*_*ser 2 clojure

我正在研究这个公案的解决方案,该公司声明:

Write a function which replicates each element of a sequence a variable number of times.
Run Code Online (Sandbox Code Playgroud)

要做到这一点,我想:

  1. 制作一个方法,该方法需要一个序列和重复每个元素的次数.
  2. 在此方法中定义一个局部方法,该方法将值v,n复制到序列中.

考虑到这一点,我写了以下方法:

(fn dupSeqX [aseq x]
  (fn dupx [v x]
    (if (= x 1) (list v) (concat v (dupx v (- x 1))))
  )
  (reverse (reduce #(concat %1 (dupx %2 x)) '() aseq)))
Run Code Online (Sandbox Code Playgroud)

运行此代码时,我收到以下错误:

java.security.PrivilegedActionException: java.lang.Exception: Unable to resolve symbol: dupx in this context (NO_SOURCE_FILE:0)
Run Code Online (Sandbox Code Playgroud)

我如何创建一个允许我完成这个公案的本地方法?

有没有"clojure-esque"这样做的方式,我不知道?

nic*_*kik 8

首先,我们不讨论方法:我们谈论功能.在clojure中你可以调用一个方法,但它与一个函数不同.如果你停止使用OO术语,你也会失去OO的思维方式.

你想做什么是可能的.您basiclly要创建一个名为新功能dupxdupseqx功能.你现在正在做的是创建一个函数,然后抛弃它(你没有对返回值做任何事情,只返回函数中的最后一个表格).由于函数与任何其他值一样,您可以使用与任何其他值相同的机制:创建本地"变量".这个机制是什么?它是本地绑定,它的工作原理如下(fn中的名称只是为了你可以从它自己调用它;它不需要与绑定名称相同let):

(let [dupx (fn dupx [v x] 
             (if (= x 1) 
                  (list v) 
                  (cons v (dupx v (dec x)))))]
  (dupx 5 3))
Run Code Online (Sandbox Code Playgroud)

请注意,我更正了其他一些事情.

一个较短的形式(修复双重名称丑陋):

(letfn [(dupx [v x] (if (= x 1)
                       (list v) 
                       (cons v (dupx v (dec x)))))]
  (dupx 5 3))
Run Code Online (Sandbox Code Playgroud)

在"(让[...]"和匹配的")"之间的所有内容都可以,我们现在有了一个dupx功能.

所以现在你的其余代码工作了:

(fn dupSeqX [aseq x]
  (letfn [(dupx [v x] (if (= x 1) (list v) (cons v (dupx v (dec x)))))]
    (reverse (reduce #(concat %1 (dupx %2 x)) '() aseq))))
Run Code Online (Sandbox Code Playgroud)

这段代码可以更加惯用:

  • 编码指南:名称参数coll而不是aseq
  • 编码指南:DoNotUseCamalCase就像这样做
  • 当你不需要它时的递归对于性能和大数字是不利的.
  • 你正在重新发明轮子.如果您想要了解语言和标准库,那么学习编码会很好但不好.

我是怎么写这个的?

首先是基本的fn.coll 是期望序列的命名函数的标准.

(fn [coll times]  )
Run Code Online (Sandbox Code Playgroud)

如果你读到这个"序列的每个元素"你的大脑必须去MAP.

(fn [coll times] 
   (map (fn ....) coll))
Run Code Online (Sandbox Code Playgroud)

"复制每个......"基本上是对你必须放入地图功能的描述.我们可以使用repeat(你的dubx功能,但有一些额外的好东西,比如它很懒).

(fn [coll times] 
   (map (fn [val] (repeat times val)) coll))
Run Code Online (Sandbox Code Playgroud)

剩下一个问题(来自公案).它想要一个seq,而不是每个元素的序列中的序列.这意味着我们必须将结果连在一起.

 (fn [coll times] 
   (apply concat (map (fn [val] (repeat times val)) coll)))
Run Code Online (Sandbox Code Playgroud)

你经常会看到这种(apply concat (map ....))模式.在标准库中有一个更好的函数,称为mapcat,我会将内部函数转换为短语法.

 (fn [coll times] 
   (mapcat #(repeat times %) coll))
Run Code Online (Sandbox Code Playgroud)

希望有所帮助!