つづき

(m-n)%3 をどうやって計算するか?

(m-n)%3 = (m+n+n)%3 を使うと引き算がいらなくなる。

  let.m_n_mod3 = abs m, n do
    add(m, add(n, n))
  end

あとは、トリプルからk%3番目をとってくる関数を実装すればできあがりだ。
それは、k回トリプルをシフトして、最初のをとってくればよい。

トリプルをシフトするのは

  let.shift = abs a, b, c, f do
    f(b, c, a)
  end
  let.tr1_s = tr1(shift)
  let.tr1_ss = tr1(shift, shift)

というようにすればよい。よって

  let.exec_tr = abs tr, k do
    let.tr_k = tr(shift, shift, ... (k times) ..., shift)
    let.f = tr(get_1st)
    f(f)
  end

な感じになるのだが、数値はここの繰り返しにしか使わないので、
最初から、shiftを何回繰り返したかを数値の表現に使えばいいことがわかる。

shiftを一回合成する関数は

  let.add_shift = abs shifts, a, b, c do
    shifts(b, c, a)
  end
  let.shift_2 = add_shift(shift)
  let.shift_3 = add_shift(add_shift(shift))

である。

というわけで、m_n_mod3はもういらなくなって

  let.exec_tr = abs tr, m, n do
    tr(m, n, n, apply_2nd_3rd)
  end

ときれいにかけるわけだ。