ミュータブルな Bignum とコンテキストの変更


お呼びでない…とは知りつつも、Squeak Smalltalk だとどうなのかなーと考えたので。


Squeak Smalltalk では、Ruby と違い、Ruby でいうところの Bignum にあたる LargePositiveInteger と LargeNegativeInteger (〜のインスタンス。正確には)はミュータブルなので、こんなふうなことができます。

| i |
i := 12345678987654321.
(1 to: i digitLength) inject: 111111111 into: [:result :each |
	i digitAt: each put: result \\ 256. result // 256].
^{i. i * 111111111}
=> #(111111111 12345678987654321)


加えてコンテキストをたぐって、耳から手を突っ込んで奥歯をがたがた言わせることも可能です。

| i |
i := 12345678987654321.
thisContext tempAt: 1 put: 111111111.
{i. i * 111111111}
=> #(111111111 12345678987654321)


あと、今回の 111111111 には使えませんが、後には凶悪な #become: というのも控えています(^_^;)。

| i |
i := 12345678987654321.
i become: 1111111111 copy.
{i. i * 1111111111}
=> #(1111111111 1234567900987654321)


いずれもお好みで。(違)


解答が示されていたのでこちらも書いてみました。

LargePositiveInteger >> div: y
   | val |
   val := self // y.
   self assureUniClass.
   #(= *) do: [:sym |
      self class compile: ('{1} other  ^val {1} other' format: {sym}).
      (self class >> sym literalAt: 1) value: val].
   ^val
| i |
i := 12345678987654321.
i div: 111111111.
{i = 111111111. i * 111111111}
=> #(true 12345678987654321)


なるほど。特異クラスで再定義するというものでしたか。