Clojure习语:合理传递函数值对

Clojure习语:合理传递函数值对,clojure,Clojure,有时我想将参数-值对传递给一个高阶函数,其中我应该传递的值由我传递的参数决定。我希望能够在不显式指定伴随值的情况下传递参数。特别是,我对参数本身是函数的情况感兴趣 通用示例: 下面是一个非常通用的示例,其中my foo和my bar是我要传递给higher foo的函数: (higher-foo my-foo :option4 args) ;good (higher-foo my-bar :option13 args) ;good (higher-foo my-foo :option13 arg

有时我想将参数-值对传递给一个高阶函数,其中我应该传递的值由我传递的参数决定。我希望能够在不显式指定伴随值的情况下传递参数。特别是,我对参数本身是函数的情况感兴趣

通用示例:

下面是一个非常通用的示例,其中
my foo
my bar
是我要传递给
higher foo
的函数:

(higher-foo my-foo :option4 args) ;good
(higher-foo my-bar :option13 args) ;good
(higher-foo my-foo :option13 args) ;how stupid are you?! my-foo requires :option4!
问题:是否有一种“标准”方法可以让
更高的foo
推断出
:option4
:option13
,这样我就可以只写
(更高的foo我的foo)
(更高的foo我的bar)

更具体的示例:

记住有,但我只是想提出一个具体的例子来说明我所说的:

(defn seq-has? [f n someseq]
    (every? (partial apply f)
            (partition n 1 someseq)))

(defn monotonicity [a b]
    (<= a b))

(defn generalized-fib [a b c]
    (= c (+ a b)))
(defn seq有?[f n someseq]
(每个?(部分适用于f)
(分区n 1 someseq)))
(defn单调性[ab]

(这个解决方案在我看来像是一个黑客。它被认为是常见的/惯用的吗?在定义您要查找的属性的函数上使用元数据:

(defn higher-foo [foo & args]
    (apply foo (:option (meta foo))
               args))

(def my-foo
    (with-meta
        (fn [a b] (println "I'm doing something cool"))
        {:option :option4}))

;using it:
user=> (higher-foo my-foo arg)

这个解决方案在我看来像是一个黑客。它被认为是常见的/惯用的吗?在定义您要查找的属性的函数上使用元数据:

(defn higher-foo [foo & args]
    (apply foo (:option (meta foo))
               args))

(def my-foo
    (with-meta
        (fn [a b] (println "I'm doing something cool"))
        {:option :option4}))

;using it:
user=> (higher-foo my-foo arg)

只需让谓词函数本身接受可变参数,并让它进行分区/循环。例如,您的单调?已存在于core中,名为
,只需让谓词函数本身接受可变参数,并让它进行分区/循环。例如,您的单调?已存在于cor中e、 并且被称为
,因为您询问函数如何从一个参数确定未传递的参数的标准方法:

(defn f 
  ([arg0] (case a :foo (f a :bar) 
                  :baz (f a :quux)))
  ([arg0 arg1] ...))
根据您的用例,与
case
不同的分派结构可能更适合

对于您的通用示例,这意味着
更高的foo
应确定所需重载中正确的
:选项
,如上文所示

在您的特定示例中,无法通过传递的函数确定
n
。您需要更具体的数据结构:

(defn seq-has? [{:keys [f n]} s]
  (every? (partial apply f)
          (partition n 1 s)))

(def monotonicity
  {:f <=
   :n 2})

(def generalized-fib
  {:f #(= (+ %1 %2) %3)
   :n 3})

(seq-has? monotonicity [1 2 3])
;; => true
(defn seq有?[{:keys[fn]}s]
(每个?(部分适用于f)
(分区n1s)))
(def)单调性
{f:true

由于您要求函数从一个参数确定未传递参数的标准方法:

(defn f 
  ([arg0] (case a :foo (f a :bar) 
                  :baz (f a :quux)))
  ([arg0 arg1] ...))
根据您的用例,与
case
不同的分派结构可能更适合

对于您的通用示例,这意味着
更高的foo
应确定所需重载中正确的
:选项
,如上文所示

在您的特定示例中,无法通过传递的函数确定
n
。您需要更具体的数据结构:

(defn seq-has? [{:keys [f n]} s]
  (every? (partial apply f)
          (partition n 1 s)))

(def monotonicity
  {:f <=
   :n 2})

(def generalized-fib
  {:f #(= (+ %1 %2) %3)
   :n 3})

(seq-has? monotonicity [1 2 3])
;; => true
(defn seq有?[{:keys[fn]}s]
(每个?(部分适用于f)
(分区n1s)))
(def)单调性
{f:true

太棒了。谢谢!有时候我把事情复杂化了,需要另一个透视图。如果我不知道小于的变量arg行为,我可能也没有这个透视图。当然,你可以在你的pred中始终使用你的seq has?作为一个广义函数。所以,事实上,我第一次读这篇文章时有点累。我很瘦k你的答案完美地回答了我前一天提出的问题。我不确定它是否回答了函数/值对的一般问题,其中值可以是任何值,只要“正确”一个完全由函数决定。将答案复制到另一个链接问题上。太棒了。谢谢!有时我会把事情复杂化,需要另一个视角。如果我不知道小于的变量arg行为,我可能也不会有这个视角。当然,你可以始终使用你的seq has?作为你体内的广义函数r preds.所以,事实上,当我第一次读到这篇文章时,我有点累了。我认为你的答案对于我前一天提出的问题来说是完美的。我不确定它是否回答了函数/值对的一般问题,其中值可以是任何东西,只要“正确”一个完全由函数决定。将答案复制到另一个链接问题上。尝试读取和使用HoF使用的函数的参数数量并不惯用,而且非常容易出错。Hackish似乎是一个恰当的描述。我不认为这种模式比可变参数函数更有用。唯一的优势是组合函数HoF使用的是减少集合的遍历次数。理论上,你只能用相同的算术组合函数,但实际上,你无法推断生成的组合函数的参数计数。是的。也许我应该删除第三种方法……它可能比其他方法更让人分心。你可以在协议方法和整个方法中没有变量重载(由OP计划)这是胡说八道。如果两个参数总是联系在一起,唯一合理的简化方法就是将它们设为一个参数并更改所调用的函数。其他一切都是荒谬的。此外,将函数应如何调用的信息写入元数据也毫无意义。你只是在创建一个隐藏的数据结构,却一无所获(例如,无论如何,该函数不能与所有函数一起调用,需要隐藏的数据结构)。这两个参数并不总是绑定在一起。它们仅在使用
higher foo
时出现。假设我有50个函数测试特定关系是否保持在2-20个数字之间(取决于函数)。假设这些是我无法接触的封闭源代码库的一部分。现在假设我想测试这些关系是否在整个有序集合中保持不变。尼尔斯克给出了一个很好的解决方案