LangDev

프로그래밍 언어 개발에 관심 있는 사람들의 모임입니다.

여러 값 반환

2009-05-27 16:17:19

어떤 프로그래밍 언어는 여러 값(multiple value)을 지원합니다. 함수가 여러 인자를 취할 수 있듯이, 여러 값을 반환할 수 있어야 한다는 것이죠. 이것은 여러 값을 담을 수 있는 튜플 같은 자료 구조를 제공하는 것과는 다릅니다.

파이썬은 한 값만 반환할 수 있기 때문에, return 1, 2를 하면 (1, 2)라는 튜플이 만들어지고, 반환된 다음에 unpack 됩니다. (1, 2) 자체가 값이기 때문에, unpack 하지 않으면 튜플이 저장됩니다. 예를 들면,

C:\>python
Python 2.6.1
>>> def f(): return 1, 2
>>> a, b = f()
>>> c = f()
>>> print a, b, c
1 2 (1, 2)

여러 값 반환을 하는 루아와 비교해 봅시다. 루아에서 return 1, 2는 (1, 2)라는 튜플을 만들지 않습니다. (루아에는 테이블만 있고 튜플이란 게 없지요.) return {1, 2}와는 다르다는 말입니다.

C:\>lua
Lua 5.1.4
> function f() return 1, 2 end
> a, b = f()
> c = f()
> print(a, b, c)
1 2 1

루아는 (여러 값 반환을 지원하는 다른 언어와 마찬가지로) 대입하는 쪽에 숫자가 맞지 않으면 남은 값을 버리기 때문에, c에는 1, 2가 들어가는 것이 아니라 1만 들어갑니다.

커먼 리습의 예는 다음과 같습니다.

C:\>clisp
GNU CLISP 2.47
[1]> (defun f () (values 1 2))
[2]> (setf (values a b) (f))
[3]> (setf c (f))
[4]> (print (list a b c))
(1 2 1)

트랙백 주소: http://langdev.net/post/trackback/290

  1. 서상현 2009-05-27 16:30:52

    차이점을 분명히 하기 위해 루아에서 테이블을 반환하는 경우를 살펴보겠습니다. 이 경우에는 수동으로 unpack을 해 주어야 합니다.

    > function f() return {1, 2} end
    > a, b = f()
    > print(a, b)
    table:003CBD60 nil
    > a, b = unpack(f())
    > print(a, b)
    1 2
    
    
  2. 까막 2009-05-28 10:23:39

    C++에서도 씁니다. :) 언어기능이 아니라 라이브러리 기능이긴 하지만요.

     int price = 0;
     std::string name = 0;
     boost::tie(price, name) = lookup_price_and_name(code);
    
    

    boost::tuple라이브러리에 있는 기능입니다.

  3. 홍민희 2009-05-28 10:36:55

    PHP에도 있긴 한데 거의 안 씁니다.

    function f() { return array(1, 2); }
    list($a, $b) = f();
    
    
  4. 김우승 2009-05-29 23:30:15

    생각해보니 필요한 데가 있었던 것 같은데 안 쓴 것 같네요. PHP 잘 쓰는 사람들은 많이 쓸 듯…

  5. 아겔-_- 2009-05-28 10:43:54

    팩터에서는 굳이 차이가 없습니다.

    : gimme-multi-vals ( -- a b ) 1 2 ;
    gimme-multi-vals + .
    
    
  6. 김우승 2009-05-29 23:29:03

    이해가 안 가서 Factor를 배우고 싶게 만드는군요.

  7. daewon 2009-05-28 21:51:01

    erlang은 파이썬과 동작이 같네요.

    F = fun() -> {1, 2} end.
    {A, B} = F().
    C = F().
    
    A.
    -> 1
    
    B. 
    -> 2
    
    C.
    -> {1,2}
    
    io:format("~p, ~p, ~p~n", [A,B,C]).
    -> 1, 2, {1,2}
    
    
  8. semmal 2009-05-29 12:30:25

    두 개의 인자를 받고 하나의 결과를 표현할 때, 결과가 같은 치역을 가질 수 있도록 표현하려면, logic 일 때 A X B X C 이고, function 일 때 A X B -> C’ 일때 C’은 C의 power set이 됩니다. C’은 고정 길이가 아니기때문에 logic과 비슷하게 함수를 만든다면 튜플보다는 리스트나 스트림 시퀀스가 더 로직 프로그래밍에 가깝지 않을까 생각해봅니다. 그런데 이게 무슨 상관이람… 쩝.

  9. 홍민희 2009-05-29 15:02:58

    새는 얘기지만 오랜만입니다. 요즘 어떻게 지내세요?

  10. semmal 2009-05-29 17:45:54

    인터넷도 쓸 수 없는 곳에서 어언 반 년동안 장기 외근 중입니다. 다음 달 즈음부터는 자주 올 수 있을 지 모르겠네요.

  11. 김우승 2009-05-29 23:30:38

    이해 안감… -_-

  12. semmal 2009-05-30 07:53:11

    관계는 결과값이 여러 개가 될 수 있다는 사실은 아실겁니다. 함수는 단 하나의 결과값을 가지죠. 하지만, 관계식을 약간 변형하면 함수가 관계식과 비슷한 결과를 낼 수 있도록 수정할 수 있는데, 그게 바로 복합데이터(튜플,리스트,시퀀스 등)로 가능한 결과값을 묶어서 내는 겁니다. R : A X B X C에서 C가 {0,1,2}라면, F : A X B X C’에서 C’은 {Θ,{0},{1},{2},{0,1},{0,2},{1,2},{0,1,2}}가 된다는 겁니다. R의 결과값은 집합 C에서 아마도 몇몇 원소만을 골라내게 될텐데, 그 가능한 결과를 따져보면 C의 power set과 같다는 거지요.

  13. 김우승 2009-05-30 23:54:55

    개인적으로 이산수학을 좋아한다고 생각했는데 이산수학 공부부터 다시해야 겠네요. 관계대수는 알고 있습니다만… 그것이 PL과 어떤 의미를 지니는지 고찰도 해봐야 될 것 같고요. 저는 Prolog 를 거의 접하지 않았기 때문에 더욱 이해가 안 갑니다.

    하여간 설명해주셔서 감사해요.

  14. lifthrasiir 2009-06-08 23:43:05

    종종 Octave를 쓰곤 하는데 반환값의 갯수에 따라서 다른 결과를 내는 경우가 있습니다.

    octave-3.0.3:1> factor(11172)
    ans =
    
        2    2    3    7    7   19
    
    octave-3.0.3:2> [P, Q] = factor(11172)
    P =
    
        2    3    7   19
    
    Q =
    
       2   1   2   1
    
    

    아마 Matlab에서 유래한 게 아닐까 싶습니다만, 하여튼 반환값의 갯수가 funcation signature에 들어 가는 게 흥미롭습니다. (뭐 펄에서는 함수가 호출된 문맥에 따라 다른 결과를 반환합니다만 이건 갯수를 따지니까요.)

  15. 홍민희 2009-06-10 09:18:46

    반환값 갯수에 따라 오버로딩이 되는 건가요? 패턴 매칭에 가까운가?

목록보기

← 2009년 6월 8~11일 이것저것 | 2009년 6월 5일 이것저것 →