Статьи

Scala экстракторы инфиксные выборки с рациональными числами

Я продолжаю возвращаться к удивительному вводному материалу по Scala, составленному Дэниелом Вестхайде . Одним из примеров, которые он предоставляет для экстракторов, использующих шаблон операции инфикса, является Streams API —

1
2
3
4
5
val xs = 58 #:: 43 #:: 93 #:: Stream.empty
xs match {
  case first #:: second #:: _ => first - second
  case _ => -1
}

где экстрактор определяется следующим образом:

1
2
3
4
5
object #:: {
  def unapply[A](xs: Stream[A]): Option[(A, Stream[A])] =
    if (xs.isEmpty) None
    else Some((xs.head, xs.tail))
}

Учитывая это, я хотел попробовать экстрактор на выборках Rational Number из книги Scala by Example , вот как выглядит Rational number:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Rational(n: Int, d: Int) {
private def gcd(x: Int, y: Int): Int = {
if (x == 0) y
else if (x < 0) gcd(-x,y)
else if (y < 0) -gcd(x, -y)
else gcd(y % x, x)
}
private val g = gcd(n, d)
 
val numer: Int = n/g
val denom: Int = d/g
 
def +(that: Rational) =
new Rational(numer * that.denom + that.numer * denom,
denom * that.denom)
 
def -(that: Rational) =
new Rational(numer * that.denom - that.numer * denom,
denom * that.denom)
 
def *(that: Rational) =
new Rational(numer * that.numer, denom * that.denom)
 
def /(that: Rational) =
new Rational(numer * that.denom, denom * that.numer)
 
 
override def toString = "" + numer + "/" + denom + ""
 
def square = new Rational(numer*numer, denom*denom)
}

и я хотел экстрактор, который будет вести себя следующим образом:

1
2
3
4
5
val r = new Rational(2, 3
 
r match {
  case num / denom => num + "/" + denom
}

Это абсолютно выполнимо в Scala, учитывая гибкость в именах идентификаторов. Учитывая это, экстрактор с именем «/» может быть определен следующим образом:

1
2
3
object / {
 def unapply(r: Rational): Option[(Int, Int)] = Some(r.numer, r.denom)
}

и используется для извлечения числителя и знаменателя рационального числа!

1
2
3
4
5
6
7
8
r match {
 case /(num, denom) => num + "/" + denom
}
 
//using infix
r match {
 case num / denom => num + "/" + denom
}
Ссылка: Scala экстракторы инкапсулируют образец с номерами Rational от нашего партнера JCG Биджу Кунджуммен в блоге all and sundry.