【问题标题】:In Ruby, is there an equivalent method of printNl as in Smalltalk?在 Ruby 中,是否有与 Smalltalk 中等效的 printNl 方法?
【发布时间】:2015-12-16 22:48:25
【问题描述】:

如果Ruby受到Smalltalk的影响很大,不知道Ruby中是否有类似Smalltalk中的printNl的等效方法?

我非常着迷,在 Smalltalk 中,你实际上有一些东西,比如一个字符串,然后你将消息 printNl(用于使用换行符打印)发送到字符串对象。它是以 OOP 方式进行的,而不是 p objputs obj 的程序方式。

我只找到了Objectdisplay 方法,它没有displayNl 替代方法。 Ruby 里面有吗?

只是为了好玩我做了以下,但我想知道如果它污染了 Object 类会不会不好:

class Object
  def displayNl
    self.display
    "\n".display
  end
end

"hello world".displayNl
5.displayNl
3.14.displayNl
Time.now.displayNl
Time.displayNl
Fixnum.displayNl
[1,3,5].displayNl
{foo: "bar"}.displayNl

-----------------

$ ruby try.rb 
hello world
5
3.14
2015-12-16 14:44:09 -0800
Time
Fixnum
[1, 3, 5]
{:foo=>"bar"}

【问题讨论】:

  • 需要考虑的是 Ruby 不是 SmallTalk。虽然它们有相似之处,但试图让一种语言使用另一种语言的语法或方法会导致代码不直观,尤其是对于那些在你编写完代码后必须使用它的人来说。维护和善待同事对于代码的可行性非常重要。我建议采用 Ruby 自己为 Ruby 代码做事的方式,并在编写代码时坚持 SmallTalk 的方式。您会发现,随着您使用更多语言工作,来回跳转变得更加容易。否则你会发疯的。像我们大多数人一样。
  • Smalltalk 也不是 SmallTalk ;)
  • @theTinMan 实际上,Ruby 跟随 Smalltalk 制作了所有的值对象,所以如果 object 打印出自己是有意义的,就像大约 50 年前的做法一样。当然,如果 Ruby 没有那样做并且每个人都在效仿,那不就是这样吗……但是如果有 display_nl,那么我不明白为什么使用它会有负面影响影响其他不熟悉它的人
  • @LeandroCaniglia 所以它是 JavaScript 和 Smalltalk 呵呵...

标签: ruby smalltalk


【解决方案1】:

不知道污染Object类会不会不好

没错!为什么将自己打印到控制台是对象的责任?由控制台负责打印字符串不是更有意义吗?

这正是它在 Ruby 中的工作方式:IO#print(和IO#puts)允许IO 对象将字符串打印到自身,#to_s 协议允许任何对象将自己表示为字符串。

Kernel#print(和Kernel#putsKernel#p)只是一种方便的方法,基本上是这样的:

module Kernel
  private def print(*args)
    $>.print(*args)
  end
end

$> 是默认输出流,启动时与$stdoutSTDOUT 相同,但可以重新分配。它是IO 的一个实例。

IO#print,反过来,看起来像这样:

class IO
  def print(*args)
    args.map(&:to_s).each do |str|
      some_internal_io_method_to_print_strings(str)
      # in a C-based Ruby implementation probably calling fputs from the libc
    end
  end
end

所以,换句话说,Ruby 以“OO 方式”。有IO 对象知道如何打印字符串,还有#to_s 方法允许对象将自己表示为字符串。


换句话说:我认为Object#display 是一个错误。

您可能会注意到,在 YARV 中,它实际上是在 io.c 中定义的,而不是在 object.c 中定义的,因此即使作者似乎也同意此功能属于 IO,而不是 Object

这是一个比较老的方法,the oldest trace我能找到的是this commit from January, 1999,好像是来自version 1.3.1 release。这里,其实是defined in Kernel, not Object

在此之前,踪迹迷失在 CVS2SVN 转换的迷雾中。

【讨论】:

  • 但是如果你说,为什么一个字符串应该知道如何打印自己,那么你可能会说,为什么一个形状或圆形或矩形应该知道如何绘制自己,所以rectangle.drawview.draw所有人都不应该那样做,它应该是window.draw(view),然后在window.draw(),你将使用case 语句在绘制视图或文本框或按钮之间切换,然后多态性不起作用。跨度>
  • 我不会标记它(我实际上赞成),但这在技术上不是“不是答案”吗?
【解决方案2】:

没有这样的等价物。您的示例是一个有效的实现,尽管可能不是 Ruby 中最惯用的。

Ruby 方法使用snake_case 而不是camelCase。此外,在您的方法中使用puts 会更简单,因为puts 会自动附加一个换行符。

class Object
  def display_nl
    puts self
  end
end

在 IRB 中键入长行后,我经常希望有这样的方法。我通常不会将光标移回行首以在所有内容前面添加puts,而是通常只在下一行使用puts _。像这样的后缀方法会很可爱。

【讨论】:

  • 我使用display 只是为了使其具有相同的行为...不确定puts 是否与display 具有相同的所有内容...顺便说一句,您知道,在至少在 Mac 和 Linux 上,您可以按 Ctrl-a 并且光标会移动到行首?
  • 我知道 Ctrl-a。不仅仅是走到队伍的最前面,还有更多的事情要做。有时您需要将整个内容放在括号中,因为您使用了{} 内联块语法,这会弄乱puts。在任何情况下,只要有一个可以坚持到底的方法会更容易,就像你在这里建议的那样。
  • 是的,如果有.display_nl,那么多态性是不是真的可以工作,例如如果应用程序想要在控制台中打印出一些东西并将该字符串发送到 GUI在它正在绘制的图表顶部最多显示 5 行状态的窗口...或类似的东西,然后重新定义 display 一切都会正常工作
  • 提交功能请求:转到bugs.ruby-lang.org/projects/ruby-trunk/issues/new 并注册(如果您尚未注册)。更好的是,首先创建补丁并将其添加到您提交的问题跟踪器中。我会支持它。
猜你喜欢
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 2015-09-08
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 2012-03-17
  • 2011-02-18
相关资源
最近更新 更多