Scala 中编译时对象创建的语法糖
假设我
trait fooTrait[T] {
def fooFn(x: T, y: T) : T
}
希望用户能够使用自己定义的 fooFn 主体快速声明 fooTrait 的新实例。理想情况下,我想要一些类似的
val myFoo : fooTrait[T] = newFoo((x:T, y:T) => x+y)
工作。但是,我不能这样做,
def newFoo[T](f: (x:T, y:T) => T) = new fooTrait[T] { def fooFn(x:T, y:T):T = f(x,y); }
因为这使用了闭包,因此当程序多次运行时会产生不同的对象。我真正需要的是能够获取 newFoo 返回的对象的 classOf ,然后使其可以在不同的机器上构造。我该怎么办?
如果您对用例感兴趣,我正在尝试为 Hadoop 编写一个 Scala 包装器,它允许您执行
IO("Data") --> ((x: Int, y: Int) => (x, x+y)) --> IO("Out")
中间的东西需要转换为实现特定接口的类,然后可以在不同的接口上实例化机器(执行相同的 jar 文件)仅通过类名。
请注意,Scala 使用转换 (x:Int) => 的语法糖做了正确的事情。 x+5 为 Function1 的实例。我的问题是我是否可以在不破坏 Scala 内部结构的情况下复制它。如果这是 lisp(正如我习惯的那样),这将是一个微不足道的编译时宏...:sniff:
Lets say I have
trait fooTrait[T] {
def fooFn(x: T, y: T) : T
}
I want to enable users to quickly declare new instances of fooTrait with their own defined bodies for fooFn. Ideally, I'd want something like
val myFoo : fooTrait[T] = newFoo((x:T, y:T) => x+y)
to work. However, I can't just do
def newFoo[T](f: (x:T, y:T) => T) = new fooTrait[T] { def fooFn(x:T, y:T):T = f(x,y); }
because this uses closures, and so results in different objects when the program is run multiple times. What I really need is to be able to get the classOf of the object returned by newFoo and then have that be constructable on a different machine. What do I do?
If you're interested in the use case, I'm trying to write a Scala wrapper for Hadoop that allows you to execute
IO("Data") --> ((x: Int, y: Int) => (x, x+y)) --> IO("Out")
The thing in the middle needs to be turned into a class that implements a particular interface and can then be instantiated on different machines (executing the same jar file) from just the class name.
Note that Scala does the right thing with the syntactic sugar that converts (x:Int) => x+5 to an instance of Function1. My question is whether I can replicate this without hacking the Scala internals. If this was lisp (as I'm used to), this would be a trivial compile-time macro ... :sniff:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一个与您在问题中列出的语法相匹配并序列化/执行匿名函数的版本。请注意,这会序列化 Function2 对象的状态,以便可以在另一台计算机上恢复序列化版本。仅类名是不够的,如下所示的解决方案。
您应该创建自己的编码/解码函数,即使只是包含您自己的 Base64 实现(不依赖 Sun 的 Hotspot)。
为了让自己相信类名不足以在另一台机器上使用该函数,请考虑下面的代码,它创建了 100 个不同的函数。计算文件系统上的类并进行比较。
Here's a version that matches the syntax of what you list in the question and serializes/executes the anon-function. Note that this serializes the state of the Function2 object so that the serialized version can be restored on another machine. Just the classname is insufficient, as illustrated below the solution.
You should make your own encode/decode function, if even to just include your own Base64 implementation (not to rely on Sun's Hotspot).
To convince yourself that the classname is insufficient to use the function on another machine, consider the code below which creates 100 different functions. Count the classes on the filesystem and compare.
快速建议:为什么不尝试创建一个隐式 def 将 FunctionN 对象转换为 --> 所期望的特征?方法。
我确实希望您不必为此使用任何宏!
Quick suggestion: why don't you try to create an implicit def transforming FunctionN object to the trait expected by the --> method.
I do hope you won't have to use any macro for this!