Squeak Smalltalk- 如何使 "Transcript show" 打印更多东西?

Squeak Smalltalk- How to make to "Transcript show" print more things?

我正在使用 Smalltalk 输入 Transcript window 1-9 乘法 table .

这是我的代码:

1 to: 9 do: [:i|
    1 to: i do: [:j|
        Transcript show: j.
        Transcript show: ' * '.
        Transcript show: i.
        Transcript show: ' = '.
        Transcript show: j * i.
        Transcript show: '  '.
        ].
    Transcript show: ' '; cr.
    ].

可以看出,上面的代码虽然工作正常,但看起来远非美观和简洁。

我曾希望写这样的东西:

Transcript show: j '*' i '=' j * i.

不幸的是,他们错了。我记得 C 有一个很好的方法来处理我的那个问题。

喜欢,printf("%d * %d = %d ", j, i, j * i);

在这种情况下,是否有更优雅的方法使 Smalltalk 代码更优雅?


Peter 解决了这个问题。谢谢。

更多问题:

如何在 Smalltalk 中显示“转义字符”。

我知道在 C 中,printf("%d * %d = %d\n", j, i, j * i); 看起来不错。

但是在 Smalltalk 中,Transcript show: ('{1} * {2} = {3}cr.' format: {i. j. i * j}). 不行。

我该如何解决?

我建议进行两项更改:

  1. 让代码与通用 Stream 一起使用,并将其与 Transcript

    一起使用
    dumpTableOn: aStream
       <your code here>
    

    然后评估

    self dumpTableOn: Transcript
    
  2. 用两种方法拆分代码

    dumpTableOn: aStream
      1 to: 9 do: [:i | 
        1 to: i do: [:j |
            self dump: i times: j on: aStream.
            aStream space].
        aStream cr]
    
    
    dump: i times: j on: aStream
      aStream
        nextPutAll: j asString;
        nextPutAll: ' * ';
        nextPutAll: i asString;
        nextPutAll: ' = ';
        nextPutAll: (j * i) asString
    

这是上述方法的简化版本

    dump: i times: j on: aStream
      aStream
        print: j;
        print: ' * ';
        print: i;
        print: ' = ';
        print: j * i

请注意 #print: 不需要我们先将参数转换为 String

另请注意,级联不会创建中间体 Strings,而表达式

j asString, '*', i asString, '=', (j*i) asString

创建 4 个中间字符串(每个 #, 一个)。没什么大不了的,只是我们不会充分利用 Stream 协议,该协议的全部意义在于使客户端无需在其端连接事物。

字符串扩展

Like, printf("%d * %d = %d ", j, i, j * i);

有一些格式化选项,但没有什么比得上 printf (afaik)

'<1p> * <2p> = <3p>' expandMacrosWith: 2 with: 3 with: 2 * 3.
"same as the following:"
'<1p> * <2p> = <3p>' expandMacrosWithArguments: {2. 3. 2 * 3}.

'{1} * {2} = {3}' format: {2. 3. 2 * 3}.

所以你的代码可以重写如下

1 to: 9 do: [ :i |
    1 to: i do: [ :j |
        Transcript
            show: ('{1} * {2} = {3}' format: {j. i. j * i});
            show: ' '
    ].
    Transcript show: ' '; cr.
].

更新有关:转义字符

字符串中没有转义字符,唯一的例外是单引号 ('),您 "escape" 将它加倍 ('It''s doubled!')

要写新行或制表符,您可以

  1. 将其输入字符串

    a := 'two lines'. (注意 Whosebug 用空格替换了制表符 :/)

  2. 加入字符串

    b := 'two', String cr, String tab, 'lines'.

  3. 告诉写入流添加它

    c := String streamContents: [ :stream | stream << 'two'; cr; tab; << 'lines' ].

  4. 使用扩展宏

    d := 'two<n><t>lines' expandMacros.

a = b = c = d

如果您更喜欢使用类似于 printf 的东西,Squeak 有 expandMacrosWith: 方法系列(浏览 class 字符串)。

你的例子可以写成:

1 to: 9 do: [:i|
    1 to: i do: [:j|
        Transcript show: ('<1p> * <2p> = <3p>   ' expandMacrosWith: j with: i with: j*i)
        ].
    Transcript show: ' '; cr.
    ].

expandMacros... 的接收器包含尖括号之间的占位符。在Squeak中找不到相关文档,以下摘自Dolphin Smalltalk中等效实现的注释:

Expand the receiver with replacable arguments.
e.g.
    'Hello <D><N><1P> <D>' expandMacrosWithArguments: #('World' 1).
    'Hello <2?Good:Bad> <1S>' expandMacrosWithArguments: #('World' false)

<nD> expands the nth parameter using it's #displayString
<nP> expands the nth parameter using it's #printString
<nS> expands the nth parameter treating it as a <String>
<N> expands as a newline combination
<T> expands as a TAB
<n?xxxx:yyyy> if the nth parameter is true expands to 'xxxx' else 'expands to yyyy'