Skip to content

Instantly share code, notes, and snippets.

@zonuexe
Created January 30, 2012 05:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zonuexe/1702741 to your computer and use it in GitHub Desktop.
Save zonuexe/1702741 to your computer and use it in GitHub Desktop.
Objective Programming Paradigm を Rubyで妄想実装
# -*- coding:utf-8 -*-
#
# Objective Programming Paradigm を Rubyで妄想実装
#
# もとねた https://gist.github.com/1700321
#
# Objective なオブジェクトを Ruby の世界に戻す
def p arg; puts arg.val; end
# Objective Programming Paradigm の世界を Ruby に持ち込む
module Objectable
def initialize n
# オブジェクトは値とリストを持つ
@val = n
@list = [@val]
end
# cat メソッドは引数を結合
def cat arg
@list += arg.list
self
end
# 演算子を再定義したいが、 ***不本意にも*** 右結合演算子である必要があるので、これ。
def ** arg
cat arg
end
attr_reader :list, :val
end
# よくわかんないけど、ObjectiveValue以外にそれっぽい型が別に必要になったらアレなので実装分けてます
class ObjectiveValue
include Objectable
# cat のメソッド定義はこっちにあった方が良い気もするけど、まあとりあへず。
end
# Objective な函数を実装しまーす。
class ObjectiveFunction
include Objectable
def initialize *arg
@name = arg[0]
@proc = Proc.new
end
def ** arg
#p [arg, arg.list]
ObjectiveValue.new(@proc.call arg.list)
end
end
# 函数の実装は定数への代入
Sum = ObjectiveFunction.new(:sum){|arg|
arg.inject(&:+)
}
Mul = ObjectiveFunction.new(:mul){|arg|
arg.inject(&:*)
}
Div = ObjectiveFunction.new(:div){|arg|
arg[0] / arg[1]
}
Sub = ObjectiveFunction.new(:div){|arg|
arg[0] - arg[1]
}
# Ruby な値を Objective な値にして返します。
class N
def self.[] n
ObjectiveValue.new n
end
end
=OPP Ruby DSL 妄想実装
==概要
OPP Ruby DSL (以下、OPP DSL) は、wasao(@MatsumuraKs)が設計した「オブジェクト型言語(Objective Programming Paradigm)」(以下、OPP)を勝手にRubyで言語内DSLとして実装する。言語仕様と参照実装はよ。
==妄想言語仕様
以下はサンプルコードとして呈示された factorial.op から推測した。
これらの仕様及び使用してゐる用語は全て筆者が独断で宛てたものなので、一刻も早い仕様策定・公開が求められる。
===用語
===オブジェクト
OPP におけるオブジェクトは以下の性質を持つ。
- オブジェクトはメッセージとしてオブジェクトを一つ受け取る
- オブジェクトへの参照リストを内部に持つ
===メッセージ式
メッセージ式は次のやうに記述する。
1 2
1, 2 は値オブジェクトである。この式において「1 に 2 を送信した」と呼ぶ。「送信」とはオブジェクト間通信のメタファであり、事実上はラムダ計算における「適用」と同義である。函数型プログラミング言語の流儀では、オブジェクトは全て函数であると考へて良い。
言語内 DSL は性質上、ホスト言語である Ruby の言語仕様の制約を強く受ける。Ruby において空白区切りで引数を受け取れるのはメソッドのみである(オブジェクト指向言語である Ruby におけるメッセージとはメソッド呼び出しにほかならない)。
そのため、 OPP DSL では、プログラムの表記上にメッセージ演算子を導入する。
N[1] ** N[2]
Ruby において右結合性のある演算子は、代入演算子及び条件演算子を除けば、 ** のみである。よって、この演算子は消去法によって選択肢なく選ばれた。
OOP DSL において ** はレシーバのメソッドとして実装されるが、オブジェクト間通信のメタファとしては「1 に 2 を送信する」、ラムダ計算の概念としては「1 を 2 に適用する」と呼ぶべきであらう。
===レシーバ
メッセージ式において、メッセージを受け取る側のオブジェクトのこと。
===メッセージ
メッセージはオブジェクト指向プログラミングにおけるオブジェクト間の通信のメタファであり、多くのプログラミング言語における「引数」に相当すると云ふことができる。
==値オブジェクト
値オブジェクトは、以下の性質を持ったオブジェクトである。
- 初期化時に自身への参照を持つ
- メッセージを受け取ると、受け取ったオブジェクトの参照リストを自身の参照リストの末尾に連結する
==函数
函数は、レシーバとは別のオブジェクトを返すオブジェクトのことである。以下の性質を持つ。
- 函数の内部状態が変化することはない
- 参照リストには自身への参照を持つ
==参考資料
- factorial.op[https://gist.github.com/1700321]
@zonuexe
Copy link
Author

zonuexe commented Jan 31, 2012

Objective な世界に計算順序をどうやって持ち込まうかと思ったら、Ruby側の () をそのまま使へば良い話だった
LispくさいLispくさいと思ってたら、ほんとに見た目上は括弧を一枚剥いただけのLispだったでござる…

#1 + 2 * 3 => (+ 1 (* 2 3))
p Sum ** N[1] ** Mul ** N[2] ** N[3]

#100 + 2 * 3 - 3 + 4 / 2 => (+ 100 (* 2 3) -3 (/ 4 2))
p Sum ** N[100] ** (Mul ** N[2] ** N[3]) ** N[-3] ** (Div ** N[4] ** N[2])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment