Me gustaría saber cuál es la mejor imitación de Scala de safe-dereference operator (?.) de Groovy, o al menos algunas alternativas cercanas?¿Mejor imitación de Scala del operador de desreferencia segura de Groovy (?.)?
he discussed it breiflyDaniel Spiewak en el blog 's, pero me gustaría abrirlo a StackOverflow ...
Por el bien de tiempo para todos, aquí está la respuesta de Daniel inicial, mi contador, y su segunda respuesta :
@Antony
Actually, I looked at doing that one first. Or rather, I was trying to replicate Ragenwald’s andand “operator” from Ruby land. The problem is, this is a bit difficult to do without proxies. Consider the following expression (using Ruby’s andand, but it’s the same with Groovy’s operator):
test.andand().doSomething()
I could create an implicit conversion from Any => some type implementing the andand() method, but that’s where the magic stops. Regardless of whether the value is null or not, the doSomething() method will still execute. Since it has to execute on some target in a type-safe manner, that would require the implementation of a bytecode proxy, which would be flaky and weird (problems with annotations, final methods, constructors, etc).
A better alternative is to go back to the source of inspiration for both andand as well as Groovy’s safe dereference operator: the monadic map operation. The following is some Scala syntax which uses Option to implement the pattern:
val something: Option[String] = … // presumably could be either Some(…) or None
val length = something.map(_.length)
After this,
length
either be Some(str.length) (where str is the String object contained within the Option), or None. This is exactly how the safe-dereferencing operator works, except it uses null rather than a type-safe monad.As pointed out above, we could define an implicit conversion from some type T => Option[T] and then map in that fashion, but some types already have map defined, so it wouldn’t be very useful. Alternatively, I could implement something similar to map but with a separate name, but any way it is implemented, it will rely upon a higher-order function rather than a simple chained call. It seems to be just the nature of statically typed languages (if anyone has a way around this, feel free to correct me).
Daniel Spiewak Monday, July 7, 2008 at 1:42 pm
Mi segunda pregunta: ¿
Thanks for the response Daniel regarding ?. I think I missed it! I think I understand what you’re proposing, but what about something like this, assuming you don’t have control over the sources:
company?.getContactPerson?.getContactDetails?.getAddress?.getCity
Say it’s a java bean and you can’t go in and change the return values to Something[T] - what can we do there?
Antony Stubbs Tuesday, July 21, 2009 at 8:07 pm oh gosh - ok on re-read that’s where you’re proposing the implicit conversion from T to Option[T] right? But would you still be able to chain it together like that? You’d still need the map right? hmm….
var city = company.map(_.getContactPerson.map(_.getContactDetails.map(_.getAddress.map(_.getCity))))
?
Antony Stubbs Tuesday, July 21, 2009 at 8:10 pm
Su segunda respuesta:
@Antony
We can’t really do much of anything in the case of company?.getContactPerson, etc… Even assuming this were valid Scala syntax, we would still need some way to prevent the later calls in the chain. This is not possible if we’re not using function values. Thus, something like map is really the only option.
An implicit conversion to Option wouldn’t be bad, but by making things implicit, we’re circumventing some of the protection of the type system. The best way to do this sort of thing is to use for-comprehensions in concert with Option. We can do map and flatMap, but it’s much nicer with magical syntax:
for {
c < - company
person <- c.getContactPerson
details <- person.getContactDetails
address <- details.getAddress
} yield address.getCity
Daniel Spiewak Tuesday, July 21, 2009 at 9:28 pm
P. S. si Daniel publica sus respuestas originales en su blog como respuestas, editaré la pregunta para eliminarlas por el bien del Sistema.
Ver también http://stackoverflow.com/questions/1364361/how-to-write-a-proper-null-safe-coalescing-operator-in-scala –