Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

배열 구현 개선 #36

Open
Qwaz opened this issue Jan 5, 2016 · 12 comments
Open

배열 구현 개선 #36

Qwaz opened this issue Jan 5, 2016 · 12 comments

Comments

@Qwaz
Copy link
Contributor

Qwaz commented Jan 5, 2016

  1. JS에서 배열을 출력할 때 맨 앞에 쉼표가 출력됩니다.
  2. 공식 구현에서 배열 일부를 잘라내는 문법(목록[1~2])이 구현되지 않은 상태입니다.
@disjukr
Copy link
Member

disjukr commented Jan 5, 2016

  1. 약속.js의 배열은 1부터 시작하는 인덱스에 맞추기 위해 첫번째 항목을 비워놓았습니다. 생각을 좀 덜 한 부분이긴 한데, 어떻게 개선하는게 좋을까요?
  2. 그런게 있었군요 (두둥)

@Qwaz
Copy link
Contributor Author

Qwaz commented Jan 5, 2016

JS에서 대괄호 접근을 오버라이드 하는 방법이 있으면 그걸로 offset을 줘도 될 것 같고, 아니면 Java처럼 YaksokList에 get, set 함수를 만들고 컴파일 될 때 그 함수들을 쓰도록 하는 방법도 있을텐데 급한 건 아니니 천천히 해도 될 것 같아요.

@disjukr
Copy link
Member

disjukr commented Jan 5, 2016

proxy를 사용하면 배열접근을 덮어씌우는 게 가능하긴 한데 es5에서는 불가능해요. (현재 구현체 중에서는 엣지랑 파이어폭스만 지원합니다.)
후자는 약속이 정적타입 언어가 아니기 때문에 런타임을 더럽게 만들지 않는 이상 불가능할 것 같아요.

@disjukr
Copy link
Member

disjukr commented Jan 5, 2016

배열 잘라내기는 따로 이슈로 등록하겠습니다: #38

@Qwaz
Copy link
Contributor Author

Qwaz commented Jan 6, 2016

후자는 약속이 정적 타입 언어가 아니기 때문에 런타임을 더럽게 만들지 않는 이상 불가능 하다는 부분이 잘 이해가 되지 않아요. 컴파일러 레벨에서 대괄호를 이용한 원소 접근이 L Value인지 R Value인지 구분하는 것으로 해결 가능하지 않나요?

@Qwaz
Copy link
Contributor Author

Qwaz commented Jan 6, 2016

YaksokList에 .get(index) => return this[index-1]; .set(index, value) => this[index-1] = value; 등으로 선언해 두고 다음과 같이 컴파일 할 때 바꿔주면 가능할 것 같은데요.

목록: [1, 2, 3] -> var 목록 = new YaksokList(1, 2, 3); //내부적으로 0-indexed로 들고 있음
목록[1] = 5 -> 목록.set(1, 5);
목록[3] 보여주기 -> console.log(목록.get(3));

@disjukr
Copy link
Member

disjukr commented Jan 6, 2016

대괄호를 사용한 원소 접근을 배열에 한해서만 허용한다면 그 이야기가 맞는 것 같아요.

저는 대괄호를 사용한 원소 접근은 자바스크립트와 동일하다고 생각했어요. 그렇다면 모든 객체가 get, set 메서드를 구현해야 된다는 뜻이 돼요. 그건 사실상 불가능하니 (예: 약속 런타임 바깥에서 들어온 값이라거나? 바깥에서 맞춰준다는 것도 가능합니다만..) get, set 메서드가 없는 경우 일반적인 대괄호 접근을 붙이는 코드가 추가적으로 필요해지죠.

#전제
목록: 어떤값 -> var 목록 = 어떤값; # 타입 모름

# 접근1: 쉬운데 더러움
목록[1] = 5 -> 목록.set? 목록.set(1, 5) : (목록[1] = 5);
목록[3] 보여주기 -> console.log(목록.get? 목록.get(3) : 목록[3]);

# 접근2: 귀찮
function yaksokGet(target, field) {
    if (target.get) { return target.get(field); }
    return target[field];
}
function yaksokSet(target, field, value) {
    if (target.set) { return target.get(field, value); }
    target[field] = value;
}

목록[1] = 5 -> yaksokSet(목록, 1, 5);
목록[3] 보여주기 -> console.log(yaksokGet(목록, 3));

# 정적분석으로 부분적으로 타입을 확정해서 최적화가 가능하긴 합니다.
# 지금 `console.log`와 `yaksokLog`를 분기하는 처리도 이런 느낌으로 되어있어요. (미완성)
목록: [1, 2, 3, 4, 5] # 이후로 목록 변수에 다른 값이 대입되지 않고, 사이드이펙트를 가진 약속이 호출되지 않는다면 당분간은 배열타입임을 확신할 수 있음
사전: {우왕: 'ㅋ'} # 역시 당분간 사전타입
목록[1] = 5 -> 목록.set(1, 5);
목록[3] 보여주기 -> yaksokLog(목록.get(3)); # `console.log`가 아니고 `yaksokLog`가 사용되는 이유는 목록 안쪽 항목의 타입을 알 수 없기 때문입니다.
사전['우왕'] = '굳' -> 사전['우왕'] = '굳';
사전['우왕'] 보여주기 -> yaksokLog(사전['우왕']);

만약 정적타입 언어라면 접근하는 변수가 배열타입인 경우에 한해서 get, set 메서드를 사용하도록 쉽게 분기할 수 있어요.

@Qwaz
Copy link
Contributor Author

Qwaz commented Jan 6, 2016

약속 자료형 중에 대괄호 인덱싱을 지원하는게 배열과 사전 밖에 없어서 간단할거라고 생각했는데 런타임 바깥에서 들어오는 값도 있군요. 그런데 애초에 보여주기에서 나오는 쉼표가 신경쓰이는 문제였으니 지금 구현을 그대로 두고 toString을 오버라이드 하는건 어떨까요.

@disjukr
Copy link
Member

disjukr commented Jan 6, 2016

사실 그거 아마 console.logyaksokLog 구분하는 쪽 버그.. (yaksokLog로 로그찍으면 앞에 쉼표 안뜰거에요)

@Qwaz
Copy link
Contributor Author

Qwaz commented Jan 6, 2016

이건 좀 치명적인 문제 같은데, 반복문에서도 0번째 undefined 원소가 사용됩니다.

약속 (식사) 먹기
    식사 + " 냠냠쩝쩝" 보여주기

하루: ["아침", "점심", "저녁"]
반복 하루 의 끼니 마다
    끼니 먹기

undefined 냠냠쩝쩝, 아침 냠냠쩝쩝, 점심 냠냠쩝쩝, 저녁 냠냠쩝쩝 순서로 출력됩니다.

@disjukr
Copy link
Member

disjukr commented Jan 6, 2016

아 그렇네요. 그건 이터레이터 코드를 수정하면 고칠 수 있기는 해요.

disjukr added a commit that referenced this issue Jan 7, 2016
@disjukr
Copy link
Member

disjukr commented Jan 7, 2016

반복에서 버그는 고쳤어염ㄹㄹ

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

No branches or pull requests

2 participants