PEP 505와 Walrus operator

구경회·2024년 1월 22일
0

PEP 505

python에 관심이 많은 사용자라면 PEP에 대해서는 어느 정도 알고 있을 것이다. 그리고 이 PEP 제안 중 유명하고 논란이되는 것 중 하나가 PEP 505 – None-aware operators
이다. 아마 모던한 언어를 사용해봤다면, 다음과 같은 구문에 익숙할 것이다.

// case 1
const x = nullable_value?.foo?.bar
// case 2
const y = nullable_value ?? default_value

하지만 위 구문을 파이썬으로 작성하려면 다음과 같이 작성해야 한다.

# case 1
x = None
if nullable_value is not None:
    tmp = nullable_value.foo
    if tmp is not None:
          x = tmp.bar
  
# case 2
y = None
if nullable_value is None:
	y = nullable_value
else:
    y = default_value

case 2를 다음과 같이 쓰고 싶은 유혹에 빠질 수 있다.

y = nullable_value or default_value

하지만 위 코드에는 심각한 결함이 있다. Python에서 ortruthy를 기준으로 하지 None인지를 따지는 것이 아니기 때문이다. 예를 들어 0 같은 값의 경우 falsy value기 때문에 default_value를 할당하게 된다.

사실 위 코드도 어느정도 결함이 있다. 예를 들어 다음과 같은 경우를 생각해보자.

y = None
if math.sin(theta) is None:
	y = math.sin(theta)
else:
    y = default_value

이 때 math.sin의 호출은 두 번 이루어진다. 이처럼 여러 가지 위험을 피해가며 none-aware한 코드를 작성하는 것은 쉬운 일이 아니다.

위 문제들을 해결하기 위해 PEP 505는 kotlin, ruby, typescript 등이 가지고 있는 ?, ?? 등을 제안한다. 하지만 PEP의 운영에 대한 논의나 언어에 대한 합의가 이루어지지 않아 파이썬 스펙으로는 들어오지 못하게 된다.

주요 반대 논의는 ?None을 특별한 것으로 취급해 나쁜 코드를 쓰게 만들고 Zen of python을 손상시킨다는 것이다.

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

하지만...

:=, Walrus Operator

귀도 반 로섬을 BDFL (Benevolent Dictator For Life, 자비로운 종신 독재자) 위치에서 내려오게 만든 논란의 Walrus operator가 등장한다. 흔히 바다코끼리 연산자 (Walrus operator)라 부르는 연산자는 다른 언어처럼 할당한 값을 반환한다.

참고로 귀도가 이 Operator에 반대해서 내려온 것은 아니다. 귀도는 PEP 505와 walrus operator 모두 호의적인 입장이었다.

x = 42 # None
x := 42 # 42

Walrus operator는 정확히 위 PEP 505가 반대를 받은 이유들과 동일한 이유들로 동일한 비판을 받았다. 언어를 펄화 (언어를 펄처럼 엉망으로 만든다)는 비난까지 들으면서 말이다. 하지만 결국 Python 3.8에 들어오게 되었다. 물론, 들어오고 나서도 논란은 끊이지 않는다.

Have they also removed Zen of python in 3.8?

Since I don't see how those two can coexist, when this feature clearly violates it a lot.

나는 PEP 505가 리젝되었을 때는 마치 Golang처럼 언어를 아주 작고 단순한 집합으로 유지하고 싶은 욕망으로 이해할 수 있었다. 하지만 바다코끼리를 마주한 순간 나는 이 논리적 비일관성 때문에 불경처럼 서러워졌다.

어떤 선택이 옳았을까?

나는 사실 walrus operator는 필요 없고 none-aware operator는 필요하다고 생각한다. 정확히는 :=를 추가하는 대신 =가 command가 아니고 Expression으로써 값을 반환해야 한다고 생각한다.

  • None은 충분히 특별하다. 그렇지 않다면 왜 우리가 x == None이 아니고 x is None으로 쓰는 걸까?
  • 언어는 프로그래머가 실수할 여지를 줄여야한다. 파이썬을 만들면서 C에서 === 대신 써서 버그가 많아 =의 Return value를 없앴다고 하지 않았나? is None을 반복적으로 체크하는 위 코드도 실수하기 쉽다. 언어 차원에서 올바른 가이드를 제공하는 것이 낫다.

PEP 505나 Walrus operator는

  1. 좀 더 지원하는 기능이 많고 편리한 언어가 될 것이냐
  2. 보일러플레이트가 많더라고 적은 수의 기능집합을 유지할 것이냐

의 갈림에서 1번을 선택하는 길이라는 공통점이 있다. 그렇다면 논리적으로 하나의 선택지로 귀결되어야 하고, 그렇다면 둘 다 받아들이거나 둘 다 거부했어야 할 것이다. 하지만 안타깝게 하나의 기능은 Python 3.8에 추가되었고 하나는 거부되었다. 이해할 수 없는 선택이다.

같이 읽어볼만한 글

profile
즐기는 거야

2개의 댓글

comment-user-thumbnail
2024년 2월 22일

정기적으로 PEP-505 관련 파생 제안들을 찾아보다가 오랜만에 마음이 맞는 글을 찾은 것 같습니다. 좋은 글 감사합니다~

1개의 답글