Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 使用在另一个方法中定义的方法_Clojure - Fatal编程技术网

Clojure 使用在另一个方法中定义的方法

Clojure 使用在另一个方法中定义的方法,clojure,Clojure,我正在研究解决方案,其中指出: Write a function which replicates each element of a sequence a variable number of times. 为此,我想: 制作一个方法,该方法需要一个序列和重复每个元素的次数 在此方法中定义一个本地方法,将一个值v,n次复制到一个序列中 考虑到这一点,我编写了以下方法: (fn dupSeqX [aseq x] (fn dupx [v x] (if (= x 1) (list v)

我正在研究解决方案,其中指出:

Write a function which replicates each element of a sequence a variable number of times.
为此,我想:

  • 制作一个方法,该方法需要一个序列和重复每个元素的次数
  • 在此方法中定义一个本地方法,将一个值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)))
    
    运行此代码时,出现以下错误:

    java.security.PrivilegedActionException: java.lang.Exception: Unable to resolve symbol: dupx in this context (NO_SOURCE_FILE:0)
    
    我如何创建一个本地方法来完成这个koan


    有没有一种我不知道的“clojure式”的方法来实现这一点?

    clojure有很多或真正伟大的功能来帮助你养成“用顺序思考”的习惯。当你发现自己在一个列表中反复写东西时,想想“我可以映射这个吗?”,当你发现自己在列表中做其他事情时,看看这个

    在这种情况下,内部函数恰好是内置的,所以您很幸运:)通常您需要自己编写它并将其存储在
    let
    中,但如果您使其成为一个适当的函数,那么您可能会在代码的其他地方找到它的用途

    这里有一个开始的提示

    (flatten (map #(repeat 3 %) [1 2 3 4]))
    (1 1 1 2 2 2 3 3 3 4 4 4)
    

    ps:
    #(重复3%)
    (fn[n](重复3 n))
    首先,我们不讨论方法:我们讨论函数。clojure中有些东西可以调用方法,但它与函数不同。如果你停止使用面向对象的行话,你也会失去面向对象的思维方式

    你想做的是可能的。您基本上希望在
    dupseqx
    函数中创建一个名为
    dupx
    的新函数。您现在正在做的是创建一个函数,然后将其丢弃(您不会对返回值执行任何操作,只返回函数中的最后一个表单)。由于函数与任何其他值一样,因此可以使用与任何其他值相同的方法:创建局部“变量”。这是什么机制?它是本地绑定,工作原理如下(fn中的名称只是为了让您可以从自身调用它;它不需要与
    let
    绑定的名称相同):

    注意,我纠正了其他一些事情

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

    在“(let[…]”和匹配项之间的所有内容中,现在我们有了一个
    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))))
    
    这段代码可以变得更地道一些:

    • 编码准则:命名参数
      coll
      而不是
      aseq
    • 编码准则:不要使用CAMALCASE这样做
    • 当您不需要递归时,它对性能和大数字都是有害的
    • 你正在重新发明轮子。这对于学习编码是很好的,但是如果你想了解语言和标准库,就不太好了
    我是怎么写的

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

    (fn [coll times]  )
    
    如果你读到这个“序列中的每一个元素”,你的大脑就必须去绘制地图

    (fn [coll times] 
       (map (fn ....) coll))
    
    “复制每个…”基本上是对必须放入映射函数中的内容的描述。我们可以使用
    repeat
    (您的dubx函数,但如果有一些像这样的额外功能,它是懒惰的)

    还有一个问题(来自koan)。它希望返回一个seq,而不是每个元素的序列中的一个序列。这就意味着我们必须一起观察结果

     (fn [coll times] 
       (apply concat (map (fn [val] (repeat times val)) coll)))
    
    您经常会看到
    (apply concat(map…)
    模式。标准库中有一个更好的函数,名为
    mapcat
    ,我将把内部函数转换成简短的语法

     (fn [coll times] 
       (mapcat #(repeat times %) coll))
    

    希望有帮助

    这里有一些提示。我想你指的是函数而不是方法。此外,函数是用defn定义的,而匿名函数(lamdba)是用fn定义的。你把两者混淆了。此外,如果您需要外部函数范围内的局部函数,请使用let或letfn。这是一个非常好的描述,谢谢!感谢您的见解。
    (展平(地图…)
    ->
    (地图猫…)
    (如果某些项目容易展平怎么办?)。祝贺你在10k上成功。:-)是的,(阿瑟地图)。:)展平地图是一个坏习惯
    (fn [coll times] 
       (map (fn [val] (repeat times val)) coll))
    
     (fn [coll times] 
       (apply concat (map (fn [val] (repeat times val)) coll)))
    
     (fn [coll times] 
       (mapcat #(repeat times %) coll))