سؤال

أنا صنع نظام إدارة مسألة صغيرة في المصعد لتعلم كل من Scala ورفع.

لدي رأي يعرض مشكلة واحدة ينتمي إلى مشروع. قبل أن أرتبط البيانات إلى قالب العرض، أريد التحقق من أن لدي جميع البيانات المطلوبة، لذلك أريد التحقق على وجه التحديد:

  • تم توفير معرف مشروع معرف
  • يوجد مشروع مع معرف المشروع المرفق
  • تم توفير معرف معرف مشكلة
  • توجد مشكلة مع معرف القضية الموردة

وهذه تحتاج إلى تقييمها من أجل، لذلك إذا كنت أكتبها الآن مع فهمي الحالي لسكلا، سأقوم بما يلي:

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")
        }
}

لذلك أنا أتساءل عما إذا كانت هناك طريقة أسهل لأداء هذا؟ أعتقد أن التعبير قد يكون قادرا على أداء شيء مماثل. أن تدرك أن project.findbyid إرجاع مربع [المشروع].

هل كانت مفيدة؟

المحلول

آسف أنا متأخر جدا مع العرض، ولكن كما يقول دانيال أنه يمكنك بالفعل استخدام صندوق الرفع و؟ ~ لفعل شيء مثل هذا. علي سبيل المثال:

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")
    }
}

ماذا يفعل؟ لذلك ستكون قيمة الإرجاع ل FindByID ممتلئة إذا نجح كل شيء أو فشل (مع رسالة الخطأ المحددة) خلاف ذلك. إذا كنت تريد الفشل في السلسلة، فعندئذ استخدام؟ ~! في حين أن.

نصائح أخرى

أنا لا أعرف الرفع، ولكن هناك بعض الأشياء التي رأيتها في تنفيذها. واحد منهم هو طرق الفشل: ?~ و ?~!. وبعد لست متأكدا تماما كيف قد يستمر المرء باستخدامها، لكن يبدو أنه مفيد. آخر هو open_!, ، لرمي الاستثناءات.

الآن، خريطة دعم مربع، صالة مخلفات، تصفية و Foreach، لذلك يمكن استخدامها بالكامل داخل الفهم:

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

لن يحصلك على رسائل الخطأ. بالنسبة لأولئك، أعتقد أن الطرق التي ذكرتها، أو غيرها ~>, ، قد توفر الجواب.

لا أعرف الرفع حتى لا أستطيع الإجابة على أي أسئلة ذات رفع. ومع ذلك، فقد جاءت بطريقة حل إحدى مشكلتك وهي كيفية كتابة سلسلة من الإجراءات التي تعمل بعد ذلك دون اللجوء إلى مطابقة نمط متداخل.

يتم اختيار نوع البيانات الرئيسي قيد الاستخدام هنا، لكنني متأكد من أنه سيكون من السهل جدا التكيف مع احتياجاتك. ما نريد أن ينجزه هنا هو القيام بتسلسل

  1. حالة الاختيار
  2. متابعة إذا نجحت
  3. إنهاء وإعادة شيء خلاف ذلك

لا يقوم الكود بإجراء نوع من الدائرة القصيرة بمجرد حصوله على أي قيمة إرجاعا عند الاحتفاظ بتسلسل الإجراءات. لاستخدامها، يبدأ بخيار، ثم اكتب "IFSome" إذا كان الخيار هو بعض و "ifnone" إذا كان الخيار ليس شيئا، فاستمر حتى يتم الانتهاء من التسلسل. إذا لم يواجه أي شيء في أي وقت في التسلسل، فسيتم الاحتفاظ بالخيار الذي تم إرجاعه من معلمة اسم مكالمة باسم "ISNONE" وإرجاعه عند استدعاء "Tooption" النهائي. استخدم "Tooption" لاستعادة نتيجة الخيار الفعلي.

تحقق من المثال في "Main" لبعض حالات الاستخدام. حظ سعيد!

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)
  }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top