Ar „Scala“ nieko nekainuoja už bet kokią sąlygą?

Scaloje noriu parašyti funkciją, kuri tam tikrame diapazone suteikia nelyginius skaičius. Kai funkcija kartojama, funkcija spausdina kai kurį žurnalą. Pirmoji funkcijos versija:

 def getOdds(N: Int): Traversable[Int] = { val list = new mutable.MutableList[Int] for (n <- 0 until N) { if (n % 2 == 1) { list += n } else { println("skip even number " + n) } } return list } 

Jei praleisiu spausdinimo žurnalus, įgyvendinimas tampa labai paprastas:

 def getOddsWithoutPrint(N: Int) = for (n <- 0 until N if (n % 2 == 1)) yield n 

Tačiau nenoriu praleisti dalies registracijos. Kaip perrašyti pirmąją versiją labiau kompaktiškai? Būtų puiku, jei jį būtų galima perrašyti taip pat:

 def IWantToDoSomethingSimilar(N: Int) = for (n <- 0 until N) if (n % 2 == 1) yield n else println("skip even number " + n) 
11
16 сент. set pocorall Rugsėjo 16 d 2012-09-16 16:25 '12, 16:25 pm 2012-09-16 16:25
@ 4 atsakymai
 def IWantToDoSomethingSimilar(N: Int) = for { n <- 0 until N if n % 2 != 0 || { println("skip even number " + n); false } } yield n 

filter vietoj išraiškos būtų šiek tiek paprastesnis.

8
16 сент. atsakymą pateikė Luigi Plinge rugsėjo 16 d 2012-09-16 19:43 '12 19:43 val. 2012-09-16 19:43

Noriu išlaikyti savo trajektorijos seką (apdorojimo koeficientus ir derinimą, o ne atskirai), galite naudoti kažką panašaus (redaguoti):

 def IWantToDoSomethingSimilar(N: Int) = (for (n <- (0 until N)) yield { if (n % 2 == 1) { Option(n) } else { println("skip even number " + n) None } // Flatten transforms the Seq[Option[Int]] into Seq[Int] }).flatten 

EDIT, vadovaujantis ta pačia koncepcija, yra trumpesnis sprendimas:

 def IWantToDoSomethingSimilar(N: Int) = (0 until N) map { case n if n % 2 == 0 => println("skip even number "+ n) case n => n } collect {case i:Int => i} 
6
16 сент. atsakymas, kurį pateikė jwinandy Sep 16 2012-09-16 17:05 '12, 5:05 val. 2012-09-16 17:05

Jei norite suprasti funkcinį požiūrį, tada prasideda kažkas panašaus:

Pirma, kai kurie bendrieji apibrėžimai:

  // use scalaz 7 import scalaz._, Scalaz._ // transforms a function returning either E or B into a // function returning an optional B and optionally writing a log of type E def logged[A, E, B, F[_]](f: A => E \/ B)( implicit FM: Monoid[F[E]], FP: Pointed[F]): (A => Writer[F[E], Option[B]]) = (a: A) => f(a).fold( e => Writer(FP.point(e), None), b => Writer(FM.zero, Some(b))) // helper for fixing the log storage format to List def listLogged[A, E, B](f: A => E \/ B) = logged[A, E, B, List](f) // shorthand for a String logger with List storage type W[+A] = Writer[List[String], A] 

Dabar jums reikia parašyti tik filtro funkciją:

  def keepOdd(n: Int): String \/ Int = if (n % 2 == 1) \/.right(n) else \/.left(n + " was even") 

Galite išbandyti iš karto:

  scala> List(5, 6) map(keepOdd) res0: List[scalaz.\/[String,Int]] = List(\/-(5), -\/(6 was even)) 

Tada galite naudoti traverse funkciją, kad pritaikytumėte savo funkciją į įvesties sąrašą ir surinkti įrašytus žurnalus ir rezultatus:

  scala> val x = List(5, 6).traverse[W, Option[Int]](listLogged(keepOdd)) x: W[List[Option[Int]]] = scalaz.WriterTFunctions$$anon$26@503d0400 // unwrap the results scala> x.run res11: (List[String], List[Option[Int]]) = (List(6 was even),List(Some(5), None)) // we may even drop the None-s from the output scala> val (logs, results) = x.map(_.flatten).run logs: List[String] = List(6 was even) results: List[Int] = List(5) 
3
16 сент. atsakymas duotas ron . 2012-09-16 17:56 '12 at 5:56 pm 2012-09-16 17:56

Nemanau, kad tai galima lengvai suprasti. Tačiau galite naudoti skyrių.

 def getOffs(N:Int) = { val (evens, odds) = 0 until N partition { x => x % 2 == 0 } evens foreach { x => println("skipping " + x) } odds } 

EDIT. Norėdami išvengti žurnalo pranešimų spausdinimo po to, kai baigiamas skaidymas, pirmąją metodo eilutę galite pakeisti taip:

 val (evens, odds) = (0 until N).view.partition { x => x % 2 == 0 } 
1
16 сент. Kim Stebel atsakymas, pateiktas rugsėjo 16 d. 2012-09-16 17:00 '12 17:00 val. 2012-09-16 17:00

Kiti klausimai apie „ arba „ Klauskite“