假设我想foo在A我控制之外的现有类型上提供方法.据我所知,在Scala中执行此操作的规范方法是实现从A实现的某种类型的隐式转换foo.现在我基本上看到两个选项.
为此目的定义一个单独的,甚至是隐藏的类:
protected class Fooable(a : A) {
def foo(...) = { ... }
}
implicit def a2fooable(a : A) = new Fooable(a)
Run Code Online (Sandbox Code Playgroud)定义内联匿名类:
implicit def a2fooable(a : A) = new { def foo(...) = { ... } }
Run Code Online (Sandbox Code Playgroud)变体2)肯定是较少的样板,特别是当发生许多类型参数时.另一方面,我认为它应该创建更多的开销,因为(概念上)每个转换创建一个类,而不是1)中的一个全局类.
有一般指导方针吗?没有区别,因为编译器/ VM摆脱了2)的开销?
假设我有一个名为LongArrayWritable的类型,它是一个Longs数组的盒装表示.我有隐式定义,在这些类型之间转换:
implicit def boxLongArray(array: Array[Long]) : LongArrayWritable { /*elided*/}
implicit def unboxLongArray(array: LongArrayWritable) : Array[Long] { /*elided*/}
Run Code Online (Sandbox Code Playgroud)
现在,我也有一些暗示,它们以通用形式在java.lang.Iterable和scala.collection.List [X]之间进行转换:
implicit def iterator2list[X](it : java.lang.Iterable[X]) : List[X] { /* elided */ }
implicit def list2iterator[X](list : List[X]) : java.lang.Iterable[X] { /* elided */ }
Run Code Online (Sandbox Code Playgroud)
使用这些定义,scala编译器可以推断java.lang.Iterable [LongArrayWritable]和List [Array [Long]](相当于iterator2list(iterator).map(unboxLongArray(_)))之间的隐式转换,或者这超出了implicits的功能,因此需要它自己的(显式?)隐式定义?
谢谢,
蒂姆
您好:我最近一直在学习Scala(我的相关背景主要是在C++模板中),而且我遇到了一些我目前对Scala不了解的事情,这让我感到疯狂.:(
(另外,这是我在StackOverflow上的第一篇文章,我注意到大多数真正令人敬畏的Scala人似乎都在闲逛,所以如果我对这个机制做了一些非常愚蠢的事情,我真的很抱歉.)
我的具体困惑与隐式参数绑定有关:我提出了一个特定的情况,其中隐式参数拒绝绑定,但具有看似相同的语义的函数确实如此.
现在,它当然可能是一个编译器错误,但鉴于我刚开始使用Scala,我已经遇到某种严重错误的可能性非常小,我期待有人解释我做错了什么.,P
我已经完成了代码并将其削减了很多,以便提出一个不起作用的单个示例.不幸的是,这个例子仍然相当复杂,因为问题似乎只发生在概括中.:(
1)简化的代码不能按我预期的方式工作
import HList.::
trait HApplyOps {
implicit def runNil
(input :HNil)
(context :Object)
:HNil
= {
HNil()
}
implicit def runAll[Input <:HList, Output <:HList]
(input :Int::Input)
(context :Object)
(implicit run :Input=>Object=>Output)
:Int::Output
= {
HCons(0, run(input.tail)(context))
}
def runAny[Input <:HList, Output <:HList]
(input :Input)
(context :Object)
(implicit run :Input=>Object=>Output)
:Output
= {
run(input)(context)
}
}
sealed trait HList
final case class HCons[Head, Tail <:HList]
(head :Head, tail :Tail)
extends HList
{
def ::[Value](value :Value) = …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个转换库,用于将一些scala类型转换为HTML表示.比方说,我想要执行List(1,2).toHtml和获取<ul><li>1</li><li>2</li></ul>,作为一个String.
到目前为止,我已经编写了一组隐式转换,它们可以很好地检测结果类型并应用正确的结果toHtml.
让我展示一个示例:
object Conversions {
implicit def fromIterable[A](l : Iterable[A]) = new Object {
def toHtml = <ul> { l.map{ e => <li>{ e }</li> } } </ul> toString
}
}
import Conversions._
Run Code Online (Sandbox Code Playgroud)
有了这段代码,每当我问编译器时,List(1,2).toHtml我得到正确的转换.就像任何其他Iterableval一样.
我的问题和问题是如何递归地使用这个toHtml转换?因为如果我输入List( List(1,2), List(3,4) ).toHtml我想要获得<ul> <li><ul><li>1</li><li>2</li></ul></li> <li><ul><li>3</li><li>4</li></ul></li> </ul>,toHtml转换应用递归地应用于输入的每个元素Iterable.
我试图将toHtml定义更改为def toHtml = <ul> { l.map{ e => <li>{ e.toHtml }</li> } } </ul> toString …
我正在尝试使用Scala和spray-client编写一个简单的HTTP客户端.我的客户基于Spray文档上给出的示例.
我的问题是该示例是创建一个新的隐式 ActorSystem即
implicit val system = ActorSystem()
Run Code Online (Sandbox Code Playgroud)
但我希望我的客户端可以重用,而不是创建一个新的ActorSystem.
这是我的代码的要点.
trait WebClient {
def get(url: String)(implicit system: ActorSystem): Future[String]
}
object SprayWebClient extends WebClient {
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
def get(url: String): Future[String] = {
val r = pipeline (Get("http://some.url/"))
r.map(_.entity.asString)
}
}
Run Code Online (Sandbox Code Playgroud)
但我得到两个关于implicits的编译器错误
implicit ActorRefFactory required: if outside of an Actor you need an implicit ActorSystem, inside of an actor this should be the implicit ActorContext WebClient.scala ...
Run Code Online (Sandbox Code Playgroud)
和
not enough arguments for …Run Code Online (Sandbox Code Playgroud) 我正在使用play框架,并有一个抽象类:
abstract class Base{...}
Run Code Online (Sandbox Code Playgroud)
在伴随对象中有自己的隐式JSON编写器
object Base {
implicit val baseWrites: Writes[Base] = (...)(unlift(Base.unapply))
}
Run Code Online (Sandbox Code Playgroud)
我是这个抽象类的子类:
case class SubClass{...}
Run Code Online (Sandbox Code Playgroud)
在其伴随对象中也有自己的隐式JSON编写器
object SubClass {
implicit val subClassWrites: Writes[SubClass] = (...)(unlift(SubClass.unapply))
}
Run Code Online (Sandbox Code Playgroud)
当我尝试使用Json.toJson(SubClass)序列化子类对象时,我收到一个错误:
[error] both value subClassWrites in object SubClass of type => play.api.libs.json.
Writes[models.SubClass]
[error] and value baseWrites in object Base of type =>
play.api.libs.json.Writes[models.Base]
[error] match expected type play.api.libs.json.Writes[models.SubClass]
[error] Ok(Json.toJson(SubClass.find(id)))
Run Code Online (Sandbox Code Playgroud)
有没有办法消除歧义?
我不喜欢将隐式参数引入我的代码中,所以在我使用它们时我想封装它们的用法.所以我试图定义一个对象,它既包含对异常处理的spray-json的调用,又包含每个模型类的默认隐式JsonFormats.但是,隐式参数不会被解析,除非它们被导入到客户端,调用代码,这正是我不想要它们的地方.这是我到目前为止(它没有解决隐式格式化程序),有没有办法让我得到我想要的工作?
package com.rsslldnphy.json
import com.rsslldnphy.models._
import spray.json._
object Json extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
def parse[T](s:String)(implicit reader: JsonReader[T]): Option[T] = {
try { Some(JsonParser(s).convertTo[T]) }
catch { case e: DeserializationException => None }
}
}
Run Code Online (Sandbox Code Playgroud)
NB.JsonFormat是一种JsonReader
编辑:这是我根据@ paradigmatic的第二个建议(我无法工作,我仍然得到Cannot find JsonReader or JsonFormat type class for T)写的.我错过了什么吗?
object Protocols extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
}
object Json {
def parse[T](s:String): Option[T] = { …Run Code Online (Sandbox Code Playgroud) 是否有一些Groovy替代方案来表达如下内容:
def doSomethingWith(implicit i:Int) = println ("Got "+i)
implicit var x = 5
doSomethingWith(6) // Got 6
doSomethingWith // Got 5
x = 0
doSomethingWith // Got 0
Run Code Online (Sandbox Code Playgroud)
更新:请参阅此处的后续问题:Groovy等效于Scala隐式参数 - 扩展
T <:< U在-Ywarn-unused传递给编译器时,在Scala中编译包含类型证据参数的程序(例如)可能会引起警告。特别是在类型证据参数用于验证使用幻像类型编码的约束的情况下,很可能会发生此警告。
例如,在此处编译文件:https : //github.com/hseeberger/demo-phantom-types/blob/master/src/main/scala/de/heikoseeberger/demophantomtypes/Hacker.scala返回以下内容:
# scalac -Ywarn-unused Hacker.scala
Hacker.scala:42: warning: parameter value ev in method hackOn is never used
def hackOn(implicit ev: IsCaffeinated[S]): Hacker[State.Decaffeinated] = {
^
Hacker.scala:47: warning: parameter value ev in method drinkCoffee is never used
def drinkCoffee(implicit ev: IsDecaffeinated[S]): Hacker[State.Caffeinated] = {
^
two warnings found
对我来说很明显,该参数ev实际上不是在运行时必需的,但在编译时该参数很有用。有什么方法可以指示编译器忽略这种情况,同时在其他情况下仍对未使用的函数参数提出警告?
例如,我认为指示编译器忽略类的隐式参数<:<或=:=将解决此问题,但是我不确定如何实现。
scala compiler-warnings implicits phantom-types unused-variables
我发现自己不止一次写下以下丑陋的模式:
class Something[A, B](implicit ev: A =:= B = null) {
...
def doStuff {
if (ev == null) ... // know that A is not the same as B
else ... // safely assume A is equal to B
}
}
Run Code Online (Sandbox Code Playgroud)
更糟糕的是,何时ev != null,我有时会写出诸如此类的异端邪说someB.asInstanceOf[A].