2017-03-11 11 views
0

私は以下のコードを持っていて、私のfindOrCreate()機能では、Type mismatch found Unit, required Future[Customer]というエラーが表示されています。 findOrCreate()の中で呼び出されているcustomerByPhone()関数には、Futuresを呼び出すコールも含まれているため、私はfatmapを使用しています。フラット・マップの結果が、なぜUnitになったのかわかりません。私は間違って何をしていますか?タイプの不一致が見つかりましたユニット、必須フラットマップの未来[得意先]

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) 
} 
+0

'val'ステートメントは' Unit'を返します。 – Reactormonk

+0

@ Reactormonk私の知る限り、valは変数を不変にしますが、値を返すことはできますか? – Rafa

+0

'val foo:Int = {val bar = 32}'はあなたにコンパイルエラーを与えます。 – Reactormonk

答えて

1

Reactormonkは基本的にこのコメントにコメントしていますが、実際にはいくつかの詳細を記した回答を作成します。 valの発言がUnitという彼のコメントは基本的には正しいですが、私はいくつかの精緻化によって事態がより明確になることを期待しています。

私が見る鍵の要素は、valが宣言であることです。 Scalaの宣言は、有用な値を生成しないステートメントです。 Scalaの機能上の性質から、それらは値を生成しますが、それはUnitであり、Unitというインスタンスが1つしかないので、それは意味を持ちません。

Scalaの新しいプログラマーは、このようなことをしばしば誘惑される理由は、コードブロックをステートメントとして考えることがなく、他の言語でreturnを使用することがよくあるからです。ここでは単純化された関数を考えてみましょう。

def foo(i: Int): Int = { 
    42 * i 
} 

ここには本当に必要ではないが、私はこのエラーの鍵であると思うので、コードブロックが含まれています。コードブロックの値は、単にコードブロック内の最後の式の値です。このため、returnを指定する必要はありませんが、returnに慣れているほとんどのプログラマーは、ブロックの最後の裸の表現に少し不快です。だからこそ、val宣言を投げ込もうとしているのです。もちろん

def foo(i: Int): Int = { 
    val result = 42 * i // Error: type mismatch. 
} 

、などが挙げたが、Unitval結果は、これは間違って作っていました。ちょうどresultの余分な行を追加するとコンパイルできますが、これはあまり冗長で非慣用です。

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で動作しません。式としてブロックの関数スタイルに慣れるまでには時間がかかります。あなたがその点に達するまでは、メソッドの最後にreturnがあるように行動するだけで、実際にメソッドを置かなくても役立ちます。

コメントの中で、jwvhはCのような宣言が値を返すと主張しています。それは偽です。割り当てほとんどのCファミリ言語でが割り当てられた値を返すので、は値5を返しますが、宣言はしません。したがって、int a = 5;は何も返さず、式として使用できません。

関連する問題