Есть ли более элегантный способ сделать следующее?Scala: Сокращение для соответствия шаблону по типу?
data match {
case e: SomeType => doSomethingWith(e)
case _ =>
}
Ищете что-то вроде:
data.ifInstanceOf[SomeType](doSomethingWith)
Есть ли более элегантный способ сделать следующее?Scala: Сокращение для соответствия шаблону по типу?
data match {
case e: SomeType => doSomethingWith(e)
case _ =>
}
Ищете что-то вроде:
data.ifInstanceOf[SomeType](doSomethingWith)
По какой-то причине это не придумали:
import PartialFunction._
condOpt("abc": Any) { case s: String => s.length } // = Some(3)
condOpt((): Any) { case s: String => s.length } // = None
Я обычно переименовать его или его брата cond
к when
.
Спасибо - это хорошо работает для меня –
Редактор, который сказал, что формат REPL лучше, был прав. Вы можете вырезать/вставить стенограмму непосредственно в REPL. Однако вы не можете сохранить сеанс (который даст вам только LOC). https://issues.scala-lang.org/browse/SI-9214 –
Вы можете использовать asInstanceOf
, чтобы получить цель:
Option(data)
.filter(_.isInstanceOf[SomeType])
.map(_.asInstanceOf[SomeType])
.map(doSomethingWith)
, но я предполагаю, что это слишком многословным.
Целью является применение функции, если тип соответствует 'T', а не для перевода в' T', а затем применить. – Marth
@Marth Ваше решение является scala идиоматическим способом. Не пытайтесь найти лучше –
Я не был тем, кто задал этот вопрос, и я согласен с тем, что оригинальное предложение - лучший способ сделать то, что он хочет. Я просто указываю, что ваше решение семантически отличается от вашего: ваш будет применять 'doSomethingWith' независимо от того, является ли' data' 'SomeType', тогда как его не будет. – Marth
Вы хотите выражение или просто выполнить побочный эффект? Если это просто побочный эффект с помощью «PimpMyLibrary» подход + трапезу:
import scala.reflect.ClassTag
implicit class AnyOps(data : Any) {
def ifInstanceOf[A : ClassTag](f: A => Unit) : Unit = {
val clzz = implicitly[ClassTag[A]].runtimeClass
if (clzz.isInstance(data)) f(data.asInstanceOf[A])
}
}
Вы можете попробовать
"abc".ifInstanceOf[String](println)
"def".ifInstanceOf[Integer](println)
1.ifInstanceOf[Integer](println)
2.ifInstanceOf[String](println)
Если вы хотите выражение, которое я считаю, что лучший способ пойти, чтобы добавить дополнительный тип Параметр B и возврат Либо [B, Anyref].
Шаблон-шаблон будет использовать ваш ClassTag: 'неявный класс AnyOps (data: Any) {def as [A: ClassTag] (f: A => Any) = соответствие данных {case a: A => f (a) case _ = >}} ' –
Я думаю, что collect
может работать для этого. Метод принимает частичную функцию, и отфильтровывает элементы, которые не соответствуют никаким case
заявления:
Option(data) collect {
case element: SomeType => mappingFunction(element)
}
Конечно, mappingFunction
здесь может иметь побочные эффекты и вернуть Unit
, тем самым имитируя foreach
.
Если вы хотите создать новый метод с именем, вы могли бы сделать новый метод на Any
:
implicit class AnyOps(data: Any) {
def forMatch[A](pf: PartialFunction[Any, A]) = pf.lift(data)
}
Как будет собирать работу? 'data' может быть любым классом, который не должен иметь метод сбора, определенный на нем. – mohit
@mohit sorry Я забыл обернуть 'data' в' Option', чтобы у вас был метод 'collect'. Исправлено. –
Я думаю, вы найдете его трудно найти что-либо более короткий или более точным, чем «старый добрый» ...
if (data.isInstanceOf[SomeType]) doSomething(data)
... если ваш случай не является более сложным, чем вы показываете
В приведенном выше примере не было бы doSomething (data) doSomething (data.asInstanceOf [SomeType])? –
Вы абсолютно правы; что уменьшит полезность, когда вам понадобится этот тип в качестве входных данных; что вполне вероятно. – thoredge
Ух, это должно быть сложнее, не проще. –
Вполне возможно, что существует лучший способ использования полиморфизма. С другой стороны, в этом случае SomeType является mixin –