Squeak Smalltalk-如何制作"成绩单节目"打印更多东西?

时间:2017-11-06 07:15:44

标签: smalltalk squeak

我正在使用Smalltalk在Transcript窗口中输入1-9乘法表。

这是我的代码:

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代码更优雅?

彼得解决了这个问题。感谢。

更多问题:

如何显示"逃脱角色"在Smalltalk。

我知道在C中,printf("%d * %d = %d\n", j, i, j * i);似乎很好。

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

我该如何解决?

3 个答案:

答案 0 :(得分:3)

字符串扩展

  

喜欢,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.
].

更新re:转义字符

Strings中没有转义字符,唯一的例外是单引号(&#39;),你可以逃脱&#34;加倍('It''s doubled!'

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

  1. 将其输入字符串

    a := 'two lines'. (请注意,StackOverflow用空格替换了标签:/)

  2. 加入字符串

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

  3. 告诉写入流添加

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

  4. 使用expandMacros

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

  5. a = b = c = d

答案 1 :(得分:2)

我建议做两处修改:

  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
    
  3. 以上是上述方法的详细版本

        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协议,其唯一的目的是让客户免于连接它的需要。

答案 2 :(得分:1)

如果你更喜欢使用与printf类似的东西,Squeak有expandMacrosWith:方法系列(浏览类String)。

你的例子可以写成:

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'