Skip to content

Instantly share code, notes, and snippets.

@einblicker
Created February 7, 2012 09:35
Show Gist options
  • Save einblicker/1758706 to your computer and use it in GitHub Desktop.
Save einblicker/1758706 to your computer and use it in GitHub Desktop.
Javaで型安全なprintf
interface Func<A, B> {
B apply(final A arg);
}
abstract class Dir<A, B> {
public Dir() {}
abstract public Func<Func<String, A>, Func<String, B>> format();
}
class DLit<A> extends Dir<A, A> {
private String s;
public DLit(String s) {
this.s = s;
}
public Func<Func<String, A>, Func<String, A>> format() {
return new Func<Func<String, A>, Func<String, A>>() {
public Func<String, A> apply(final Func<String, A> cont) {
return new Func<String, A>() {
public A apply(final String out) {
return cont.apply(out + s);
}
};
}
};
}
}
class DInt<A> extends Dir<A, Func<Integer, A>> {
public DInt() {}
public Func<Func<String, A>, Func<String, Func<Integer, A>>> format() {
return new Func<Func<String, A>, Func<String, Func<Integer, A>>>() {
public Func<String, Func<Integer, A>> apply(final Func<String, A> cont) {
return new Func<String, Func<Integer, A>>() {
public Func<Integer, A> apply(final String out) {
return new Func<Integer, A>() {
public A apply(Integer i) {
return cont.apply(out + i.toString());
}
};
}
};
}
};
}
}
class DStr<A> extends Dir<A, Func<String, A>> {
public DStr() {}
public Func<Func<String, A>, Func<String, Func<String, A>>> format() {
return new Func<Func<String, A>, Func<String, Func<String, A>>>() {
public Func<String, Func<String, A>> apply(final Func<String, A> cont) {
return new Func<String, Func<String, A>>() {
public Func<String, A> apply(final String out) {
return new Func<String, A>() {
public A apply(String s) {
return cont.apply(out + s);
}
};
}
};
}
};
}
}
class DCon<A, B, C, D> extends Dir<C, B> {
private Dir<A, B> d1;
private Dir<C, A> d2;
public DCon(Dir<A, B> d1, Dir<C, A> d2) {
this.d1 = d1;
this.d2 = d2;
}
public Func<Func<String, C>, Func<String, B>> format() {
return new Func<Func<String, C>, Func<String, B>>() {
public Func<String, B> apply(final Func<String, C> cont) {
return new Func<String, B>() {
public B apply(final String out) {
return d1.format().apply(d2.format().apply(cont)).apply(out);
}
};
}
};
}
}
class SafeFormatter {
public static <A> A format(Dir<String, A> d) {
return d.format().apply(new Func<String, String>() {
public String apply(final String a) {
return a;
}
}).apply("");
}
public static <A> Dir<A, A> newDLit(String s) {
return new DLit<A>(s);
}
public static <A> Dir<A, Func<Integer, A>> newDInt() {
return new DInt<A>();
}
public static <A> Dir<A, Func<String, A>> newDStr() {
return new DStr<A>();
}
public static <A, B, C, D> Dir<C, B> newDCon(Dir<A, B> d1, Dir<C, A> d2) {
return new DCon<A, B, C, D>(d1, d2);
}
public static void main(String[] args) {
//型安全なSystem.out.printf("hello, %s!", "world")を表現している。
Dir<Func<String, String>, Func<String, String>> d1 = newDLit("hello, ");
Dir<String, Func<String, String>> d2 = newDStr();
Dir<String, String> d3 = newDLit("!");
System.out.println(format(newDCon(newDCon(d1, d2), d3)).apply("world"));
//System.out.println(format(newDCon(newDCon(d1, d2), d3)).apply(123)); //String以外の型はコンパイルエラー
//型安全なSystem.out.printf("a: %d b: %d c: %d", 1, 2, 3)を表現している。
Dir<Func<Integer, Func<Integer, Func<Integer, String>>>,
Func<Integer, Func<Integer, Func<Integer, String>>>> d4 = newDLit("a: ");
Dir<Func<Integer, Func<Integer, String>>,
Func<Integer, Func<Integer, Func<Integer, String>>>> d5 = newDInt();
Dir<Func<Integer, Func<Integer, String>>,
Func<Integer, Func<Integer, String>>> d6 = newDLit(" b: ");
Dir<Func<Integer, String>,
Func<Integer, Func<Integer, String>>> d7 = newDInt();
Dir<Func<Integer, String>, Func<Integer, String>> d8 = newDLit(" c: ");
Dir<String, Func<Integer, String>> d9 = newDInt();
System.out.println(
format(newDCon(newDCon(newDCon(newDCon(newDCon(d4, d5), d6), d7), d8), d9))
.apply(1).apply(2).apply(3)
);
//System.out.println(
// format(newDCon(newDCon(newDCon(newDCon(newDCon(d4, d5), d6), d7), d8), d9))
// .apply('a').apply('b').apply('c')
//); //Integer以外の型はコンパイルエラー
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment