Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 在flatmap上找到类型不匹配的装置,需要未来[客户]_Scala_Functional Programming_Future_Flatmap - Fatal编程技术网

Scala 在flatmap上找到类型不匹配的装置,需要未来[客户]

Scala 在flatmap上找到类型不匹配的装置,需要未来[客户],scala,functional-programming,future,flatmap,Scala,Functional Programming,Future,Flatmap,我有下面的代码,在我的findOrCreate()函数中,我得到一个错误,说找到了类型不匹配的单元,需要未来的[Customer]。在findOrCreate()内部调用的customerByPhone()函数也包含预期未来的调用,这就是我使用fatmap的原因。我不知道为什么平面图的结果会导致单元。我做错了什么 override def findOrCreate(phoneNumber: String, creationReason: String): Future[AvroCustomer]

我有下面的代码,在我的
findOrCreate()
函数中,我得到一个错误,说
找到了类型不匹配的单元,需要未来的[Customer]
。在
findOrCreate()
内部调用的
customerByPhone()
函数也包含预期未来的调用,这就是我使用fatmap的原因。我不知道为什么平面图的结果会导致
单元
。我做错了什么

override def findOrCreate(phoneNumber: String, creationReason: String): Future[AvroCustomer] =  {

  //query for customer in db
  val avroCustomer: Future[AvroCustomer] = customerByPhone(phoneNumber).flatMap(_ => createUserAndEvent(phoneNumber, creationReason, 1.0))

}

override def customerByPhone(phoneNumber: String): Future[AvroCustomer] = {
  val query = Schema.Customers.byPhoneNumber(phoneNumber)
  val dbAction: DBIO[Option[Schema.Customer]] = query.result.headOption

  db.run(dbAction)
    .map(_.map(AvroConverters.toAvroCustomer).orNull)
}

private def createUserAndEvent(phoneNumber: String, creationReason: String, version: Double): Future[AvroCustomer] = {

  val query = Schema.Customers.byPhoneNumber(phoneNumber)
  val dbAction: DBIO[Option[Schema.Customer]] = query.result.headOption

  val data: JsValue = Json.obj(
    "phone_number" -> phoneNumber,
    "agent_number" -> "placeholder for agent number",
    "creation_reason" -> creationReason
  )
  //empty for now
  val metadata: JsValue = Json.obj()

  //creates user
  val avroCustomer: Future[AvroCustomer] = db.run(dbAction).map(_.map(AvroConverters.toAvroCustomer).orNull)
  avroCustomer.onComplete({
    case Success(null) => {

    }

    //creates event
    case Success(customer) => {
      val uuid: UUID = UUID.fromString(customer.id)
      //create event
      val event: Future[CustomerEvent] = db.run(Schema.CustomerEvents.create(
        uuid,
        "customer_creation",
        version,
        data,
        metadata)
      ).map(AvroConverters.toAvroEvent)
    }
    case Failure(exception) => {

    }
  })

  Future.successful(new AvroCustomer)
}

虽然Reactormonk在评论中基本上回答了这个问题,但我将实际写一个包含一些细节的答案。他关于
val
语句产生
Unit
的评论从根本上说是正确的,但我希望一些详细说明会让事情变得更清楚

我看到的关键元素是
val
是一个声明。Scala中的声明是不产生有用值的语句。由于Scala的功能性质,它们确实产生了一个值,但它是
Unit
,因为只有一个
Unit
,所以它没有任何意义

Scala新手经常尝试这样做的原因是,他们不认为代码块是语句,通常习惯于在其他语言中使用
return
。让我们考虑一个简化函数。< /P>
def foo(i: Int): Int = {
  42 * i
}
我包括了一个代码块,因为我认为这是这个错误的关键,尽管这里确实不需要它。代码块的值就是代码块中最后一个表达式的值。这就是为什么我们不必指定
return
,但是大多数习惯
return
的程序员对块末尾的裸表达式有点不舒服。这就是为什么要加入
val
声明的原因

def foo(i: Int): Int = {
  val result = 42 * i // Error: type mismatch.
}
当然,正如前面提到的,但是
val
导致
Unit
使这一点不正确。您可以添加一个额外的行,其中只包含
结果
,这将进行编译,但它过于冗长且不惯用

Scala支持使用
return
离开一个方法/函数并返回一个特定的值,尽管美国通常不赞成这样做。因此,下面的代码是有效的

def foo(i: Int): Int = {
  return 42 * i
}
虽然您不应该在Scala代码中使用
return
,但我觉得想象它存在可以帮助理解这里的错误。如果在
val
前面粘贴一个
return
,则会得到如下代码

def foo(i: Int): Int = {
  return val result = 42 * i // Error: type mismatch.
}
至少对我来说,这个代码显然是不正确的。
val
是一个声明,因此它不适用于
返回。习惯块作为表达式的函数样式需要一些时间。在达到这一点之前,只需表现出方法末尾有一个
return
,而不实际放在那里,可能会有所帮助


值得注意的是,在评论中,jwvh声称C中这样的声明将返回一个值。这是错误的赋值在大多数C族语言中返回被赋值的值,因此
a=5
返回值
5
,但声明不返回值,因此
int a=5
不返回任何内容,不能用作表达式。

A
val
语句返回
Unit
@reactormank据我所知,val只是使变量不可变,但您可以返回任何值?
val foo:Int={val bar=32}
将给您一个编译错误。
val
使用指定的值创建不可变变量,但它不会像在C语言中那样返回该值。