【问题标题】:Scala a better printlnScala 更好的 println
【发布时间】:2012-04-21 18:47:15
【问题描述】:

我经常发现自己在做这样的事情:

println(foo)

当我想做的时候:

println foo

编译器不允许这样做。

还有,println是满嘴的,我真的只想说:

echo foo

所以,在一个基础包对象中,我创建了 println 的 echo 版本:

def echo(x: Any) = Console.println(x)

很简单,有广泛的回声应用,很棒。

现在,我如何调用 echo 而无需将要打印的 Any 包装在括号中?

【问题讨论】:

  • @Debilski - 这是一个“我该怎么做”的问题,它引发了一些很棒的,如果可怕的话,黑客攻击。 The other question 是“为什么我不能”,其回答很好地解释了根本问题。我投票反对关闭。
  • @dave:你是对的。在发布那些可怕的黑客攻击之前很久就应该关闭它。
  • 然而,它不应该被关闭,因为问题是针对 println 本身,而不仅仅是无括号调用。
  • 是的,但话又说回来,它也可能会得到一个,“为什么我可以用 4 个字符表达相同的意图,但我总是输入 7 个字符?”

标签: scala echo parentheses println


【解决方案1】:
object ∊ {def cho(s: Any) {println(s)}}

∊cho "Hello world"

会拯救你的手指。

之所以有效,是因为 ∊ 是 Unicode Sm 集中的数学符号,因此算作 operator in Scala,因此放在字母数字字符旁边时不需要空格。

你也可以

object echo {def -(s: Any) {println(s)}}

echo-"Hello world"

IMO 效果很好。

几年后编辑:另一个几乎是解决方案,使用 StringContext:

implicit class PimpMyString(sc: StringContext) {
  def echo(args: Any*) = println(sc.raw(args: _*))
}

echo"Hello World"

【讨论】:

  • 很有趣,不过有点多 ;-) 直接 "echo(foo)" 很好,如果我不必输入整个内容, println(foo) 也可以(IDE 自动完成) ,从列表中选择实际上比直接敲出来要慢,顺便说一句)
  • 为什么不cout<<"Hello world"
  • 现在唯一的问题是弄清楚如何输入 比输入括号更快。
【解决方案2】:

定义

trait ShortCuts {
  def echo(x: Any) = Console.println(x)
  def trace[T](x: T): T = { echo(x); x }
  // ...
}

object ↬ extends ShortCuts

并且愉快地使用没有括号:

↬ echo "hello!"

【讨论】:

  • k,得到它,println,echo,无论如何,你必须有一个上下文才能在没有括号的情况下调用。
  • 不起作用:“:1: error: ';'预期但找到整数字面量。"
【解决方案3】:

Scalaz 有一个增强的Identity 类型,它有一个println 方法。

scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._

scala> val foo = 1
foo: Int = 1

scala> foo println
1

如果您不想依赖 scalaz,您可以创建自己的 pimped 身份并将其隐含在包对象中。

【讨论】:

  • 对,实际上,在从 PreDef 克隆 println 之前,我是从隐式开始的。查看我更新的替代方案
【解决方案4】:

您想要实现的目标在 Scala 中是不可能实现的。

括号只能在所谓的无点语法中删除,其中您必须在函数左侧有一个上下文对象,因此在您的情况下,您只能实现以下内容,这有点不反正感觉:

Console println x

虽然我可以理解您为什么要实现这一点,可能更好地考虑其他语言的更简单的语法结构,但我建议坚持标准的 Scala 做事方式,所以只需使用 println(x) 或考虑其他语言。为这样一个基本的标准功能创建一个委托方法肯定会给您在将来的项目管理中带来麻烦 - 所以绝对是 echo 方法的“不可以”。

对于这样的情况有句老话:在罗马,做罗马人做的事。

【讨论】:

  • 谢谢,这里没有危险。我没有委托任何东西,开销为零,只是基础包对象中的一个方法。如果将来 Scala/Java 与 Console.println() 以外的其他东西一起使用,那么有一个巨大的地方可以做出改变。至于基于我对 println 替代方案的渴望考虑其他语言,不知道该说什么。 Scala 完全和完全摇滚,基于他们使用 echo 的事实,我应该使用 PHP 而不是 Scala 吗? ;-)
  • @virtualeyes JVM 破坏向后兼容性的可能性接近于零。有些人在学习您对标准 API 的自定义之前,更有可能使用您的代码不了解正在发生的事情。一段时间后,您自己甚至很有可能难以理解该代码。此外,在习惯了自己的 API 之后,您会发现更难理解不是您编写的代码。如果你不得不在一个人中工作,那么团队肯定不会非常欣赏这样的事情。
  • @virtualeyes 在其他语言中,如果您正在寻找具有出色语法的功能性静态语言,您可以考虑 Haskell,如果您正在寻找具有良好语法的流行语言,您可以考虑使用 Python(或者如果您的目标是 Jython JVM)。还有一个新的 Kotlin,它是一种改进和简化的 Scala——因为它是 JetBrains 的产品,它肯定会变得流行,并且将有一个极好的 IDE 支持。我刚刚提到的语言在各个领域都优于 Scala。我什至不会建议接触 PHP。
  • 是的,团队方面是一个很好的观点,Java 互操作/熟悉/约定也是如此。通常我不会在意,但 println 语句是如此常见的开发任务,我愿意尝试使用更短的形式 echo。不用说,我是一个单人表演,从设计到数据库再到代码,所以打扰团队成员不会成为问题(无论如何现在都不是)
  • 您可以将 echo 拉到 Any 上并绕过对 parens 的需求
【解决方案5】:

这里有一组有趣的响应,从无法完成到可以完成,使用这种符号相关的 hack 或使用这种依赖 (Scalaz)

@Nikita 正确地指出,人们可以很容易地在他们的 IDE 中添加一个 sn-p(如果你是这样滚动的)来执行 println “legwork”。虽然这是真的,但您通常必须停止输入才能执行 ctrl-p-r 或您决定使用的任何组合键,这会破坏您的流程,IMO。因此,本着创造“更好”的 println 的精神,这是我的看法:

创建一个基础包对象,您的子包(模型、视图、dao 等)将从(基本上是您自己的 PreDef)继承

package com
package object company {

  // echo(foo)
  def echo(x: Any) = Console.println(x)

  // foo.echo   
  class AnyProvidesEcho(x: Any) { def echo = Console.println(x) }
  @inline implicit def any2Echo(x: Any) = new AnyProvidesEcho(x)
}

用法:

val list = List(1,2,3)
val string = "c'est beacoup mieux mit butter"

list foreach echo
echo(string)
string.echo

【讨论】:

  • 当你使用它时,你应该添加一个trace,它会打印并返回值。
猜你喜欢
  • 1970-01-01
  • 2011-11-05
  • 2011-01-27
  • 2015-03-18
  • 2020-09-13
  • 2011-11-16
  • 2019-10-21
  • 2017-11-30
  • 2012-06-24
相关资源
最近更新 更多