我想知道什么是最好的Scala模仿Groovy的安全解除引用运算符(?.),或者至少是一些接近的替代方案?
我在Daniel Spiewak的博客上讨论过它,但是想把它打开到StackOverFlow ......
为了每个人的时间,这是丹尼尔的最初回应,我的反击,以及他的第二个回应:
@Antony
实际上,我先看了那个.或者更确切地说,我试图从Ruby土地上复制Ragenwald和"操作员".问题是,如果没有代理,这有点困难.考虑以下表达式(使用Ruby的andand,但它与Groovy的运算符相同):
test.andand().doSomething的()
我可以从Any =>某种类型实现andand()方法创建隐式转换,但这就是魔术停止的地方.无论值是否为null,doSomething()方法仍将执行.由于它必须以类型安全的方式在某个目标上执行,这将需要实现字节码代理,这将是片状和奇怪的(注释,最终方法,构造函数等的问题).
更好的选择是回归到两者的灵感来源,以及Groovy的安全解除引用运算符:monadic map操作.以下是一些使用Option实现模式的Scala语法:
val something:Option [String] = ... //可能是Some(...)或None
val length = something.map(_.length)
在此之后,
length要么是Some(str.length)(其中str是Option中包含的String对象),要么是None.这正是安全解除引用操作符的工作原理,除了它使用null而不是类型安全的monad.如上所述,我们可以从某种类型T => Option [T]定义隐式转换,然后以这种方式映射,但是某些类型已经定义了映射,因此它不会非常有用.或者,我可以实现类似于map但具有单独名称的东西,但无论如何实现它,它将依赖于高阶函数而不是简单的链式调用.它似乎只是静态类型语言的本质(如果有人能解决这个问题,请随时纠正我).
Daniel Spiewak,2008年7月7日星期一下午1:42
我的第二个问题:
感谢Daniel对此的回应?我想我错过了!我想我明白你的建议是什么,但是假设你无法控制来源,那么这样的事情是怎样的:
company?.getContactPerson?.getContactDetails?.getAddress?.getCity
Run Code Online (Sandbox Code Playgroud)
假设它是一个java bean,你不能进入并将返回值更改为Something [T] - 我们可以在那里做什么?
Antony Stubbs 2009年7月21日星期二晚上8:07哦天哪 - 重新阅读那就是你提出从T到Option [T]的隐式转换的权利吗?但是你还能像这样把它连在一起吗?你还需要地图吗?嗯....
var city = company.map(_.getContactPerson.map(_.getContactDetails.map(_.getAddress.map(_.getCity))))
Run Code Online (Sandbox Code Playgroud)
?
Antony Stubbs于2009年7月21日星期二晚上8:10发布
他的第二回应:
@Antony
在公司的情况下,我们真的无法做很多事情吗?.getContactPerson等等......即使假设这是有效的Scala语法,我们仍然需要一些方法来阻止链中的后续调用.如果我们不使用函数值,这是不可能的.因此,像地图这样的东西确实是唯一的选择.
对Option的隐式转换不会很糟糕,但是通过隐含事物,我们会绕过对类型系统的一些保护.做这种事情的最好方法是使用与Option一致的for-comprehension.我们可以做map和flatMap,但它的魔法语法更好:
for {
c < - company
person <- c.getContactPerson
details <- person.getContactDetails
address <- details.getAddress
} yield address.getCity …Run Code Online (Sandbox Code Playgroud) 让我们假设将这两个等价表达式传递给Scala宏:
1+"foo"any2stringadd(1)+"foo"有没有办法在宏内区分这两个?