gpt4 book ai didi

json - 为什么这个 getOrElse 语句返回 ANY 类型?

转载 作者:行者123 更新时间:2023-12-04 22:58:13 25 4
gpt4 key购买 nike

我正在尝试遵循教程 https://www.jamesward.com/2012/02/21/play-framework-2-with-scala-anorm-json-coffeescript-jquery-heroku但当然,自教程以来 play-scala 发生了变化(我发现的每个教程似乎都是这种情况)。我正在使用 2.4.3 这需要我真正了解事情是如何工作的,不一定是坏事。

给我带来麻烦的一件事是 getOrElse 方法。

这是我的 Bar.scala 模型

package models

import play.api.db._
import play.api.Play.current
import anorm._
import anorm.SqlParser._

case class Bar(id: Option[Long], name: String)

object Bar {

val simple = {
get[Option[Long]]("id") ~
get[String]("name") map {
case id~name => Bar(id, name)
}
}

def findAll(): Seq[Bar] = {
DB.withConnection { implicit connection =>
SQL("select * from bar").as(Bar.simple *)
}
}

def create(bar: Bar): Unit = {
DB.withConnection { implicit connection =>
SQL("insert into bar(name) values ({name})").on(
'name -> bar.name
).executeUpdate()
}
}

}

和我的 BarFormat.scala Json 格式化程序
package models

import play.api.libs.json._
import anorm._

package object Implicits {
implicit object BarFormat extends Format[Bar] {
def reads(json: JsValue):JsResult[Bar] = JsSuccess(Bar(
Option((json \ "id").as[Long]),
(json \ "name").as[String]
))

def writes(bar: Bar) = JsObject(Seq(
"id" -> JsNumber(bar.id.getOrElse(0L)),
"name" -> JsString(bar.name)
))

}
}

为了完整起见,我的 Application.scala Controller :
package controllers

import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import javax.inject.Inject
import javax.inject._
import play.api.i18n.{ I18nSupport, MessagesApi, Messages, Lang }
import play.api.libs.json._

import views._
import models.Bar
import models.Implicits._

class Application @Inject()(val messagesApi: MessagesApi) extends Controller with I18nSupport {

val barForm = Form(
single("name" -> nonEmptyText)
)

def index = Action {
Ok(views.html.index(barForm))
}

def addBar() = Action { implicit request =>
barForm.bindFromRequest.fold(
errors => BadRequest,
{
case (name) =>
Bar.create(Bar(None, name))
Redirect(routes.Application.index())
}
)
}

def listBars() = Action { implicit request =>
val bars = Bar.findAll()

val json = Json.toJson(bars)

Ok(json).as("application/json")

}

和路线
 # Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

# Home page
POST /addBar controllers.Application.addBar
GET / controllers.Application.index
GET /listBars controllers.Application.listBars

# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)

当我尝试运行我的项目时,出现以下错误:

Compilation Error

现在 bar.id 被定义为一个 Option[Long] 所以 bar.id.getOrElse(0L) 应该返回一个 Long 据我所知,但它显然返回一个 Any。谁能帮我理解为什么?

谢谢你!

最佳答案

这就是类型推断在 Scala 中的工作方式......

首先有一个来自 Int 的隐式转换至 BigDecimal :

scala> (1 : Int) : BigDecimal
res0: BigDecimal = 1

该转换允许 Int在构造选项之前进行转换:
scala> Some(1) : Option[BigDecimal]
res1: Option[BigDecimal] = Some(1)

如果我们尝试 getOrElse在类型可以固定的地方我们得到预期的类型 Int :
scala> Some(1).getOrElse(2)
res2: Int = 1

但是,这不起作用(您遇到的问题):
scala> Some(1).getOrElse(2) : BigDecimal
<console>:11: error: type mismatch;
found : Any
required: BigDecimal
Some(1).getOrElse(2) : BigDecimal
^

Scala 的隐式转换在执行类型推断后才开始。这是有道理的,因为如果您不知道类型,您将如何知道需要应用哪些转换。 Scala 可以看到 BigDecimal是预期的,但它有一个 Int结果基于 Option 的类型它有。所以它试图扩大类型,找不到任何匹配 BigDecimalInt的类型层次结构并因错误而失败。

这是有效的,但是因为类型在变量声明中是固定的:
scala> val v = Some(1).getOrElse(2)
v: Int = 1

scala> v: BigDecimal
res4: BigDecimal = 1

所以我们需要以某种方式帮助编译器——任何类型注释或显式转换都可以工作。选择你喜欢的任何一个:
scala> (Some(1).getOrElse(2) : Int) : BigDecimal
res5: BigDecimal = 1

scala> Some(1).getOrElse[Int](2) : BigDecimal
res6: BigDecimal = 1

scala> BigDecimal(Some(1).getOrElse(2))
res7: scala.math.BigDecimal = 1

关于json - 为什么这个 getOrElse 语句返回 ANY 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35329761/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com