Это нужно будет сделать независимо для каждой поисковой системы, иначе это может произойти со временем. Для Google используйте инструмент Google Search Console. Это позволит вам загрузить новый файл robots.txt и отправить его на повторное сканирование.
scala> val (x, y) = (Some(4), Some(9))
x: Some[Int] = Some(4)
y: Some[Int] = Some(9)
scala> def f(x: Int, y: Int) = Math.max(x, y)
f: (x: Int,y: Int)Int
scala> for { x0 <- x; y0 <- y } yield f(x0, y0)
res26: Option[Int] = Some(9)
scala> val x = None
x: None.type = None
scala> for { x0 <- x; y0 <- y } yield f(x0, y0)
res27: Option[Int] = None
Ответ @RahulG использует тот факт, что Option
является монадой (хотя в библиотеке Scala нет типа, который бы представлял это). Компилятор расширяет понимание for
до следующего:
def a: Option[Int]
def b: Option[Int]
val calc: Option[Int] = a flatMap {aa => b map {bb => aa + bb}}
Вы также можете рассматривать его как аппликативный функтор, с некоторой помощью Scalaz:
import scalaz._
import Scalaz._
def a: Option[Int]
def b: Option[Int]
val calc: Option[Int] = (a ⊛ b) {_ + _}
Ключевое отличие заключается в что в монадическом вычислении сбой (то есть None
) вычисления a
приводит к короткому замыканию оценки. В аппликативном стиле оцениваются как a
, так и b
, и если оба значения равны Some
, вызывается чистая функция. Вы также можете видеть, что в монадическом вычислении значение aa
могло использоваться в вычислении b
; в аппликативной версии b
не может зависеть от результата a
.
У меня есть немного более старая версия скаляза , чем ретронима , но следующее работает для меня в качестве примера и обобщается для случая, когда у вас есть 3 типа T, U, V
, а не только один:
def main(args: Array[String]) {
import scalaz._
import Scalaz._
val opt1 = some(4.0) //Option[Double]
val opt2 = some(3) //Option[Int]
val f: (Double, Int) => String = (d, i) => "[%d and %.2f]".format(i, d)
val res = (opt1 <|*|> opt2).map(f.tupled)
println(res) //Some([3 and 4.00])
}
Затем я могу добавить:
val opt3 = none[Int]
val res2 = (opt1 <|*|> opt3).map(f.tupled)
println(res2) //None
def optApply[A,B,C](f: (A, B) => C, a: Option[A], b: Option[B]): Option[C] =
a.zip(b).headOption.map { tup => f.tupled(tup) }
a.zip(b)
действительно приводит к Итерируемому [(A, B)] (с, потому что это из Опций, самое большее один элемент). headOption
затем возвращает первый элемент в качестве опции.
Начиная с Scala 2.13
, Option#zip
можно применить к другому Option
, чтобы вернуть Option
(в более ранних версиях он возвращал бы Iterable
); таким образом:
def optApply[T](f: (T,T) => T, a: Option[T], b: Option[T]): Option[T] =
a.zip(b).map(f.tupled)
, где поведение zip
имеет вид:
Some(2).zip(Some(3)) // Some((2, 3))
Some(2).zip(None) // None
None.zip(Some(3)) // None
None.zip(None) // None
и которое может применяться как таковое:
optApply[Int]((a, b) => a max b, Some(2), Some(5)) // Some(5)
optApply[Int]((a, b) => a max b, Some(2), None) // None
Вы можете использовать для понимания:
def opt_apply[T](f: (T,T) => T, x: Option[T], y: Option[T]): Option[T] =
for (xp <- x; yp <- y) yield (f(xp,yp))
Что является сахаром для:
x flatMap {xp => y map {yp => f(xp, yp)}}
Это также возможно из-за того, что Option является монадой
{{ 1}}