03. Names, Scopes, and Bindings - (2)

Jimin Lim·2021년 11월 2일
0

Programming Language

목록 보기
3/9
post-thumbnail

3.5 The Meaning of Names within a Scope

:이전까지 다뤘던 내용은 이름과 객체간의 관계는 일대일 관계였음

Aliases

두 개 또는 그 이상의 이름이 같은 오브젝트를 가리킴 (별칭)
한 개 object에 이름 여러 개, 같은 공간에 접근함

  • union
typedef union {
	int mem1;
   	int mem2;
   	double mem3;
} UBox;
  • pass by reference
double sum, sumOfSquares;
...
void accumulate (double& x){
	sum += x;
    sumOfSquares += (x * x);
}

accumlatue(sum);

Overloading

한 개의 이름이 여러 개의 오브젝트를 나타냄

  • 다형성과 연관 있음
  • C : + 연산자가 여러 가지 다양한 함수로 사용됨 (double, int 타입 등등)

  • 위의 경우 month, print_base 중 어디 것을 의미하는지 모호함
  • Symbol table 에서는 Lookup 함수를 사용해서 특정 이름 찾음
    • 가능성이 있는 것을 리스트로 나타내고, context에 맞춰서 선택 결정한다.
    • 위의 상황처럼 모호하면 오류 발생
    • Modula-3 & C#: type name을 앞에 명시해줘야함
      • explicit하게 month'(oct) 명시
  • C 언어: 오버로딩 매우 제한됨
  • C++ → 스코프를 새로 만듦: 감춰져서 안보이게 됨
  • enum constant는 구별이 가능해야 한다 → enum class 를 사용하면 사용 가능
    • month::OCT와 같이 연산 씀
  • 갯수, 타입이 다른 것을 가질 때 오버로딩 가능
  • Built-in Operators오버로딩 가능
    • Ada 에서 prefix를 사용해야하는데 Infix사용할 수 있도록 함
    • C++,C#: operator+(A,B) or A.operator+(B)
    • Syntax sugar: 문법적으로 사용하기 쉽도록 (A+B)
    • Haskell : 연산자 정의 가능
      • 연산자의 우선 순위 따름, 결합 방식
  • Overloadig: 같은 이름을 가진 여러 개 의 오브젝트

Coercion

컴파일러가 자동으로 형 변환
(void f(double a), f(2) → (정수)다른 타입 넘김)

Polymorphism

다형성, 하나의 서브 루틴에 다양한 인자 타입을 허락함

void f(Object o)

: 모든 클래스 전달 가능 (부모 클래스로부터 상속받은 자식 클래스)

1. Overloading은 같은 이름의 여러 개의 객체를 프로그래머에게 허용, 문맥에 근거해서 명확히 구분 짓는다. 인자의 갯수, 타입이 다른 것을 가질 때 오버로딩이 가능하다.

2. Coecion은 **컴파일러**가 예측되어지는 타입으로 자동 변환하는 것을 허용한다

3. Polymorphism은 한 개의 서브 루틴에 여러 개의 타입의 argument을 가지는 것을 허용한다. (interface를 구현하거나 상속하는 object)
  • print: 화면에다 출력함, 다양한 타입을 받을 수 있음
    • overloading: 여러 개 함수 만들면 됨 (타입별)
    • print(my_object)타입이 있는지 확인 → 없으면 오류를 내거나 my_object의 부모 클래스를 찾음 or coercion으로 인해 자동 형변환
  • java: toString()
    • 많은 타입에서 toString() 지원
    • 부모 함수 호출 처럼 보이지만 overriding 한 함수 호출

3.6 The Binding of Referencing Environments

  • Referencing Environments: 프로그램을 실행시키다가 한 순간에 멈췄을 때 유효한 함수 및 변수 즉 바인딩
  • 스코프 룰: 프로그램 내에서 지정된 statement의 referencing environment에 의해 결정됨 (그때 사용할 수 있는 함수, 변수)
  • Static scope rules: 프로그램을 실행하지 않아도 알 수 있음
  • Dynamic scope rules: 프로그램을 실행시켜봐야 알 수 있음
  • 함수가 파라미터로 전달하는 경우? → 어떤 스코프를 사용해야 하는지
    • 함수 자체가 호출되는 시점 (1. 전달할 때 reference is first created, 2. 그 함수를 호출할 때: routine is finally called)
  • Deep binding: reference가 만들어질 때 → 구조적으로 가장 상위의 것
  • Shallow binding: 서브 루틴이 호출될 때 → 가장 최근에 호출된 곳에서 값 가져옴
    • 파라미터로 전달된 함수가 late binding (호출되기 직전)

  • threshold → 어디선가 가져와야하는 변수

  • 다이나믹 스코프: line_length를 print_selected_records 내에서 만들고 값을 지정해줘야함 → print_routine 에서 사용
    • print_routine 사용 직전: shallow (다이나믹 스코프는 기본 shallow)
      • line_length를 사용할 수 있어서
    • threshold 라는 변수를 print_selected_record가지고 있다면
      • main에서 지정하더라도 덮어씌게 되니까 deep binding이 적합함

