やりたいこと
デバッグなどのちょっとしたときにカウンタを使いたい場合があると思います。ひとまず、とりあえず、殴り書くとしたらこんな感じでしょうか。
c = 0
3.times do # なんらかの繰り返し
p c += 1
end
# => 1
# => 2
# => 3
このときブロックの外にある c = 0
がなんとなくゆるせへん、というところに本稿は端を発します。
クロージャや便利メソッドを用いたとしても、大抵はブロックの外で準備をする必要があり、本稿で目指すところではありません。目指すところは、その一行を挿入するだけで機能する以下のようなカウンタです(1からでなくてもよい)。
3.times do # なんらかの繰り返し
p # なんらかのすごいカウンタ
end
# => 1
# => 2
# => 3
また、無から生み出すということで参考ページの IQ1450で美少女JSの先輩から、Rubyで無から有を生み出す方法を教わった - Qiita において設けられている以下の縛りを導入します。
- 一度宣言・初期化した変数は他の式・文で使用しない
- 演算子および演算子風のシンタックスシュガーが導入されたメソッド、及び代入、また括弧のみが使用できる
できたもの
3.times do # なんらかの繰り返し
p $c = !$c && ($c <=> $c) || $c + ($c <=> $c)**($c <=> $c)
end
# => 0
# => 1
# => 2
いい感じに最悪になりました。
グローバル変数 $c
はここで初めて使用されます。
一応 1
や 0
を使うことも避けています。
なんだこれ
これはグローバル変数を使用しているので、厳密には参考ページで説明されている「存在しないローカル変数に値を代入しようとしたとき nil
で初期化される」という仕様を悪用できていません。
とはいえグローバル変数も最初は nil
なのでいきなり $c += 1
とすることはできません。そのため $c
が nil
のときは ||
の右辺が評価されないようにしています。
グローバル変数は既に nil
として存在しているとも言えるので無から生成したかと言われると微妙な感じになってしまいましたが、グローバル変数は縛られてなかったので見逃してください。
おまけ
上記のカウンタをつくる過程で生まれたその他の1行カウンタです。
0
と 1
は無から生み出せることがわかっているので普通に使っています。
縛りを無視してメソッドも普通に使っています。
$c = $c.to_i.succ
$c = $c ? $c + 1 : 0
$c = $c + 1 rescue 0
他にも縛りを守った上でもっと簡単に書けるよ、という1行カウンタがありましたらぜひコメントにて教えていただけると幸いです。