说我有一个像这样的简单类
abstract class Foo {
implicit val impInt: Int = 42
def f[A]()(implicit a: A): A
val f2: Int = f()
}
Run Code Online (Sandbox Code Playgroud)
当声明VAL f2,编译器能够推断出的功能隐式参数的类型f是Int因为该类型是相同的结果类型,和结果类型需要匹配的值的类型f2,这是Int.
然而,投入Ordering[A]混合:
def f[A]()(implicit a: A, m: Ordering[A]): A
val f2: Int = f()
Run Code Online (Sandbox Code Playgroud)
导致此编译错误:
不明确的隐含值:对象的类型为StringCanBuildFrom,类型=> scala.collection.generic.CanBuildFrom [String,Char,String]的对象Predef和方法$ conforms对象Predef的类型为[A] => <:<[A,A]匹配预期类型A.
如果我在调用时添加类型信息f(),它会编译:
val f2: Int = f[Int]()
Run Code Online (Sandbox Code Playgroud)
首先我遇到了隐式排序的情况,我认为它与Scala从左到右推断有关; 我认为它首先不能匹配返回类型然后推断(隐式)参数类型f.但后来我尝试了没有隐式排序的情况,看到它有效 - 它推断f必须参数化,Int因为返回类型必须是Int(因为f2是Int …
我正在使用下面的 JSON,
{
"@context": "Testingcontext",
"@type": "Testingtype",
"actor": "Testingactor"
}
Run Code Online (Sandbox Code Playgroud)
我正在 scala 中创建一个案例类:
case class LoggedInAction(`@context`: String,`@type`:String,actor:String)
Run Code Online (Sandbox Code Playgroud)
如何在案例类中使用特殊字符@,例如 , ?&另外,如何使用此类案例类字段?
我们以此为例:
import scala.reflect._
def get[T](list: List[Any])(implicit tag: ClassTag[T]) = {
list.flatMap {
case element: T => Some(element)
case _ => None
}
}
Run Code Online (Sandbox Code Playgroud)
我可以用来从列表中get()获取类型的值T(例如,get[String](list)将从该列表中给出所有字符串).
现在,我明白编译器会ClassTag[String]自动提供类型的值.我也明白这ClassTag是一个类型类,在幕后的某处,有一段代码可以说implicitly[ClassTag[T]].getRuntimeClass()或者其他什么.
但是如果是这样的话,为什么我们可以在没有类标签的情况下进行模式匹配(在这种情况下我们无法区分擦除类型)?我的意思是,它是如何实现的,如果我宣布一个隐含的参数(这是由编译器自动提供),我得到一个行为,但如果我不这么做,我得到一个不同的行为?
我有这些模型:
trait Vehicle[T <: Vehicle[T]] { def update(): T }
class Car extends Vehicle[Car] { def update() = new Car() }
class Bus extends Vehicle[Bus] { def update() = new Bus() }
Run Code Online (Sandbox Code Playgroud)
如果我获得了一个a Vehicle[Car]并且调用的实例update(),我会得到一个Car.由于Car扩展Vehicle[Car](或简单地说,Car 是一个 Vehicle [Car]),我可以安全地将结果的类型设置为Vehicle[Car]:
val car = new Car
val anotherCar = car.update()
val anotherCarAsVehicle: Vehicle[Car] = car.update() // works as expected
Run Code Online (Sandbox Code Playgroud)
但是,如果我想,比如说,将实例Car和Bus一起放入一个列表中,那么我必须将列表类型设置为Vehicle[_ <: Vehicle[_]](具有简单的列表Vehicle[_]并且update()在元素上调用会产生Any …
您认为打印出来的是什么?
val foo: String = "foo" + foo
println(foo)
val foo2: Int = 3 + foo2
println(foo2)
Run Code Online (Sandbox Code Playgroud)
回答:
foonull
3
Run Code Online (Sandbox Code Playgroud)
为什么?规范中是否有一部分描述/解释了这一点?
编辑:澄清我的惊讶 - 我确实意识到这foo是未定义的val foo: String = "foo" + foo,这就是为什么它有一个默认值null(整数为零).但这似乎不是很"干净",我在这里看到的意见与我一致.我希望编译器能阻止我做那样的事情.它在某些特定情况下确实有意义,例如在定义Streams本质上是懒惰的时候,但对于字符串和整数,我会期望由于重新分配给val或者告诉我我正在尝试使用未定义的值而阻止我,就像我写的那样val foo = whatever(假设whatever从未定义).
为了进一步复杂化,@ dk14指出此行为仅适用于表示为字段的值,并且不会发生在块内,例如
val bar: String = {
val foo: String = "foo" + foo // error: forward reference extends...
"bar"
}
Run Code Online (Sandbox Code Playgroud) 这是一个简单的雀科服务器,使用circe作为解码器:
import com.twitter.finagle.http.RequestBuilder
import com.twitter.io.Buf
import io.circe.generic.auto._
import io.finch._
import io.finch.circe._
case class Test(myValue: Int)
val api = post("foo" :: body.as[Test]) { test: Test => Ok(test) }
val bodyPost = RequestBuilder()
.url("http://localhost:8080/foo")
.buildPost(Buf.Utf8("""{ "myValue" : 42 }"""))
api.toService.apply(bodyPost).onSuccess { response =>
println(s"$response: ${response.contentString}")
}
// output: Response("HTTP/1.1 Status(200)"): {"myValue":42}
Run Code Online (Sandbox Code Playgroud)
将内容myValue改为Option开箱即用,给出与上述代码相同的结果.但是,将其更改为scalaz.Maybe:
import scalaz.Maybe
case class Test(myValue: Maybe[Int])
Run Code Online (Sandbox Code Playgroud)
结果是:
响应("HTTP/1.1状态(400)"):{"message":"正文无法转换为测试:CNil:El(DownField(myValue),true,false)."}
我该如何实现所需的编码器/解码器?