我在理解Scala语法时遇到问题,请提出建议。我有两个代码片段。
abstract class Try[T] {
def flatMap[U](f: T => Try[U]): Try[U] = this match {
case Success(x) => try f(x) catch { case NonFatal(ex) => Failure(ex) }
case fail: Failure => fail
}
}
我的理解:
Q1-我的理解正确吗?
Q2-f的返回类型(即Try [U])和平面映射Try [U]的返回类型之间有什么关系?一定要一样吗?
def flatMap [U](f:T => Try [U] ): Try [U]
或者我可以以某种方式拥有类似的东西
def flatMap [U](f:T => Option [U] ):尝试[U]
在最后一段代码中,我猜想,在我的flatMap中使用函数f之后,我需要在f的输出(即Option [U])和flatMap要求的最终输出之间建立连接。 (我是说Try [U])
编辑
此代码来自一个scala课程。这是完整的代码(有人问了这个问题)。我只想了解语法。
abstract class Try[T] {
def flatMap[U](f: T => Try[U]): Try[U] = this match {
case Success(x) => try f(x) catch { case NonFatal(ex) => Failure(ex) }
case fail: Failure => fail
}
def map[U](f: T => U): Try[U] = this match {
case Success(x) => Try(f(x))
case fail: Failure => fail
}
}
答案 0 :(得分:0)
Q1 在很大程度上是正确的,但只是为了澄清,所有这些都在编译时发生-T在运行时未知(请参见here)
第二季度当然,您可以创建带有签名的方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ERL.Models
{
public class LabEntry
{
public int sl { get; set; }
public string unitname { get; set; }
public string SampleName { get; set; }
public DateTime Entrydate { get; set; }
public string EntryTime { get; set; }
public string userid { get; set; }
public decimal Density15C { get; set; }
public decimal RVP_PSI { get; set; }
public string colourASTM { get; set; }
public decimal FP { get; set; }
public decimal Viscosity50 { get; set; }
public decimal Viscosity100 { get; set; }
public decimal pp { get; set; }
public decimal ASTM_IBP { get; set; }
public decimal ASTM5 { get; set; }
public decimal ASTM10 { get; set; }
public decimal ASTM50 { get; set; }
public string ASTM90 { get; set; }
public string ASTM95 { get; set; }
public decimal FBP { get; set; }
public decimal BSWB4Oxid { get; set; }
public decimal BSWAfterOxid { get; set; }
public string Report { get; set; }
public decimal FR5xylene { get; set; }
public int slWater { get; set; }
public string SampleNameWater { get; set; }
public decimal ph { get; set; }
public decimal COND { get; set; }
public decimal TDS { get; set; }
public decimal TA { get; set; }
public decimal TAC { get; set; }
public decimal NACL { get; set; }
public decimal H2S { get; set; }
public decimal NH3 { get; set; }
}
}
您可以随意调用该方法flatMap,但它不是标准的flatMap:
override func viewWillAppear(_ animated: Bool) {
let textFieldInsideSearchBar = searchBar.value(forKey: "_searchField") as? UITextField
textFieldInsideSearchBar?.borderStyle = .none
textFieldInsideSearchBar?.textColor = UIColor.white
textFieldInsideSearchBar?.underlined()
}
flatMap的形式存在数学原因(这也对Scala的for表达式的实现有影响)。为避免混乱...
将...[U](f: T => Option[U]): Try[U]
用trait T[A] {
flatMap[B](f: A => T[B]): T[B]
}
包裹起来,以创建T => Option[U]
,然后再将其传递给flatMap,而不是更改flatMap的签名。
答案 1 :(得分:0)
Q1-我的理解正确吗?
很难根据您的示例代码进行注释,该示例代码在抽象类中具有方法实现,而未定义任何具体类。让我们考虑从Scala API中提取的Try
的以下玩具版本,并在其具体类中使用flatMap
实现:
import scala.util.control.NonFatal
sealed abstract class MyTry[+T] {
def flatMap[U](f: T => MyTry[U]): MyTry[U]
}
object MyTry {
def apply[T](r: => T): MyTry[T] =
try MySuccess(r) catch { case NonFatal(e) => MyFailure(e) }
}
final case class MyFailure[+T](exception: Throwable) extends MyTry[T] {
override def flatMap[U](f: T => MyTry[U]): MyTry[U] =
this.asInstanceOf[MyTry[U]]
}
final case class MySuccess[+T](value: T) extends MyTry[T] {
override def flatMap[U](f: T => MyTry[U]): MyTry[U] =
try f(value) catch { case NonFatal(e) => MyFailure(e) }
}
使用以下函数f: T => MyTry[U]
对其进行测试,其中T
=字符串,U
=整数,希望它能回答您的问题:
val f: String => MyTry[Int] = s => s match {
case "bad" => MyFailure(new Exception("oops"))
case s => MySuccess(s.length)
}
MyTry("abcde").flatMap(f)
// res1: MyTry[Int] = MySuccess(5)
MyTry("bad").flatMap(f)
// res2: MyTry[Int] = MyFailure(java.lang.Exception: oops)
Q2-f的返回类型(即Try [U])之间的关系是什么 以及平面地图Try [U]的返回类型?一定要一样吗?
在Scala中,flatMap
是许多Scala容器/集合中定义的常用方法,例如Option[T]
,List[T]
,Try[T]
,Future[T]
,标准签名:
class Container[T] {
def flatMap[U](f: T => Container[U]): Container[U]
}
如果您想要一个特殊的地图,该地图需要一个T => Container1[U]
函数并返回一个Container2[U]
,则最好不要将其命名为flatMap
。