リフレクションとメタプログラミング¶
Ring は動的プログラミング言語であり、プログラムのコードに関する応答を得られます。 さらに、実行中にコードを変更できます。
本題、および利用可能な関数の用法を学びます。
- locals()
- globals()
- functions()
- cfunctions()
- islocal()
- isglobal()
- isfunction()
- iscfunction()
- packages()
- ispackage()
- classes()
- isclass()
- packageclasses()
- ispackageclass()
- classname()
- objectid()
- isobject()
- attributes()
- methods()
- isattribute()
- isprivateattribute()
- ismethod()
- isprivatemethod()
- addattribute()
- addmethod()
- getattribute()
- setattribute()
- mergemethods()
- packagename()
locals() 関数¶
locals() 関数は現在のスコープにある変数名のリストを取得します。
文法:
locals() --> 現在のスコープにある変数名のリスト
用例:
test("hello")
func test cMsg
see cMsg + nl
x = 10
y = 20
z = 30
see locals()
実行結果:
hello
cmsg
x
y
z
globals() 関数¶
globals() 関数はグローバルスコープにある変数名のリストを取得します。
文法:
globals() --> グローバルスコープにある変数名のリスト
用例:
x=10 y=20 z=30
test()
func test
see "message from test()" + nl +
"Global Variables:" + nl
see globals()
実行結果:
message from test()
Global Variables:
x
y
z
functions() 関数¶
functions() 関数は Ring で記述された関数名のリストを取得します。
文法:
functions() --> Ring 関数名のリスト
用例:
see functions()
func f1
see "f1" + nl
func f2
see "f2" + nl
func f3
see "f3" + nl
実行結果:
f1
f2
f3
cfunctions() 関数¶
cfunctions() 関数は C 言語で記述された関数名のリストを取得します。
文法:
cfunctions() --> C 関数名のリスト
用例:
aList = cfunctions()
See "Count : " + len(aList) + nl
for x in aList
see x + "()" + nl
next
実行結果:
Count : 210
len()
add()
del()
get()
clock()
...
注釈
前述の実行結果から完全なリストは割愛されています。
islocal() 関数¶
islocal() 関数はローカルスコープで定義済みの変数であるかを検査します。
文法:
islocal(cVariableName) --> 変数がローカルスコープで定義されているならば 1 を返します。
変数がローカルスコープで定義されていないならば 0 を返します。
用例:
test()
func test
x=10 y=20
see islocal("x") + nl +
islocal("y") + nl +
islocal("z") + nl
実行結果:
1
1
0
isglobal() 関数¶
isglobal() 関数はグローバルスコープで定義済みの変数であるかを検査します。
文法:
isglobal(cVariableName) --> 変数がグローバルスコープで定義されているならば 1 を返します。
変数がグローバルスコープで定義されていないならば 0 を返します。
用例:
x=10 y=20
test()
func test
see isglobal("x") + nl +
isglobal("y") + nl +
isglobal("z") + nl
実行結果:
1
1
0
isfunction() 関数¶
isfunction() 関数は定義済みの Ring 関数であるかを検査します。
文法:
isfunction(cFunctionName) --> Ring 関数が定義されているならば 1 を返します。
Ring 関数が定義されていないならば 0 を返します。
用例:
see isfunction("f1") + nl +
isfunction("f2") + nl +
isfunction("f3") + nl
func f1
see "message from f1()" + nl
func f2
see "message from f2()" + nl
実行結果:
1
1
0
iscfunction() 関数¶
iscfunction() 関数は定義済みの C 関数であるかを検査します。
文法:
iscfunction(cFunctionName) --> C 関数が定義されているならば 1 を返します。
C 関数が定義されていないならば 0 を返します。
用例:
see iscfunction("len") + nl +
iscfunction("add") + nl +
iscfunction("test") + nl
実行結果:
1
1
0
packages() 関数¶
packages() 関数はパッケージ名のリストを取得します。
文法:
packages() --> パッケージ名のリスト
用例:
See packages()
Package Package1
Class class1
Func f1
Package Package2
Class class1
Func f1
Package Package3
Class class1
Func f1
Package Package4
Class class1
Func f1
実行結果:
package1
package2
package3
package4
ispackage() 関数¶
ispackage() 関数は定義済みのパッケージであるかを検査します。
文法:
ispackage(cPackageName) --> パッケージが定義されているならば 1 を返します。
パッケージが定義されていないならば 0 を返します。
用例:
See ispackage("package1") + nl +
ispackage("package4") + nl +
ispackage("package5") + nl +
ispackage("package3") + nl
Package Package1
Class class1
Func f1
Package Package2
Class class1
Func f1
Package Package3
Class class1
Func f1
Package Package4
Class class1
Func f1
実行結果:
1
1
0
1
classes() 関数¶
classes() 関数はクラス名のリストを取得します。
文法:
classes() --> クラス名のリスト
用例:
See classes()
Class class1
Func f1
Class class2
Func f1
Class class3
Func f1
実行結果:
class1
class2
class3
isclass() 関数¶
isclass() 関数は定義済みのクラスであるかを検査します。
文法:
isclass(cClassName) --> クラスが定義されているならば 1 を返します。
クラスが定義されていないならば 0 を返します。
用例:
see isclass("class4") + nl +
isclass("class3") + nl +
isclass("class2") + nl
Class class1
func f1
class class2
func f1
class class3
func f1
実行結果:
0
1
1
packageclasses() 関数¶
packageclasses() 関数はパッケージにあるクラス名のリストを取得します。
文法:
packageclasses(cPackageName) --> パッケージにあるクラス名のリスト
用例:
see "classes in Package1" + nl
see packageclasses("Package1")
see "classes in Package2" + nl
see packageclasses("Package2")
Package Package1
Class class1
Func f1
Package Package2
Class class1
Func f1
Class class2
Func f1
Class class3
func f1
実行結果:
classes in Package1
class1
classes in Package2
class1
class2
class3
ispackageclass() 関数¶
ispackageclass() 関数はパッケージで定義済みのクラスであるかを検査します。
文法:
ispackageclass(cPackageName,cClassName) --> クラスが定義されているならば 1 を返します。
クラスが定義されていないならば 0 を返します。
用例:
see ispackageclass("package1","class1") + nl +
ispackageclass("package1","class2") + nl +
ispackageclass("package2","class1") + nl +
ispackageclass("package2","class2") + nl
Package Package1
Class class1
Func f1
Package Package2
Class class1
Func f1
Class class2
Func f1
Class class3
func f1
実行結果:
1
0
1
1
classname() 関数¶
classname() 関数はオブジェクトのクラス名を検査します。
文法:
classname(object) --> オブジェクトのクラス名を返します。
用例:
o1 = new point
o2 = new rect
see classname(o1) + nl # point を表示
see classname(o2) + nl # rect を表示
class point
class rect
objectid() 関数¶
objectid() 関数はオブジェクトの識別子 (ID) を検査します。
文法:
objectid(object) --> オブジェクトの識別子 (ID) を返します。
用例:
o1 = new point
see objectid(o1) + nl
test(o1)
func test v
see objectid(v) + nl
Class point x y z
実行結果:
021B5808
021B5808
isobject() 関数¶
isobject() 関数は変数がオブジェクトであるかを検査します。
文法:
isobject(variable) --> オブジェクトならば True を、そうでなければ False を返します。
attributes() 関数¶
attributes() 関数はオブジェクトの属性を取得します。
文法:
attributes(object) --> オブジェクトの属性リストを返します。
用例:
o1 = new point
aList = attributes(o1) # see attributes(o1) を使えます。
for t in aList see t next # xyz の表示
Class Point x y z
methods() 関数¶
methods() 関数はオブジェクトのメソッドを取得します。
文法:
methods(object) --> オブジェクトのメソッドのリストを返します。
用例:
o1 = new test
aList = methods(o1)
for x in aList
cCode = "o1."+x+"()"
eval(cCode)
next
Class Test
func f1
see "hello from f1" + nl
func f2
see "hello from f2" + nl
func f3
see "hello from f3" + nl
func f4
see "hello from f4" + nl
実行結果:
hello from f1
hello from f2
hello from f3
hello from f4
isattribute() 関数¶
isattribute() 関数はオブジェクトに属性があるかを検査します。
文法:
isattribute(object,cAttributeName)
--> オブジェクトが属性を有しているならば True を返します。
用例:
o1 = new point
see isattribute(o1,"x") + nl # 1 の表示
see isattribute(o1,"t") + nl # 0 の表示
see isattribute(o1,"y") + nl # 1 の表示
see isattribute(o1,"z") + nl # 1 の表示
class point x y z
isprivateattribute() 関数¶
isprivateattribute() 関数はオブジェクトにプライベート属性があるかを検査します。
文法:
isprivateattribute(object,cAttributeName)
--> オブジェクトにプライベート属性があるならば True を返します。
用例:
o1 = new person
see isprivateattribute(o1,"name") + nl +
isprivateattribute(o1,"address") + nl +
isprivateattribute(o1,"phone") + nl +
isprivateattribute(o1,"job") + nl +
isprivateattribute(o1,"salary")
Class Person
name address phone
private
job salary
実行結果:
0
0
0
1
1
ismethod() 関数¶
ismethod() 関数はオブジェクトのクラスにメソッドがあるかを検査します。
文法:
ismethod(object,cMethodName)
--> オブジェクトのクラスにメソッドがあるならば True を返します。
用例:
o1 = new point
see ismethod(o1,"print") + nl # 1 の表示
mylist = []
mylist + new point
see ismethod(mylist[1],"print") + nl # 1 の表示
class point x y z
func print
see x + nl + y + nl + z + nl
isprivatemethod() 関数¶
isprivatemethod() 関数はオブジェクトのクラスにプライベートメソッドがあるかを検査します。
文法:
isprivatemethod(object,cMethodName)
--> オブジェクトのクラスにプライベートメソッドあるならば True を返します。
用例:
o1 = new Test
see isprivatemethod(o1,"f1") + nl +
isprivatemethod(o1,"f2")
Class Test
func f1
see "message from f1()" + nl
private
func f2
see "message from f2()" + nl
実行結果:
0
1
addattribute() 関数¶
addattribute() 関数はオブジェクトの状態 (クラスではなく) へ属性 (または属性のグループ) を追加します。
文法:
AddAttribute(object,cAttributeName|aAttributesList)
用例①:
see new point {x=10 y=20 z=30}
Class Point
AddAttribute(self,["x","y","z"])
用例②:
o1 = new point
addattribute(o1,"x")
addattribute(o1,"y")
addattribute(o1,"z")
see o1 {x=10 y=20 z=30}
class point
実行結果:
x: 10.000000
y: 20.000000
z: 30.000000
addmethod() 関数¶
addmethod() 関数はオブジェクトのクラスへメソッドを追加します。 このメソッドは同一クラスにあるオブジェクトでも使えます。
文法:
AddMethod(Object,cNewMethodName,cMethodName|AnonymousFunction)
用例:
o1 = new point { x=10 y=20 z=30 }
addmethod(o1,"print", func { see x + nl + y + nl + z + nl } )
o1.print()
Class point
x y z
実行結果:
10
20
30
無名関数ではなく関数名により、新規メソッドをクラスへ追加できます
用例:
o1 = new point { x=10 y=20 z=30 }
myfunc = func { see x + nl + y + nl + z + nl }
addmethod(o1,"print", myfunc )
addmethod(o1,"display", myfunc )
addmethod(o1,"show", myfunc )
o1.print()
o1.display()
o1.show()
Class point
x y z
実行結果:
10
20
30
10
20
30
10
20
30
クラスへメソッドを追加するため、このメソッドでは対象のクラスにあるメソッドを使用します。
用例:
o1 = new point { x=10 y=20 z=30 }
o2 = new point { x=100 y=200 z=300 }
o3 = new point { x=50 y=150 z=250 }
addmethod(o1,"print", func { see x + nl + y + nl + z + nl } )
o1.print()
o2.print()
o3.print()
Class point
x y z
実行結果:
10
20
30
100
200
300
50
150
250
getattribute() 関数¶
getattribute() 関数はオブジェクトの属性値を取得します。
文法:
GetAttribute(oObject,cAttributeName) ---> 属性の値
用例:
o1 = new point
see getattribute(o1,"name") + nl +
getattribute(o1,"x") + nl +
getattribute(o1,"y") + nl +
getattribute(o1,"z") + nl
Class Point
x=10 y=20 z=30
name = "3D-Point"
実行結果:
3D-Point
10
20
30
用例:
findclass() 関数から GetAttribute() を呼び出してクラスリストのメンバを検索します。検索には桁の位置よりもメンバ名を優先して使用します。
myList =
[new Company {position=3 name="Mahmoud" symbol="MHD"},
new Company {position=2 name="Bert" symbol="BRT"},
new Company {position=1 name="Ring" symbol="RNG"}
]
see myList
see nl +"=====================" + nl + nl
for i = 1 to len(myList)
see "Pos: "+ i +" | "+ myList[i].position +" | "+ myList[i].name +
" | "+ myList[i].symbol +" | "+ nl
next
See findclass(myList, "MHD", "symbol") +nl ### メンバのクラス名を指定
###---------------------------------------
func findclass classList, cValue, classMember
See nl + "FindClass: " +" "+ cValue + nl + nl
for i = 1 to len(classList)
result = getattribute( classList[i], classMember )
See "Result-Attr: " + i +" "+ result +nl
if result = cValue
j = i
ok
next
return j
###--------------------------------------
class company position name symbol
実行結果:
Pos: 1 | 3 | Mahmoud | MHD |
Pos: 2 | 2 | Bert | BRT |
Pos: 3 | 1 | Ring | RNG |
FindClass: MHD
Result-Attr: 1 MHD
Result-Attr: 2 BRT
Result-Attr: 3 RNG
1
setattribute() 関数¶
setattribute() 関数はオブジェクトの属性値を設定します。
文法:
SetAttribute(oObject,cAttributeName,Value)
用例:
o1 = new person
setattribute(o1,"cName","Mahmoud")
setattribute(o1,"nSalary",1000000)
setattribute(o1,"aColors",["white","blue","yellow"])
see o1
see o1.aColors
Class Person
cName
nSalary
aColors
実行結果:
cname: Mahmoud
nsalary: 1000000.000000
acolors: List...
white
blue
yellow
mergemethods() 関数¶
MergeMethods() 関数は継承を行わずにクラスとメソッドを共有します。
この関数は別のクラスへクラスのメソッドを併合します。
文法:
MergeMethods(cClassNameDestination,cClassNameSource)
用例:
mergemethods("count","share")
mergemethods("count2","share")
o1 = new count { test() }
o1 = new count2 { test() }
Class Share
func one
see "one" + nl
func two
see "two" + nl
func three
see "three" + nl
Class Display
Func printline
see copy("*",20) + nl
Class Count from Display
Func test
printline()
one()
two()
three()
printline()
Class Count2 from Display
Func test
three()
two()
one()
printline()
実行結果:
********************
one
two
three
********************
three
two
one
********************
packagename() 関数¶
packagename() 関数は import 命令が成功した最近のパッケージ名を検査します。
文法:
packagename() --> import 命令が成功した最近のパッケージ名を返します。
用例:
load "weblib.ring"
import System.web
see packagename() # system.web