1

Hi I am trying to implement this Common Lisp Macro in Ruby 2.0.0-p247:

(defmacro binary-cmp (a b &key (test-func '>))
  `(funcall #',test-func ,a ,b))

A binary test function that takes 2 arguments and 1 keyword argument test_func, and the test_func defaults to gt proc.

gt    = -> (a, b) { a > b }
lt    = -> (a, b) { a < b }
equal = -> (a, b) { a == b }

def binary_cmp (a, b, test_func: gt)
  test_func.(a, b)
end

But this won't work, because in binary_cmp cannot see the outside: gt .

How should I do to accomplish this? Is it possible? Or there is a common practice to do it? Thank you very much.

EDIT:

The reason why I need keyword argument is that my parameter list has 5 parameters and maybe the user only need the default test function (say lt), or maybe someone wanna use (gt) as default.

4

4 回答 4

5

这个 Lisp 代码在以下几个方面是不好的风格:

(defmacro binary-cmp (a b &key (test-func '>))
  `(funcall #',test-func ,a ,b))
  • 它不应该是一个宏。它应该是一个函数。

  • 宏可以写得更简单。

FUNCALL表单不是必需的,因为它不添加任何功能。由于设计test-func需要是函数名(FUNCTION#'期望函数名),我们可以删除FUNCALLand #'。在 Lisp 语法中,列表的第一个元素是函数名。

(defmacro binary-cmp (a b &key (test-func '>))
  `(,test-func ,a ,b))

作为一个函数,它只是:

(defun binary-predicate (a b &key (predicate '>))
  (funcall predicate a b))
于 2013-07-08T22:27:42.853 回答
3

你真的不需要宏来做到这一点。Ruby 有一个非常动态的运行时,所以只需使用 OO 设计所涉及的消息传递语义并使用#send.

def binary_cmp (a, b, test_func = :>)
  a.send(test_func, b)
end

binary_cmp(42, 7, :<) # => false
于 2013-07-08T13:11:15.247 回答
2

这与函数或关键字参数或宏完全无关。gt是一个局部变量。局部变量在它们定义的范围内是局部的,在这种情况下是脚本主体。如果你想要一个全局变量,你需要使用一个全局变量:

$gt    = -> (a, b) { a > b }
$lt    = -> (a, b) { a < b }
$equal = -> (a, b) { a == b }

def binary_cmp (a, b, test_func: $gt)
  test_func.(a, b)
end

或者,您可以使用嵌套范围。Ruby 中唯一创建嵌套作用域的是块,因此您需要使用块:

gt    = -> (a, b) { a > b }
lt    = -> (a, b) { a < b }
equal = -> (a, b) { a == b }

define_method(:binary_cmp) do |a, b, test_func: gt|
  test_func.(a, b)
end
于 2013-07-08T14:17:21.307 回答
1

你可以尝试这样的事情:

def binary_cmp(a, b, test_func: ->(a, b){ a > b })
  test_func.(a,b)
end
于 2013-07-08T13:15:12.623 回答