2013年9月29日日曜日

[Common Lisp] 破壊的な関数

Common Lispには、戻り値を作り出すために元々の構造を破壊する関数があります。

sort、stable-sort を除く破壊的な関数には対応する非破壊的な関数があるので、基本的には非破壊版を利用しておいたほうが良さそうです。

なお、破壊的関数の先頭に付く n は non-consing の略だそうです。

詳しくは 実践Common Lispの12章 あたりを見ると良いでしょう。

非破壊的破壊的概要
sortソート
stable-sort安定ソート
reversenreverseリストの反転
appendnconcリストの結合
revappendnreconcリストの結合
butlastnbutlastリストの末尾以外取得
removedeleteシーケンスの要素削除
remove-ifdelete-if条件に一致する要素削除
remove-if-notdelete-if-not条件に一致しない要素削除
remove-duplicatesdelete-duplicates重複を削除
unionnunion和集合
intersectionnintersection積集合
set-differencenset-difference差集合
set-exclusive-ornset-exclusive-or対称差
string-capitalizenstring-capitalize単語の先頭を大文字、それ以外を小文字に変換
string-downcasenstring-downcase文字列を小文字に変換
string-upcasenstring-upcase文字列を大文字に変換
substnsubst木構造(リスト)の要素を変更
subst-ifnsubst-if木構造(リスト)の要素を変更
subst-if-notnsubst-if-not木構造(リスト)の要素を変更
sublisnsublis木構造(リスト)の要素を変更
substitutensubstituteシーケンスの要素を変更
substitute-ifnsubstitute-ifシーケンスの要素を変更
substitute-if-notnsubstitute-if-notシーケンスの要素を変更

2013年9月16日月曜日

[D]デザインパターン修行:Builderパターン

Builderパターンは複雑なオブジェクトの生成を抽象化するデザインパターン。

  • Builderインターフェース
    • オブジェクトの組み立てに使うメソッドを定義する
  • Directorクラス
    • Builderのメソッドを適切な順序で使ってオブジェクトを組み立てる
  • ConcreteBuilderクラス
    • Builderで定義したメソッドを実装する

BuilderパターンをD言語で書いてみます。

/* builderパターン */

import std.algorithm;
import std.string;
import std.stdio;

interface DocBuilder {
  void makeTitle(string title);
  void addContent(string content);
  string getResult();
}

class HtmlBuilder : DocBuilder {
  string title;
  string[] contents;

  override void makeTitle(string title) {
    this.title = title;
  }

  override void addContent(string content) {
    this.contents ~= content;
  }

  override string getResult() {
    string fmt = "<html><head><title>%s</title></head><body>%s</body></html>";
    string c = reduce!((a, b) => a ~ "<a>%s</a>".format(b))("", contents);
    return fmt.format(title, c);
  }
}

class TextBuilder : DocBuilder {
  string title;
  string[] contents;

  override void makeTitle(string title) {
    this.title = title;
  }

  override void addContent(string content) {
    this.contents ~= content;
  }

  override string getResult() {
    string list = "";
    foreach(s; contents) {
      list ~= "- " ~ s ~ "\n";
    }
    return "* " ~ title ~ "\n" ~ list;
  }  
}

class Director {
  private DocBuilder builder;

  this(DocBuilder builder) {
    this.builder = builder;
  }

  string construct(string title, string[] contents) {
    builder.makeTitle(title);
    foreach(c; contents) {
      builder.addContent(c);
    }
    return builder.getResult();
  }
}

void main() {
  auto d1 = new Director(new HtmlBuilder());
  writeln(d1.construct("AAA", ["hello", "world"]));
  auto d2 = new Director(new TextBuilder());
  writeln(d2.construct("AAA", ["hello", "world"]));
}
> dmd builder.d
> ./builder
<html><head><title>AAA</title></head><body><a>hello</a><a>world</a></body></html>
* AAA
- hello
- world