好吧,也许我应该在这里解析两个愿望。
我记得当到达setSendTimeout(0)
部分的时候,我会使用像implicitly[Socket]
这样的东西。
new ZContext(1) {
createSocket(ZMQ.PUB).setSendTimeout(0).//RATS!
}
我还想到了一种更通用的方法,那就是(用伪代码术语):
这就是你在某个时间点包装T
的引用而不复制它的方法,这样你可以向前移动,在潜在的状态从任何值的变化后梳理出引用的状态表达使用它。
如果可以将其视为map
map
map
从T
到最终结果的链,那么很容易追加/应用一个值 - 再次map
......
这是一个激励人心的例子。
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
logger.info("Initializing ZMQ context.")
val context = new ZContext(1)
logger.info(s"Binding PUB socket to ${endpoint}")
val socket = {
val s = context.createSocket(ZMQ.PUB)
s.setSendTimeOut(0)
s.bind(endpoint)
s
}
在那里看socket
。出于某种原因,感觉比我需要的更加丑陋,但是setters
没有返回像setSendTimeOut
这样的事实的结果。
我通常会尝试按如下方式对其进行改进:
new ZContext(1) {
createSocket(ZMQ.PUB).setSendTimeout(0).//RATS!
}
答案 0 :(得分:2)
这是@Dima的答案版本。再次设置:
trait Instance {
def createPort(): Port
}
trait Port {
def makeSpecial(): Unit
def bindTo(address: Any): Unit
}
trait Provider {
def getTheInstance(i: Int): Instance
}
现在的诀窍:
implicit class InstanceOps(i: Instance) {
def withCreatePort(fun: (Unit => Port) => Any): Port = {
val res = i.createPort()
fun(_ => res)
res
}
}
如果您将implicit
修饰符添加到传递给withCreatePort
的函数的参数中,那么您将导入"导入"隐式转换:
trait ConnectTest extends Provider {
getTheInstance(2).withCreatePort { implicit p =>
().makeSpecial().bindTo("foo")
}
}
这可能更危险,因为您有Unit
到Port
的隐式转换,尽管它是本地封装的。这是通用的,因为Connect
是通用的。
这个技巧可能太聪明,也很难被一些外面的人阅读你的代码所理解。
答案 1 :(得分:1)
是的,您可以创建两个包装器,一个包含withCreatePort
,另一个包含返回this
的端口方法的变体:
trait Instance {
def createPort(): Port
}
trait Port {
def makeSpecial(): Unit
def bindTo(address: Any): Unit
}
class PortOps(p: Port) {
def makeSpecial() : this.type = { p.makeSpecial() ; this }
def bindTo(address: Any): this.type = { p.bindTo(address); this }
}
implicit class InstanceOps(i: Instance) {
def withCreatePort[A](fun: PortOps => A): A = fun(new PortOps(i.createPort()))
}
示例:
trait Provider {
def getTheInstance(i: Int): Instance
}
trait Plain extends Provider {
val instance = getTheInstance(2)
val port = instance.createPort()
port.makeSpecial()
port.bindTo("foo")
}
trait Rich extends Provider {
getTheInstance(2).withCreatePort { p =>
p.makeSpecial().bindTo("foo")
}
}
问题是这项努力是否值得。您还可以试用import
:
trait Import extends Provider {
val instance = getTheInstance(2)
val port = instance.createPort()
locally {
import port._
makeSpecial(); bindTo("foo")
}
}
答案 2 :(得分:1)
我不确定你要使用这个Zipped
的东西......但是你在问题的开头所描述的(假设该片段末尾的port
是拼写错误,并且你真的想要返回instance
)可以用这样的东西来完成:
object Taps {
implicit class Tap[T](t: T) extends Anyval {
def tap(f: T => Unit) = { f(t); t }
}
}
然后你可以写:
import Taps._
val instance = getTheInstance(2).tap {
_.createPort
.makeSpecial
.bindTo(...)
}
这是你在找什么?