hy语言有没有办法对自己使用doto?
Is there a way in the hy language to use doto on self?
希望有人能帮我解决这个问题。我正在将一些 python 代码移植到 hy,并试图找出如何使用 doto 宏删除一些重复代码。例如,看一个 python class 这样的:
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) 的方法。
这是一个有趣的想法。你可以这样做:
(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")
如果你只想保留__init__
的本地变量,最简单的方法是直接.update
实例变量与本地变量。
(defclass Foo [object]
(defn __init__ [self x y z]
(.update (vars self) (vars))))
(顺便说一句,上面使用的是 Github 上 Hy 版本的新 defclass
语法,它不适用于当前的 PyPI 版本。[更新:现在在当前的 PyPI 版本中])
这确实包括 所有 当地人,所以你得到一个 self.self
,这可能是无害的,但你可以 del
如果你想. Hy 有时会生成局部变量以使语句像表达式一样工作。如果您不小心,这些也可能最终出现在实例字典中。您可以通过 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))
您还可以使用 dict-comp
避免 .update
中的重复,尽管这通常不会更短。
(.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))
希望有人能帮我解决这个问题。我正在将一些 python 代码移植到 hy,并试图找出如何使用 doto 宏删除一些重复代码。例如,看一个 python class 这样的:
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) 的方法。
这是一个有趣的想法。你可以这样做:
(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")
如果你只想保留__init__
的本地变量,最简单的方法是直接.update
实例变量与本地变量。
(defclass Foo [object]
(defn __init__ [self x y z]
(.update (vars self) (vars))))
(顺便说一句,上面使用的是 Github 上 Hy 版本的新 defclass
语法,它不适用于当前的 PyPI 版本。[更新:现在在当前的 PyPI 版本中])
这确实包括 所有 当地人,所以你得到一个 self.self
,这可能是无害的,但你可以 del
如果你想. Hy 有时会生成局部变量以使语句像表达式一样工作。如果您不小心,这些也可能最终出现在实例字典中。您可以通过 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))
您还可以使用 dict-comp
避免 .update
中的重复,尽管这通常不会更短。
(.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))