简体   繁体   English

Scala:隐式背后的魔力

[英]Scala: the magic behind implicits

I've been playing with "implicits" in Scala all weekend but I'm still having trouble grasping the whole concept. 我整个周末都在Scala中玩“隐性游戏”,但是我仍然难以理解整个概念。 This question is based off of my previous one . 这个问题是基于我以前的问题 I decided to take things a step further with: 我决定进一步采取以下措施:

def a(b: String)(implicit c: () => String = () => "") = {
    println(s"$b - up next is "+c());c();b
}

implicit def conv(s: => String) = () => s

That's when things start to get a little whacky: 那时候事情开始变得有些古怪:

scala> a("1")(a("2")(a("3")))
3 - up next is 
2 - up next is 3
3 - up next is 
1 - up next is 2
3 - up next is 
2 - up next is 3
3 - up next is 

The basic idea here is to get each line to reference each other like so: 这里的基本思想是使每一行相互引用,如下所示:

1
2 from 1
3 from 2
4 from 3

  1. Correct me if I'm wrong, but using implicit in this case will insert a string when one is found..? 如果我错了,请纠正我,但是在这种情况下使用隐式将在发现一个字符串时插入一个字符串。 I'm not sure why it's printing out 7 lines instead of 3 我不确定为什么要打印7行而不是3行

  2. What am I doing wrong here? 我在这里做错了什么? I'm starting to think that using implicits gives me less control 我开始认为使用隐式会减少我的控制

  3. Not as important, but is there a more safe way to go about implicits? 不是很重要,但是有没有更安全的隐式方式? A way that allows me to see exactly what's going on? 一种让我确切了解正在发生什么的方式?

You are invoking c twice, instead only invoke it once: 您两次调用c ,而只调用一次:

def a(b: String)(implicit c: () => String = () => "") = {
  println(s"$b - up next is " + c())
  b
}

Which then produces: 然后产生:

3 - up next is 
2 - up next is 3
1 - up next is 2

Even though a("1") gets invoked first, it has to invoke the () => String it is passed before producing any output. 即使首先调用a("1") ,它也必须在产生任何输出之前调用它传递的() => String As a result, a("3") is the first one to produce output. 结果, a("3")是产生输出的第一个。

You need to turn this around, and have a("2") tell a("3") that it is being invoked from a("2") : 您需要解决这个问题,并让a("2")告诉a("3")a("2")调用它:

def a(current: String, next: String => Unit = _ => ())(prev: String) = {
  println(s"$current from $prev")
  next(current)
}

And invoke it like: 并像这样调用它:

a("1", a("2", a("3")))("nothing")

Which produces: 产生:

1 from nothing
2 from 1
3 from 2

To answer three of your points: 要回答您的三点:

  1. No, your implicit parameter takes a () => String , not a String . 不,您的隐式参数采用() => String ,而不是String
  2. See above, you don't need implicits here. 参见上文,您在这里不需要隐式。
  3. Read up on the -Xlog-implicits , -Xlog-implicit-conversions and -Xprint:all options. 阅读-Xlog-implicits-Xlog-implicit-conversions-Xprint:all选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM