Frage

Ich mache ein kleines Problem-Management-System in Aufzug sowohl Scala und Aufzug zu lernen.

Ich habe eine Ansicht, die eine einzelne Ausgabe zeigt zu einem Projekt gehören. Bevor ich Daten an die View-Template binden, möchte ich überprüfen, dass ich alle Daten erforderlich ist, so möchte ich, dass speziell überprüfen:

  • Ein Projekt ID param geliefert wurde
  • existiert ein Projekt mit der mitgelieferten Projekt-ID
  • Ein Problem ID param geliefert wurde
  • Es besteht ein Problem mit dem mitgelieferten Heft ID

Und diese braucht, um zu bewerten, so dass, wenn ich es schreiben sollte jetzt mit meinem aktuellen Verständnis der Scala, würde ich Folgendes tun:

class Project {
    def findByID(xhtml:NodeSeq): NodeSeq = 
        param("projectID") match {
            case Full(projectID) =>
                Project.findByID(projectID) match {
                    case Full(projectID) =>
                        param("issueID") match {
                            ....
                        }
                    case _ => Text("Project does not exist")
                }
            case _ => Text("projectIDNotSupplied")
        }
}

Also ich frage mich, ob es ein einfacherer Weg, dies durchzuführen? Ich denke, dass ein für die Expression könnte in der Lage sein, etwas ähnliches durchzuführen. Beachten Sie, dass Project.findByID gibt eine Box [Projekt].

War es hilfreich?

Lösung

Sorry, ich bin so spät, um die Show, aber wie Daniel sagt kann man in der Tat Lift Box verwenden und? ~, So etwas zu tun. Zum Beispiel:

import net.liftweb.util.Box
import net.liftweb.util.Box._

class Project {
  def findByID(xhtml:NodeSeq): NodeSeq = 
    (for {
      projectID <- param("projectID") ?~ "projectIDNotSupplied"
      project <- Project.findById(projectID) ?~ "Project does not exist"
      issueID <- param("issueID") ?~ "issueIDNotSupplied"
      ...
    } yield {
      ...
    }) match {
      case Full(n) => n
      case Failure(msg, _, _) => Text(msg)
      case _ => Text("fail")
    }
}

Was? ~ Tut, ist schalen ein leeres Feld in eine Failure Box mit der angegebenen String Fehlermeldung, aber tut nichts, um ein Full (Erfolg) Box. So ist der Rückgabewert von findByID wird voll sein, wenn alles gelingt, oder Failure (mit der angegebenen Fehlermeldung) anders. Wenn Sie die Fehler zu verketten wollen, dann benutzen? ~! statt.

Andere Tipps

Ich weiß nicht, Lift, aber es gibt ein paar Dinge, die ich gesehen habe darin Umsetzung ist. Einer von ihnen ist die Ausfall Methoden: ?~ und ?~!. Ich bin mir nicht sicher, wie man sie etwa mit gehen könnte, aber es scheint sinnvoll zu sein. Ein weiterer Grund ist open_!, um Ausnahmen zu werfen.

Nun wird eine Box-Unterstützung Karte, flatMap, Filter und foreach, so kann sie vollständig in einem für das Verständnis verwendet werden:

for(projectID <- param("projectID");
    if Project.findByID(projectID).isDefined;
    issueID <- param("issueID");
    if Issue.findByID(issueID).isDefined)
yield ...

Dies wird nicht die Fehlermeldungen erhalten. Für diejenigen, bin zu raten ich die Methoden, die ich erwähnt, oder andere wie ~>, könnte die Antwort geben.

Ich weiß nicht, Fahrstuhl so dass ich keine Aufzüge spezifische Fragen beantworten können. Ich habe aber kam eine Idee, wie man von Ihrem Problem zu lösen, das ist wie eine Folge von Check-dann arbeiten schreiben Aktionen ohne verschachtelten Musterabgleich greifen zu müssen.

Der Hauptdatentyp im Einsatz hier ist eine Option, aber ich bin sicher, dass es ganz einfach sein wird, auf Ihre Bedürfnisse anzupassen. Was wir hier erreichen wollen ist eine Folge von

zu tun
  1. Prüfbedingung
  2. weiter, wenn erfolgreich
  3. beenden und zurück etwas anders

Der Code macht eine Art Kurzschluss, sobald es eine None begegnet so der Rückgabewert beibehalten wird, wenn die Folge von Aktionen zurückkehren. Zur Verwendung mit einer Option startet dann schreiben „ifSome“, wenn Option a Einige und „ifNone“, wenn Option a None ist, fortgesetzt werden, bis die Sequenz beendet ist. Wenn ein Keine Begegnung an jedem Punkt in der Folge ist, kehrte die Option vom Call-by-Name-Parameter von „isNone“ zurückgehalten und zurückgeführt, wenn die letzte „toOption“ genannt wird. Verwenden Sie „toOption“, um die aktuelle Option Ergebnis zurück.

Überprüfen Sie das Beispiel in „main“ für einige Anwendungsfälle aus. Viel Glück!

object Options {

  class RichOption[A](a: Option[A]) {

    def ifSome[B](f: A => Option[B]): RichOption[B] = a match {
      case Some(x) => new RichOption(f(x))
      case None => this.asInstanceOf[RichOption[B]]
    }

    def ifNone[B](f: => Option[B]): RichOption[B] = a match {
      case Some(_) => this.asInstanceOf[RichOption[B]]
      case None => new RichNone(f)
    }

    def toOption[A] = a
  }

  class RichNone[A](a: Option[A]) extends RichOption[A](a) {

    override def ifSome[B](f: A => Option[B]): RichOption[B] = this.asInstanceOf[RichOption[B]]

    override def ifNone[B](f: => Option[B]): RichOption[B] = this.asInstanceOf[RichOption[B]]
  }

  implicit def option2RichOption[A](a: Option[A]): RichOption[A] = new RichOption(a)

  def main(args: Array[String]) {
    println(Some("hello") ifSome(s => Some(s.toUpperCase)) toOption) // prints Some(HELLO)
    println(Some("hello") ifNone(Some("empty")) toOption) // prints Some(hello)
    println(Some("hello") ifSome(s => Some(s.toUpperCase)) ifNone(Some("empty")) toOption) // prints Some(HELLO)
    println(Some("hello") ifNone(Some("empty")) ifSome(s => Some(s.toUpperCase)) toOption) // prints Some(HELLO)
    println((None: Option[String]) ifSome(s => Some(s.toUpperCase)) toOption) // prints None
    println((None: Option[String]) ifNone(Some("empty")) toOption) // prints Some(empty)
    println((None: Option[String]) ifSome(s => Some(s.toUpperCase)) ifNone(Some("empty")) toOption) // prints Some(empty)
    println((None: Option[String]) ifNone(Some("empty")) ifSome(s => Some(s.toUpperCase)) toOption) // prints Some(empty)
    println(Some("hello world") ifSome(s => Some(s.toUpperCase)) ifNone(Some("empty")) ifSome(s => Some(s.length)) ifNone(None) toOption) // prints Some(11)
    println(Some("hello world") ifSome(_ => None) ifNone(Some("goodbye world")) ifSome(s => Some(s.length)) ifNone(None) toOption) // prints Some(goodbye world)
    println((None: Option[String]) ifSome(s => Some(s.toUpperCase)) ifNone(Some("empty")) ifSome(s => Some(s.length)) ifNone(None) toOption) // prints Some(empty)
    println((None: Option[String]) ifSome(_ => None) ifNone(Some("goodbye world")) ifSome(s => Some(s.length)) ifNone(None) toOption) // prints Some(goodbye world)
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top