3.6.1 Subroutine Closures

  • Deep binding 은 함수 전달 직전 bundling 해서 보내야함
  • closure: 배낭을 매고 있는 함수, 함수 자체와 함수에 사용할 Reference environment(그 당시의 값이 아니라 그 당시의 reference를 의미)를 포함함
  • dynamic scoping의 default: shallow binding
    • dynamic scoping → deep binding 필요하는 경우 있음
      • 빌트인 함수를 통해서 사용 가능
      • 호출할 함수를 인자로 전달 받고 클로저를 반환해줌 → 클로저를 파라미터로 전달 가능
  • static scoping → deep binding(전달할 때) 만 사용
    • shallow binding 일때는 지역변수로 지정하면 다른 함수에서는 안보이는 영역이기때문
    • static scoping 은 shallow binding 은 사실 의미가 없음 → 덮어씌여지니까 (즉, 디폴트는 deep binding )
    • 만약 오브젝트가 현재 실행 중인 서브루틴의 로컬일 경우, 서브루틴이 직접적으로 호출되었는지 혹은 클로저를 통해서 호출되었는 지는 중요한 것이 아님
      • 두 경우 모두 다 로컬 오브젝트가 서브루틴이 시작할 때 생성된 것이기 때문임
      • 지역 변수는 안보이는 영역이므로 영향 받지 않음
    • 전역 변수 → 한 개 이상의 인스턴스가 존재할 수 없음 → 똑같은 값 유지: g_x

  • Deep: 함수 넘길때 → 1
  • Shallow: 함수 호출 직전 → 2
  • 자바 스크립트의 클로져
    • localVariable은 testClosure()의 지역 변수로, testClosure()가 종료되면 함께 사라지는 변수지만 이 경우에서 function()이 반환 될때 localVariable도 함께 묶여서 반환되도록 한다.

3.6.2 First-Class Values and Unlimited Extent

First- Class

ex) C# / 제한 존재 - C, C++, imperative 언어, Fortan, Modula-2, Modula-3, Ada95

프로그래밍 언어에서 세 가지 조건 만족

  1. (함수, 변수) value를 인자로 전달 가능
  2. 서브 루틴으로부터 반환 받기 가능
  3. 변수에 할당 가능
  • outlive: 함수 리턴하고 나면, 함수 벗어난 영역에서 사용 로컬 오브젝트가 destroy된 후, x에 대한 내용도 가지고 있음 → 로컬 오브젝트가 unlimited extent → 라이프 타임은 더 길다. → garbage 콜렉터에서 더 이상 사용하지 않는다고 판단하면 reclaim → heap (끝날 때까지 들고 있음) limited → stack
    • 대부분의 imperative 언어는 local object는 limited extent를 가지고 스코프 끝에서 파괴됨

    • x가 사라진 후 x를 사용하고 있음

    • plus-x안의 x를 f의 referencing environment에서 참조

Second-Class

ex) 대부분 imperative 언어

  • 조건1 만족, 2 or 3 불가

Third-Class

ex) Ada

  • 조건1 만족 안함

3.6.3 Object Closures

  • nested subroutines 없을 때는 서브루틴 context와 함께 전달하는 것을 못할 수 있음
  • object-oriented
    • 객체를 만들고 그 객체에 nested subroutine의 변수를 메소드에 넣고 객체를 넘긴다.

    • 오브젝트는 마치 함수인 것처럼 호출

    1. 함수의 객체화 (static 이용 → 제한적)

    2. 객체에 있는 함수

    • 이름이 없는 함수 사용

    • C++

    • object인데 함수 역할: functor

3.6.4 Lambda Expressions

  • C#: delegate 키워드 사용

  • 람다 표현은 코드 재사용성과 일반화를 도움
    • 즉석에서 새로운 함수를 만들어 냄
    • call back: 메인 프로그램으로 라이브러리가 콜백 하는 것을 허용
      • 먼저 만들어진 일반화된 함수에 Compare에서 불러서 씀

        // In JAVA
        class AgeComparator implements Comparaotr<Person> {
          public int compare(Person p1, Person p2) {
            return Integer.compare(p1.age, p2.age);
          }
        }
        Person[] people = …
        …
        Arrays.sort(People, new AgeComparator());
        Arrays.sort(People, (p1, p2) -> Integer.compare(p1.age, p2.age))
    • filter
      • predicate: 2021년 노래 뽑기 등등 톨렉션의 요소를 필터링
    • event handler
      • 미래 이벤트에 응답할 때 호출

Lambda Expression in C++

  • vector: 크기가 정해지지 않은 배열

  • 50이하 원소 출력
    • 벡터의 모든 요소에 대해 마지막 인자의 함수를 적용함
  • k가 밖에 정의되어 있을 때

  • = : 복사본 사용 → 오래 걸림, deep binding을 해도 영향을 주지 않음 (함수 호출 전)
  • &: 같은 공간 사용 → 시간 빠름, 밖에서 값이 바뀌면 값이 바뀔 수도

Lambda Expression in JAVA

  • Comparator를 구현한 클래스의 배열을 받아서 정렬해줌 (Arrays.sort)
  • 함수 하나만 가지고 있는 인터페이스(fuctional interface)
    • 를 넘길때 람다를 대체할 수 있음
    • interface를 사용하는 익명 클래스 생성함 → 객체 생성(전달)
    • 파라미터, 리턴 타입 같아야 함

3.7 Macro Expansion

  • 어셈블리 언어 프로그래머들은 반복되는 코드를 잘 찾을 수 있도록 매크로 사용함
  • 함수로 만들면 느리지만 매크로는 그대로 바꿔치기 때문에 효율적일 수도

  1. 그대로 치환 → 산술 연산에서 우선 순위로 인해 원하는 결과가 나오지 않을 수도
  2. 겹치는 문제 발생
  3. 수도 없이 증가
  • 최근에는 지양하는 추세
    • C 는 어쩔 수 없이 사용
  • named constants 지원
    • const int a = 3; : type-safe, 구현 쉬움
  • inlined subroutine
    • 치환이지만 타입 체킹함
    • 치환에서 속도가 비슷함
  • Scheme, Comon Lisp → max 문제 여전히 존재
profile
💻 ☕️ 🏝 🍑 🍹 🏊‍♀️

0개의 댓글