在hy语言中有没有办法在自己上使用doto?

时间:2015-03-09 18:43:05

标签: hy

希望有人可以帮我解决这个问题。我正在将一些python代码移植到hy,并试图找出如何使用doto宏删除一些重复的代码。例如,看一下像这样的python类:

class Foo(object):
  def __init__(self, x, y, z):
      self.x = x
      self.y = y
      self.z = z

我如何在hy中使用doto转换它?

(defclass Foo [object]
  [[__init__ (fn [self x y z]
               (doto self  ;
                 (setv ...) ; What goes here? 
  ))]])

问题是看起来你通常做这样的事情:

(defclass Foo [object]
  [[__init__ (fn [self x y z]
               (setv self.x x)
               (setv self.y y)
               (setv self.z z))]])

我没有看到在自己上使用(doto)的方法。

2 个答案:

答案 0 :(得分:1)

这是一个有趣的想法。你可以这样做:

(doto self
  (setattr "x" x)
  (setattr "y" y)
  (setattr "z" z))

但它并没有好多少。考虑定义一个宏:

(defmacro vars-to-attrs [obj &rest attrs]
  (let [[actions (list (map
                        (fn (a) `(setattr (str '~a) ~a))
                        attrs))]]
    `(doto ~obj ~@actions)))

然后这样称呼它:

(vars-to-attrs self x y z)

尽管如此,这可能会更好:

(defun vars-to-attrs-fun [obj &rest attrs]
  (for [a attrs]
    (setattr obj a (get (locals) a))))

然后称之为:

(vars-to-attrs-fun self 'x 'y 'z)

或等同于:

(vars-to-attrs-fun self "x" "y" "z")

答案 1 :(得分:0)

如果您只想保留__init__的本地人,最简单的方法是直接.update具有本地变量的实例变量。

(defclass Foo [object]
   (defn __init__ [self x y z]
     (.update (vars self) (vars))))

(顺便说一句,上面的内容是使用我们在Github上的Hy版本的新defclass语法,它不适用于当前的PyPI版本。[更新:它现在在当前的PyPI版本中] )

这包括所有本地人,所以你得到self.self,这可能是无害的,但如果你愿意,可以del。 Hy有时会生成本地语言,使语句像表达式一样。如果你不小心,这些也可能最终出现在dict的情况下。您可以assoc只使用您想要的名称来避免这种情况:

(assoc (vars self)
  'x x
  'y y
  'z z))

新的setv语法也需要任意数量的对,所以你可以这样做:

;; new setv syntax
(setv self.x x
      self.y y
      self.z z)

在使用元组之前你几乎可以做到这一点:

;; works in both Hy versions
(setv (, self.x self.y self.z)
      (, x y z))

您还可以使用.update避免dict-comp中的重复,但通常不会更短。

(.update (vars self) (dict-comp k (get (vars) k) [k '[x y z]]))

如果您仍然使用doto,请使用正确的语法:

(doto self
    (-> (. x) (setv x))
    (-> (. y) (setv y))
    (-> (. z) (setv z)))

这确实避免重复self,但它并不比上述替代方案短,因此doto是这项特定工作的错误工具。

更新

我为此https://github.com/hylang/hy/issues/1532

提出了问题

我们可能会向Hy添加attach宏。如果你想早点试试,我还发布了implementation

用法:

(defclass Foo []
  (defn __init__[self x y z]
    (attach self x y z)))

由于附件目标是第一个参数,attach也适用于->doto,例如。

(doto self
  (.configure foo bar)
  (attach spam eggs))