marg-do's

関数型生活

Rangeオブジェクトにおけるcase等値演算子の定義とcase文

Rangeオブジェクトにおいてcase等値演算子(===)は以下のように定義される。
左辺(Rangeオブジェクト)が示す範囲内に右辺の値が属していればtrue、それ以外はfalse。

(1..10) === 4 #=> true
(1..10) === 10 #=> true
(1..10) === 10.1 #=> false

case文においては以下のように処理される

x = 5

case x
when 0..10
   puts "0 <= #{x} <= 10"
when 10..100
   puts "10 <= #{x} <= 100"
else
   puts "error"
end

#=> "0<=5<=10"

case文では、case直後にある式を右辺、when直後にある式を左辺として、case等値演算子で評価している。

入力した文字の文字数を返す

#include <stdio.h>
#define EOL 10

int main()
{
  int c, length = 0;
  c = getchar();

  while (c != EOF) {
    if (c == EOL) {
      printf("%d\n", length);
      length = 0;
    } else {
      length = length + 1;
    }
    c = getchar();
  }
  return 0;
}

getcharは、入力ストリームに文字が存在する場合そこから一文字読み込み、
存在しなくなった場合、標準入力からの入力を待つ。

論理演算子&&を定義してみる

class Object
  def myand(x)
    if self == nil
      false
    elsif self == false
      false
    else
      if x == nil
        false
      elsif x == false
        false
      else
        x
      end
    end
  end
end

a = 5
b = nil
a.myand(b) #=> nil  (a&&bと同じ役割)

絶対もっと上手い書き方ありますが…。
内部ではこんな感じの分岐で評価される模様
とりあえず練習までに

追記
ただこれだと

a = "test"
nil.myand(a.reverse!)
a #=> "tset"

となって、引数が評価されてしまい、
&&の挙動と少し違うようになってしまう…

Rubyが変数とメソッドを区別する瞬間

def a
  1
end

a #=> 1 (メソッドaの実行)

a = 0 if false

a #=> nil (変数aの参照)

a = 2

a #=> 2 (変数aの参照)

以上のように、Rubyは、変数の定義式が現れた瞬間に、aをメソッドではなく変数への参照として扱い始める。
実際の代入が行われているかどうかは判別しない。