リフレクションとメタプログラミング — プログラミング言語 Ring 1.14 取扱説明書

Skip to content

# リフレクションとメタプログラミング

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