かけ算の順序の昔話

算数教育について気楽に書いていきます。

Perl,Ruby,Pythonにおける文字列のたし算およびかけ算

Rubyによるテキストデータ処理 (講座ITと日本語研究)』p.30に,「文字列についても,数値の足し算と掛け算に相当する操作が可能である」と記し,いくつか演算の例を示しています.
Ubuntu 12.04のPerlRubyPythonで確認してみました.なお,煩雑さを避けるため,文字列は英語にしています.またスクリプトファイルを書くのではなく,インタラクティブな各処理系で一つ一つ実行させました.

Perl(失敗)

http://haraken.info/wordpress/?p=9によると,perl -de 1でできます.

$ perl -v

This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi
(以下略)

$ perl -de 1

Loading DB routines from perl5db.pl version 1.32
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(-e:1):   1
  DB<1> print "gaku" + "buru"
0
  DB<2> print "gaku" * 2 + "buru" * 2
0
  DB<3> print ("gaku" + "buru") * 2
0
  DB<4> print "gaku2" + "buru2"
0
  DB<5> print "2gaku" + "2buru"
4

最後の例を除いて,出力はいずれも「0」です.文字列に対して算術演算を適用しようとすると,数値に変換されるからです.

Perl(成功)

それで終わるわけにはいきません.久しぶりのPerlプログラミングの記憶を呼び覚ますと,文字列の結合は.だったはずです.そして調べたところ,繰り返しにはxが演算子として使えます.
仕切り直しして,動作を確認します.

$ perl -de 1

Loading DB routines from perl5db.pl version 1.32
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(-e:1):   1
  DB<1> print "gaku" . "buru"
gakuburu
  DB<2> print "gaku" x 2 . "buru" x 2
gakugakuburuburu
  DB<3> print ("gaku" . "buru") x 2
gakuburu
  DB<4> print(("gaku" . "buru") x 2)
gakuburugakuburu
  DB<5> print 2 x "gaku"

  DB<6> print "gaku" x 2
gakugaku

DB<5>とDB<6>の結果から,「文字列 x 回数」はOKだけど「回数 x 文字列」は何も出力しない(ただしエラーでもない)というのが分かりました.またDB<2>のところから,数値に対する加算と乗算と同様に,xは.よりも優先順位が高いことが確認できます.

Ruby

irbを使います.printをつけることなく,式を書けば,次の行で評価値を教えてくれます.

$ irb -v
irb 0.9.5(05/04/13)
$ ruby -v
ruby 1.8.7 (2011-06-30 patchlevel 352) [x86_64-linux]
$ irb
irb(main):001:0> "gaku" + "buru"
=> "gakuburu"
irb(main):002:0> "gaku" * 2 + "buru" * 2
=> "gakugakuburuburu"
irb(main):003:0> ("gaku" + "buru") * 2
=> "gakuburugakuburu"
irb(main):004:0> 2 * "gaku"
TypeError: String can't be coerced into Fixnum
        from (irb):4:in `*'
        from (irb):4

最後は,「数*文字列」はエラーと思えば良さそうです.腕利きのRubyistなら,エラーにならないようなインスタンスメソッドを(再)定義できそうにも思いますが….

Python

引数なしのpythonで,インタラクティブモードになってくれます.

$ python
Python 2.7.3 (default, Apr 20 2012, 22:39:59)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "gaku" + "buru"
'gakuburu'
>>> "gaku" * 2 + "buru" * 2
'gakugakuburuburu'
>>> ("gaku" + "buru") * 2
'gakuburugakuburu'
>>> 2 * "gaku"
'gakugaku'
>>> "gaku" * 2
'gakugaku'

これはすごい.Pythonでは,「文字列*数」だけでなく「数*文字列」も対応してくれました.
あえてエラーを出させるなら…

(続き)
>>> "gaku" * 2.5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'

まあ,小数倍は無理でしょうね.
もし"gaku"の2.5倍の文字列として"gakugakuga"を作りたければ,整数部と小数部に分けて部分文字列を求め,足すこと*1でしょうか.

*1:Pythonでの書き方は思い浮かびませんでしたが,Rubyだと,s = "gaku"とした上で,s * 2 + s[0, s.length * 0.5]と書けば,期待する文字列となります.