επιστημηさんのBlogのdelegateもどきにあるコードと同じ動きをするものをC#とJavaとRubyで書いてみた。
まずは、C#。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Deleg
{
static class Utils
{
public static int Add(int x, int y) { return x + y; }
public static int Time2(int x) { return Add(x, x); }
}
class Bias
{
int value_;
public Bias(int n) { value_ = n; }
public int Value(int x) { return value_ + x; }
}
class Program
{
static void Main(string[] args)
{
// fはintを引数とし、intを返す
Func<int, int> f;
f = Utils.Time2;
Console.WriteLine(f(3)); // 3 + 3 = 6
// Addの第二引数を4に固定
f = (x) => Utils.Add(x, 4);
Console.WriteLine(f(3)); // 3 + 4 = 7
Bias b = new Bias(10);
// インスタンスメソッドだからって特にC#ではC++と違って意識することはない
f = b.Value;
Console.WriteLine(f(2)); // b.Value(2) = 12
}
}
}
もともとのネタがdelegateを使ったコードがあるのを前提にしてあるから、すっきりと移植完了。
tr1::bindは、ラムダ式で代用してみた。
続いてJava。最近NetBeans6を使ってる。Eclipseを起動してないなぁ…。と感慨にふけってみたけど、感慨にふけってもまだNetBeans6は立ち上がらない。
もうちょいここらへんの起動スピードあがってほしいと思う今日この頃でした。
package deleg;
public class Main {
static int add(int x, int y) { return x + y; }
static int time2(int x) { return add(x, x); }
static class Bias {
int value_;
public Bias(int x) {
value_ = x;
}
public int value(int x) { return value_ + x; }
}
// delegateないしなぁ…
static interface Func {
int exec(int x);
}
public static void main(String[] args) {
Func f;
// 無名クラス?でお茶を濁す
f = new Func(){ public int exec(int x) { return time2(x); } };
System.out.println(f.exec(3)); // 3 + 3 = 6
// 第二引数を固定と言われても…
f = new Func() { public int exec(int x) { return add(x, 3); } };
System.out.println(f.exec(3)); // 3 + 4 = 7
// finalじゃないと無名クラスのメソッドから参照できないんです
final Bias b = new Bias(10);
f = new Func() { public int exec(int x) { return b.value(x); } };
System.out.println(f.exec(2)); // b.value(2) = 12
}
}
こちらは、Delegateみたいなものや関数ポインタみたいなものがJava6までには無い(Java7で出来るのかな)ので無名クラスを使ってお茶を濁した。
同じ事が実現できてはいるけど、ちょっと記述がまどろっこしい。
次はRuby。
こちらは、Procあたりを使うとさくっとできる。
これも、引き続きNetBeans6で作ってみた。起動に時間がかかったりするけど、IDEがあると補完とかがきいて楽チン。
def add x, y
x + y
end
def time2 x
add x, x
end
class Bias
def initialize x
@value = x
end
def value x
@value + x
end
end
# こういうのはlambda使うのかな…自身が無い
f = lambda {|x| time2 x}
puts f.call(3) # 3 + 3 = 6
# addの第二引数を4に固定
f = lambda {|x| add x, 4 }
puts f.call(3) # 3 + 4 = 7
b = Bias.new 10
f = lambda {|x| b.value(x)}
puts f.call(2) # b.value(2) = 12
Rubyも確か、関数ポインタやdelegateにあたるような概念は言語仕様になかったような気がする…(気がするだけ!)
lambdaを使って、Procクラスのオブジェクトをこさえてやることでいける。
こちらも割りとすっきり書けたような気がする。どうだろうか。