First-class Function

First-class Function

  • 프로그래밍 언어 중 함수를 다른 변수와 동일하게 다루는 언어를 함수우선순위(First-class Functions) 가졌다고 표현한다.
  • 함수를 다른 함수의 argument로 사용하고, 함수에서 함수를 return하거나 변수의 값으로 함수를 할당할 수 있다.
  1. 변수에 함수를 할당
    1
    2
    3
    4
    5
    const foo = function() {
    console.log("foobar");
    }
    // 변수를 사용하여 호출
    foo();
  1. 함수를 인자로 전달
    1
    2
    3
    4
    5
    6
    7
    8
    function sayHello() {
    return "Hello, ";
    }
    function greeting(helloMessage, name) {
    console.log(helloMessage() + name);
    }
    // `sayHello`를 `greeting` 함수에 인자로 전달
    greeting(sayHello, "JavaScript!");
  • 다른 함수에 인자로 전달된 함수를 Call Back 함수라고 한다.
  • 다른 언어들과 같이 sayHello()를 호출하면 바로 실행되지만, 위와 같이 greeting(satHello, “)의 인자로 전달된 sayHello의 경우 greeting 함수의 helloMessage parameter로 전달된 후에, 필요한 경우 helloMessage()에서 호출된다.
  • 전달된 이후 나중에 호출되기 때문에 CallBack 함수라고 불린다.
  1. 함수를 return 값으로 전달 (함수 return)

    1
    2
    3
    4
    5
    function sayHello() {
    return function() {
    console.log("Hello!");
    }
    }
    • 함수가 함수를 반환하는 예시문. JavaScript에서는 함수를 변수처럼 취급하므로 함수를 return할 수 있다.
    • Higher-Order Function : 함수를 반환하는 함수

Call by Value, Call by Reference and Call by Object Reference

우선 Parameter와 Argument의 차이를 짚고 가도록 한다.

Parameter

The names given in the function definition are called Parameters.

Argument

The values supplied in the function call are called Arguments.

Call by Value

  • 함수를 호출할 때, 변수의 값을 복사하여 argument로 넘기는 것

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>

    void change_value(int x, int val) {
    x = val;
    printf("x : %d in change_value \n", *x);
    }

    int main(void) {
    int x = 10;
    change_value(x, 20);
    printf("x : %d in main \n", x);
    }

    Call by Value

    • 위 코드에서는 단순히 x에 10이라는 값이 복사되어 들어가기 때문에, change_value(x, 20)에서 x를 변경하더라도 main 함수에서의 x에 영향을 미치지 못한다.

Call by Reference

  • 함수를 호출할 때 변수의 값을 넘기는 것이 아니라, 변수의 주소(변수의 위치)를 복사하여 함수에 넘긴다.

  • 넘겨받은 주소로 실제 변수에 접근하고 값을 변경할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>

    void change_value(int * x, int val) {
    *x = val;
    printf("x : %d in change_value \n", *x);
    }

    int main(void) {
    int x = 10;
    change_value(&x, 20);
    printf("x : %d in main \n", x);
    }

    Call by Reference

  • 주소값을 전달 (참조값을 전달) : 주소값을 알고 있으면 해당 memory 주소에 저장되어있는 값을 참조할 수 있다.

  • *x가 x를 참조하고 있다 : 가리키고 있다.

    이를 이해하기 위해서는 pointer에 대한 이해가 필요하다.

  • Pointer

    1
    2
    3
    int *pnum;
    int num = 12345;
    pnum = &num //num의 주소값을 return하여 pnum에 저장
    • 변수를 만들 때 변수 이름 앞에 *를 붙이면 pointer 변수 됨
    • &연산자: &오른쪽에 오는 피연산자의 주소값을 반환
    • *연산자: 포인터가 가리키는 메모리 공간에 접근할 때 사용되는 연산자. 포인터 변수를 이용해 포인터 변수가 가리키는 변수의 값을 바꿀 수도 있다.

Call by Assignment (Call by Object Reference)

The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object). [1] When a function calls another function, a new local symbol table is created for that call.

이 문장이 나를 얼마나 헷갈리게 했는지 모른다. 그러니까 Python에서는 function의 argument가 call by value로 넘어오는데, 그 value는 언제나 object의 값이 아닌 object의 reference라는 것이다.

Actually, call by object reference would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list).

정확하게는 call by object reference라는 설명이 더 맞다. 왜냐면 mutable 객체가 넘어올 때에는 call by reference처럼 원본 값을 변경할 수 있기 때문이다.

  • 파이썬은 모든 것이 object이고, Object에는 두 종류가 있다.
  1. Immutable object
    • int, float, str, tuple
    • Immtable 객체가 함수의 인자로 전달되면, 처음에는 call by reference로 받지만 값이 변경되면 call by value로 동작한다.
    • 즉, 함수 내에서 formal parameter 값이 바뀌어도 actual parameter에는 영향이 없다.
    • 함수 내부에서 값을 변경할 수 없다!
    • 그래서 tuple은 변경하려면 함수에서 element와 tuple 인자로 넘겨 아예 새로 할당해줘야 함
  2. Mutable object
    • list, dict, set
    • Mutable 객체가 함수의 인자로 넘어가면 call by reference도 동작한다. 즉, object referene가 전달되어 actual parameter의 값에 영향을 미칠 수도 있다.
    • 새로운 객체를 할당하는 게 아니라면, 함수 내부에서 값을 변경할 수 있다!

정리

  • Python은 함수를 실행할때 Call by reference같은 느낌으로 reference를 넘겨준다. 하지만 이때 넘겨주는 것은 변수(Variable)의 reference가 아니라 변수가 담고 있는 자료(Data)의 reference이다.
  • 자료가 mutable하다면 변경해도 reference가 보존되므로 결과적으로 Call by reference처럼 보일 것이고, 자료가 immutable하다면 결과적으로 Call by value처럼 보일 것이다.

Local Variable and Global Variable

전역변수 (global variable) / 지역변수 (local variable)

  1. 변수의 scope와 lifetime
  • 변수는 선언하는 순간부터 속한 scope 내에서 lifetime을 가진다. 즉, 특정 범위의 코드가 실행되고 있을 때는 메모리에 존재하지만, 실행이 끝나면 이 변수는 메모리에서 사라진다.
  1. 변수의 선언 위치

    a. Block 외부 : block({})으로 감싸진 main 함수와 여러 함수들의 외부 공간에 변수를 선언할 수 있다.

    b. Block 내부 : block 내부에 변수를 선언할 수 있다. C는 block의 최상단에 모든 지역변수를 선언해야한다.

    c. 함수의 parameter : 함수의 매개변수는 그 함수의 block 내에서 선언된 변수와 동일한 효과를 갖는다.

  2. 전역변수 (a case)

  • Block 외부에 선언되는 변수. 전역 변수는 프로그램이 시작되는 순간부터 종료되는 순간까지 메모리를 차지하고 있으며 사라지지 않는다.

  • C라면 main() 위, #include <stdio.h>와 함수 원형 밑 그 사이에 선언

  • 전역변수는 어느 block에서도 언제든지 접근이 가능하다 > sycncrinize 고려

  1. 지역변수 (b case, c case)
  • 지역변수는 block 내부에서 선언되는 변수이다. { } 안에 선언되어있다면 무조건 지역변수

  • 지역변수는 선언된 block 내부로 scope가 한정되며 그 block의 실행이 끝나면 lifetime 또한 소멸된다.

  • 함수의 parameter로서 선언되는 local variable도 이와 같다. 함수 body 내에서 선언되는 것과 똑같다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×