Pangaea 언어의 원형 체인 정보
2020년부터 스스로'팡나아'라는 프로그래밍 언어를 만들었다.
원형 기반의 동적 유형 언어에서 하위 대상은 부모 대상의 속성을 계승한다.
cat := {
name: "Tama",
# NOTE: Pangaeaではメソッドは単なる関数プロパティ
meow: m{ "Meow. I am #{.name}.".p }
}
kitten := cat.bear({name: "Mike"})
cat.meow # "Meow. I am Tama."
kitten.meow # "Meow. I am Mike."
언어에 대한 상세한 내용과 강좌는 과거의 보도를 보십시오.이 글에서는 판가를 원형 체인으로 계승할 때 시행착오가 있었던 점을 소개한다.
(집필할 때도 창작부분v0.8.0 예상)
상속수
Pangaea의 상속 트리는 다음과 같습니다.예를 들어 소양
{a: 1}
이 계승Obj
,[1, 2]
이 계승Arr
했다.- BaseObj
- Obj
- (object literal) {a: 1} etc.
- Arr
- (arr literal) [1, 2] etc.
- Err
- AssertionErr
- NameErr
- ...(その他各種エラー)
- Func
- (func literal) {|x| x+1} etc.
- Iter
- (iter literal) <{|x| x+1}> etc.
- Map
- (map literal) %{"a": 1} etc.
- Nil
- nil
- Num
- Float
- (float literal) 1.0 etc.
- Int
- 0
- false
- 1
- true
- (int literal)
- Range
- (range literal) (1:10:2) etc.
- Str
- (str literal) "foo" etc.
대상 조작 방법(속성)이 있는 것은 부 대상Arr
과 Obj
이고 각 소양은 이것만 계승(자신이 없음)이다.원형 체인의 설치
방법(속성)의 해결
모든 대상은 자신의 부모 대상(원형)1이 있기 때문에 순서대로 호출하는 방법을 얻었다.
원형 체인의 대상이 상응하는 명칭을 가진 방법이 있으면 이 방법을 되돌려주고 마지막까지 찾지 못하면 토해낸다
NoPropErr
2.# {a: 1} はプロパティaを持っているのでそれを直接呼び出す
{a: 1}.a # 1
# {a: 1} はプロパティ keysを持たないが、 Obj が持っている
{a: 1}.keys # ["a"]
# foo は誰も持っていない
{a: 1}.foo # NoPropErr: property `foo` is not defined.
# 参考:プロトタイプの一覧
{a: 1}.ancestors # [Obj, BaseObj]
해석기 내부에서도 이 같은 설명을 간단하게 실시했다.object/findprop.go
func FindPropAlongProtos(o PanObject, propHash SymHash) (PanObject, bool) {
// trace prototype chains
for obj := o; obj != nil; obj = obj.Proto() {
prop, ok := findProp(obj, propHash)
if ok {
return prop, true
}
}
return nil, false
}
func findProp(o PanObject, propHash SymHash) (PanObject, bool) {
obj, ok := o.(*PanObj)
if !ok {
return nil, false
}
elem, ok := (*obj.Pairs)[propHash]
if !ok {
return nil, false
}
return elem.Value, true
}
수신기의 해결다른 한편, 내부 설치로서 단지 이렇게 해서는 안 된다.
삽입 방법은 특정한 데이터 구조 (int와arr 등) 가 필요합니다.데이터 구조는 상속 관계와 무관하기 때문에 하위 대상은 부모 대상의 방법을 사용할 수 없다.
난처하다
# 配列リテラル。データ構造は *object.PanArr
arr := [1, 2]
# arrを継承。データ構造はデフォルトの *object.PanObj
child := arr.bear({a: 1})
# has? は Arrの組み込みメソッド。*object.PanArrのデータ構造を要求するので、childをレシーバにすると処理できない!
child.has?(1)
따라서 삽입식 방법에서 평가에 사용되는 수신기(or파라미터)도 원형 체인을 통해 얻을 수 있다.props/arr_props.go
func ArrProps(propContainer map[string]object.PanObject) map[string]object.PanObject {
return map[string]object.PanObject{
// Obj.has?の実装。要素一覧を舐めるので*PanArrのデータ構造が必要
"has?": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
if len(args) < 2 {
return object.NewTypeErr("Arr#has? requires at least 2 args")
}
// レシーバは第一引数として渡される(型はインターフェースPanObject)が、実装が*PanArrでない場合要素を参照することができない
// そこで、プロトタイプチェーンを辿り*PanArrであるプロトタイプを取得
self, ok := object.TraceProtoOfArr(args[0])
if !ok {
return object.NewTypeErr(`\1 must be arr`)
}
// 以下selfをレシーバとし本処理
for _, elem := range self.Elems {
// ...
}
},
),
object/traceproto.gofunc TraceProtoOfArr(obj PanObject) (*PanArr, bool) {
for o := obj; o.Proto() != nil; o = o.Proto() {
if v, ok := o.(*PanArr); ok {
return v, true
}
}
return nil, false
}
child
가 계승[1, 2]
했기 때문에child.has?(1)
는 실질적으로Arr['has?]([1, 2], 1)
로 평가된다.수신기 대체 수신기는 언뜻 보면 위화감이 있지만 child
부모[1, 2]
로 대처하는 것은 상속적으로 자연스러운 일이다.대체로 몇 가지 모델을 시험해 보았지만 예상대로 일을 하고 있다.계승의 예
# 1. 配列リテラル [1, 2] (Arrを継承、データ構造は*PanArr)
[1,2].has?(1) # true
# 2. Arrをcallで継承 (できるものはリテラル [1, 2] と同じ。データ構造は*PanArr)
Arr(1,2).has?(1) # true
# 3. リテラルをbearで継承 (データ構造は*PanObj)
child3 := [1, 2].bear({a: 1})
child3.has?(1) # true
# 4. Arrをbearで継承→callで継承 (データ構造は*PanArr)
childArr := Arr.bear({foo: "bar"})
childArr(1, 2).has?(1) # true
# 5. リテラルをcallで継承 (データ構造は*PanArr)
[1,2](3, 4).has?(1) # false
*PanArr
가 여러 원형 체인5.
에 나타나도 수신기는 자신[3, 4]
을 정확하게 사용했다.원형을 0값으로 볼 수 있도록 하다
위에도 해결할 수 없는 문제가 하나 있다.
Arr
자신의 방법을 사용할 수 없습니다.Arr
그 조상Obj
과 BaseObj
의 데이터 구조는 모두 *PanObj
였고, 요구*PanArr
의 삽입식 방법으로는 수신기의 오류를 해결할 수 없었다.물론 못 사용하기로 결정하면 되지만 모처럼 원형
Arr
을 표시해 배열로 처리했으면 좋겠다.따라서 수신기Arr
는 []
에 의해 해결될 수 있다.우선, 모든 대상을 위해 0치 개념을 도입한다.
*PanObj
유형: 임의의 대상을 0값으로 할 수 있습니다Arr
0값 있음[]
object/traceproto.go
func TraceProtoOfArr(obj PanObject) (*PanArr, bool) {
for o := obj; o.Proto() != nil; o = o.Proto() {
if v, ok := o.(*PanArr); ok {
return v, true
}
// ゼロ値確認を追加
// 自身のデータ構造が違っても、ゼロ値が*PanArrならゼロ値にレシーバ解決
if a, ok := o.Zero().(*PanArr); ok {
return a, true
}
}
return nil, false
}
이렇게 되면 맑은 날Arr
에 자신의 방법을 사용할 수 있다.# Arr は組み込みメソッドでは [] として扱われる
Arr + [1, 2] # [1, 2]
Arr.len # 0
Arr.has?(1) # false
(이 부분은 아직 수정 중이며 집필할 때 완성만 했다Arr
. 끝말
원형의 계승구조는 간단하게 표현할 수 있지만 숨겨진 실제 데이터 구조를 처리할 때 생각해야 할 부분이 많다.
이 보도의 내용은 다음 판본
v0.8.0
에 발표될 예정이다."이게 더 좋아요!"이런 댓글 달아주시면 감사하겠습니다!자바스크립트처럼 부모가 프로타입을 사용하는 속성을 가지고 있는 것이 아니라 원형으로 부모 자신을 참조하는 것이다. ↩
엄밀히 말하면 모든 대상의 조상
BaseObj
까지 속성을 찾지 못하면 속성을 다시 획득_missing
(Rubby 참조)↩Reference
이 문제에 관하여(Pangaea 언어의 원형 체인 정보), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Syuparn/items/bbf1241ab804949eb690텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)