部分函数的Scala奇怪错误

时间:2017-08-21 07:55:03

标签: scala

我有以下一段代码因为一些奇怪的原因而无法编译!

def createNewPowerPlant = Action.async(parse.tolerantJson) { request =>
    request.body.validate[PowerPlantConfig].fold(
      errors => {
        Future.successful(
          BadRequest(Json.obj("message" -> s"invalid PowerPlantConfig $errors"))
        )
      },
      success => { // fails here!!
        dbService.newPowerPlant(toPowerPlantRow(success)).recover {
          case NonFatal(ex) =>
            Future.successful { UnprocessableEntity(
              Json.obj("message" -> s"Could not create new PowerPlant because of ${ex.getMessage}")
            ) }
        }
        Future.successful { Ok("") }
      }
    )
  }

这就是我所看到的原因:

Controller.scala:103: a type was inferred to be `Any`; this may indicate a programming error.
[error]       success => {
[error]                  ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 16 s, completed Aug 21, 2017 9:46:30 AM

有关此错误发生原因的任何想法?我确定它与编译器有关,因为我在我的控制器中有类似的代码编译!

2 个答案:

答案 0 :(得分:1)

build.sbt中有"-Xfatal-warnings"。这使编译器抛出一个编译错误,在常规情况下它只是一个警告。 为了检查这一点,我评论了"-Xfatal-warnings"。然后sbt clean compile给出了这个:

alex@POSITRON /ssd2/projects/PowerPlantProblem/plant-simulator $ sbt clean compile
[info] Loading project definition from /ssd2/projects/PowerPlantProblem/plant-simulator/project
[info] Updating {file:/ssd2/projects/PowerPlantProblem/plant-simulator/project/}plant-simulator-build...
Waiting for lock on /home/alex/.ivy2/.sbt.ivy.lock to be available...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Set current project to plant-simulator (in build file:/ssd2/projects/PowerPlantProblem/plant-simulator/)
[success] Total time: 0 s, completed Aug 21, 2017 3:39:57 PM
[info] Updating {file:/ssd2/projects/PowerPlantProblem/plant-simulator/}root...
[info] Resolving jline#jline;2.14.3 ...
[info] Done updating.
[info] Compiling 31 Scala sources and 2 Java sources to /ssd2/projects/PowerPlantProblem/plant-simulator/target/scala-2.11/classes...
[warn] /ssd2/projects/PowerPlantProblem/plant-simulator/app/com/inland24/plantsim/controllers/PowerPlantController.scala:102: a type was inferred to be `Any`; this may indicate a programming error.
[warn]           case Some(row) => dbService.newPowerPlant(row) recoverWith{
[warn]                ^
[warn] one warning found
[success] Total time: 23 s, completed Aug 21, 2017 3:40:20 PM
alex@POSITRON /ssd2/projects/PowerPlantProblem/plant-simulator $ 

这意味着我的建议是正确的。 因此,您要么禁用"-Xfatal-warnings",要么使代码满足它带来的更严格的要求。

现在为了理解警告本身,请看一下recoverWith方法的签名:

def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U]

在您的情况下,TInt。因此IntFuture[Result]的任何共同祖先当然都是Any。 您只需在此处插入"-Xfatal-warnings"值即可使Intcase Some(row) => dbService.newPowerPlant(row) recoverWith{ case ex: Exception => Future.successful{ UnprocessableEntity( Json.obj("message" -> s"Could not create new PowerPlant because of ${ex.getMessage}") ) 5 } } 兼容:

UnprocessableEntity

这里的警告是有道理的,因为代码不干净:你试图通过返回Future.successful { Ok("") } HTTP状态来恢复向DB插入行(例如DB服务器已关闭)的问题任何意义上的考虑到你在 @Override public void onMapClick(LatLng latLng) { mMap.clear(); mMap.addMarker(new MarkerOptions().position(latLng).title("Konum")); mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); Geocoder geocoder = new Geocoder(MapsActivity.this.getBaseContext(), Locale.getDefault()); try { List<Address> city = geocoder.getFromLocation(latLng.latitude,latLng.longitude,1); if (city != null && city.size() > 0){ Log.i("Info",city.get(0).getLocality()); } } catch (IOException e) { e.printStackTrace(); } } 之后覆盖了这个意图。

希望这有帮助。

答案 1 :(得分:0)

来自Alexander Arendar

的提示

我做了以下事情来解决这个问题:

def createNewPowerPlant = Action.async(parse.tolerantJson) { request =>
    request.body.validate[PowerPlantConfig].fold(
      errors => {
        Future.successful(
          BadRequest(Json.obj("message" -> s"invalid PowerPlantConfig $errors"))
        )
      },
      success => {
        toPowerPlantRow(success) match {
          case None => Future.successful(
            BadRequest(Json.obj("message" -> s"invalid PowerPlantConfig ")) // TODO: fix errors
          )
          case Some(row) =>
            dbService.newPowerPlant(row).materialize.map {
              case Success(insertedRecordId) =>
                Ok("TODO: Send a Success JSON back with the id of the newly inserted record")
              case Failure(ex) =>
                UnprocessableEntity(
                  Json.obj("message" -> s"Could not create new PowerPlant because of ${ex.getMessage}")
                )
            }
        }
      }
    )
  }

请注意我使用Monix库中的实现FutureExtensions方法!