私はボールローリングを開始します。頻繁に遭遇する問題のためにScalaに確立された共通のパターン/ソリューション
いくつかの要素が複数回含まれている場合、一般的な要件の1つは、タリーまたはヒストグラムの形でカウントすることです。
しばしば引用符で囲まれたソリューションは、次のとおりです。
ss.groupBy(identity).mapValues(_.size)
だから、Scalaでは同様の一般的に遭遇する問題のために存在する他のどのような解決策?
私はボールローリングを開始します。頻繁に遭遇する問題のためにScalaに確立された共通のパターン/ソリューション
いくつかの要素が複数回含まれている場合、一般的な要件の1つは、タリーまたはヒストグラムの形でカウントすることです。
しばしば引用符で囲まれたソリューションは、次のとおりです。
ss.groupBy(identity).mapValues(_.size)
だから、Scalaでは同様の一般的に遭遇する問題のために存在する他のどのような解決策?
Monoid
sまたはNumeric
を使用して、必要に応じてインプリシットを使用して、リッチクラスの適切な操作を定義します。
case class Money(ccy: Currency, amount : BigDecimal) {
def +(that : Money) = {
require(this.currency == that.curency)
copy(amount = this.amount + that.amount)
}
def abs = copy(amount = amount.abs)
}
それではさんは、私がMoney
年代のコレクションを持っているとしましょうと私はそれらを合計する:
val turnover = trades.map(_.usdValue.abs).∑ //no implicit monoid :-(
しかし、これを実行するために、私は暗黙のMonoid
を持っている必要があります。しかし、ゼロの値がMoney
の場合は、すでに通貨がある場合のみ意味があります。
implicit def CurrencyMonoid(implicit currency : Currency) = new Monoid[Currency] {
def zero = Money(currency, 0)
def append(m1 : Money, m2 : Money) = m1 + m2
}
だから今Scalaはこれらの暗黙の両方を使用します。
implicit val usd = Currency.USD
val turnover = trades.map(_.usdValue.abs).∑ //yay for monoids :-)
Scalaコレクションのデカルト積を生成する方法が何度も欠けていました。 Haskellでは、あなたは
import Control.Applicative
(,) <$> [1,2,3] <*> ["a","b"]
-- [(1,"a"),(1,"b"),(2,"a"),(2,"b"),(3,"a"),(3,"b")]
for(x <- List(1,2,3); y <- List("a","b")) yield (x,y)
があまりにも不器用であるScalaのソリューションを書くことができます。
scalaz: '(リスト(1,2,3)| @ – Debilski
)最も!それは私の主張することが許可されているので、私の質問です:) –
は私が...
我々は成功した出力を生成する、またはいくつかのエラーメッセージで失敗することがありプロセスの数を持っている問題の解決策を再び同じドラムを叩いたがいないということ。目標は、すべてのプロセスが成功し、1つ以上が失敗した場合、すべてのエラーメッセージを集約するために、成功した結果を集計することです。
これはscalaz検証することで解決することができます:まず、セットアップ一部の輸入
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
は、今すぐ/失敗を集約するApplicative
を使用するのは、私たちの "プロセス"
scala> def fooI(s : String) : ValidationNEL[Exception, Int] = s.parseInt.liftFailNel
fooI: (s: String)scalaz.Scalaz.ValidationNEL[Exception,Int]
scala> def fooF(s : String) : ValidationNEL[Exception, Float] = s.parseFloat.liftFailNel
fooF: (s: String)scalaz.Scalaz.ValidationNEL[Exception,Float]
scala> def fooB(s : String) : ValidationNEL[Exception, Boolean] = s.parseBoolean.liftFailNel
fooB: (s: String)scalaz.Scalaz.ValidationNEL[Exception,Boolean]
を定義してみましょう成功:
scala> def attempt(ss : String*) = (fooI(ss(0)) <|**|> (fooF(ss(1)), fooB(ss(2)))) match {
| case Success((i, f, b)) => println("Found " + i + " " + f + " " + b)
| case Failure(es) => es foreach println
| }
attempt: (ss: String*)Unit
今度は、いくつかの失敗のために試してみましょう:
scala> attempt("a", "b", "true")
java.lang.NumberFormatException: For input string: "a"
java.lang.NumberFormatException: For input string: "b"
今度は成功のために試してみましょう:
scala> attempt("1", "2.3", "false")
Found 1 2.3 false
特定の条件cond
がSome(x)
を返す保持している場合は、他のリターンNone
:
Some(x) filter cond
を[ポールフィリップスのポストメーリングリストの投稿から]
臆面もなくこの質問へのoxbow_lakes'答えから盗ま:Instantiating a case class from a list of parameters
引数を指定するタプルを使用する方法/関数を呼び出す:これは、任意の関数のために使用することができる
case class Foo(a: Int, b: String, c: Double)
(Foo.apply _).tupled apply (1, "bar", 3.14)
。
時にはあなたが代わりのための間、使用する必要があり、多くの場合、あなたは結果を収集している:
val buf = new Listbuffer[Int]
while(cond()) {
val x = fancyStuff()
buf += calculation(x)
}
私は思いますwhile
については、for
の場合と同じように「何か」を出すようにしておくことが大切です。イオンスタイル:
val buf = while(cond()) {
val x = fancyStuff()
} yield calculation(x)
私はこの1つが好きです。(例えば、リスト( "a"、 "b"))( –