Files
hakorune/examples/lisp/cons_box.hako

228 lines
5.4 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 📦 ConsBox - LISPのcons cell実装
// ペアcar, cdrを表現する基本データ構造
box ConsBox {
car // 最初の要素
cdr // 残りの要素通常は別のConsBoxかNullBox
init {
car, cdr
}
// 基本アクセサ
func getCar() {
return me.car
}
func getCdr() {
return me.cdr
}
func setCar(value) {
me.car = value
}
func setCdr(value) {
me.cdr = value
}
// リストかどうかの判定
func isList() {
// cdrがNullBoxならリストの終端
if (NullBox.check_null(me.cdr)) {
return true
}
// cdrがConsBoxなら再帰的にチェック
// TODO: 型チェックの別の方法が必要
// 暫定的にtrueを返す
return true
// それ以外はドット対
return false
}
// リストの長さを取得
func length() {
if (not me.isList()) {
return -1 // リストでない場合は-1
}
count = 0
current = me
loop(not NullBox.check_null(current)) {
count = count + 1
current = current.getCdr()
}
return count
}
// n番目の要素を取得0ベース
func nth(n) {
if (n < 0) {
return new NullBox()
}
current = me
i = 0
loop(i < n) {
if (NullBox.check_null(current)) {
return new NullBox()
}
current = current.getCdr()
i = i + 1
}
if (NullBox.check_null(current)) {
return new NullBox()
}
return current.getCar()
}
// リストを配列に変換
func toArray() {
result = new ArrayBox()
current = me
loop(not NullBox.check_null(current)) {
result.push(current.getCar())
cdr = current.getCdr()
// ドット対の場合
// TODO: 型チェックの別の方法が必要
// 暫定的にスキップ
current = cdr
}
return result
}
// 文字列表現
func toString() {
// 空リスト
if (NullBox.check_null(me.car) and NullBox.check_null(me.cdr)) {
return "()"
}
result = "("
current = me
first = true
loop(not NullBox.check_null(current)) {
if (not first) {
result = result + " "
}
first = false
// carの表示
car = current.getCar()
if (NullBox.check_null(car)) {
result = result + "nil"
} else {
result = result + car.toString()
}
// cdrの確認
cdr = current.getCdr()
if (NullBox.check_null(cdr)) {
break
}
// ドット対の場合
// TODO: 型チェックの別の方法が必要
// 暫定的にスキップ
current = cdr
}
result = result + ")"
return result
}
// デバッグ用の詳細表示
func debugPrint() {
print("ConsBox {")
print(" car: " + me.car.toString())
print(" cdr: " + me.cdr.toString())
print(" isList: " + me.isList())
if (me.isList()) {
print(" length: " + me.length())
}
print("}")
}
}
// ヘルパー関数:配列からリストを作成
function arrayToList(arr) {
if (arr.length() == 0) {
return new NullBox()
}
// 逆順に構築
result = new NullBox()
i = arr.length() - 1
loop(i >= 0) {
result = new ConsBox(arr.get(i), result)
i = i - 1
}
return result
}
// ヘルパー関数:可変長引数でリストを作成
function list() {
// TODO: 可変長引数のサポートが必要
// 現在は固定数の引数での実装例
return new NullBox()
}
// テストコード
print("🎯 === ConsBox Test ===")
// 基本的なペア
print("📦 基本的なペア (1 . 2):")
pair = new ConsBox(new IntegerBox(1), new IntegerBox(2))
print(pair.toString())
pair.debugPrint()
// リスト (1 2 3)
print("\n📋 リスト (1 2 3):")
list123 = new ConsBox(
new IntegerBox(1),
new ConsBox(
new IntegerBox(2),
new ConsBox(
new IntegerBox(3),
new NullBox()
)
)
)
print(list123.toString())
print("Length: " + list123.length())
print("2nd element: " + list123.nth(1).toString())
// 配列からリストを作成
print("\n🔄 配列からリスト作成:")
arr = new ArrayBox()
arr.push(new StringBox("hello"))
arr.push(new StringBox("world"))
arr.push(new IntegerBox(42))
listFromArray = arrayToList(arr)
print(listFromArray.toString())
// ネストしたリスト ((1 2) (3 4))
print("\n🎯 ネストしたリスト:")
innerList1 = new ConsBox(
new IntegerBox(1),
new ConsBox(new IntegerBox(2), new NullBox())
)
innerList2 = new ConsBox(
new IntegerBox(3),
new ConsBox(new IntegerBox(4), new NullBox())
)
nestedList = new ConsBox(
innerList1,
new ConsBox(innerList2, new NullBox())
)
print(nestedList.toString())
print("\n✅ ConsBox implementation completed!")