リフレクションとメタプログラミング¶
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 : 236
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