1P by GN⁺ | ★ favorite | 댓글 1개
  • Raku는 Python, J, Frink, Excel의 수학 작업상 빈틈을 메울 계산기 언어 후보로 검토됐고, 짧은 실험만으로도 매우 강력하지만 기묘한 언어라는 인상을 줌
  • Unicode 기호, 영숫자 중위 연산자, 리스트 곱·zip·리듀스·누적, ~~ 매처, ... 시퀀스처럼 연산자 중심 표현력이 넓음
  • 사용자가 중위 연산자뿐 아니라 circumfix/postcircumfix 연산자까지 정의할 수 있고, 결합성도 좌·우 결합을 넘어 체인·리스트 결합까지 지정 가능함
  • 다중 디스패치는 타입 시그니처뿐 아니라 where 런타임 조건자로도 분기하며, 함수 시그니처와 그 안의 파라미터도 일급 값으로 다룰 수 있음
  • 큰 코드베이스 유지보수에는 부담이 커 보이지만, 일회성 스크립트·계산·개인 도구 같은 작은 규모 프로그래밍에는 매력적이며 문서, Windows REPL, 컴파일 속도, sigil 실수가 주요 걸림돌임

Raku를 살펴본 계기와 첫인상

  • Raku는 과거 Perl 6로 알려졌던 언어임
  • 동적 언어에 대한 불만을 쓴 뒤 몇몇 사용자가 Raku를 추천했고, 수학 작업에 쓸 계산기 언어로 적합한지 확인하기 위해 살펴봄
  • 기존에는 Python, J, Frink, Excel을 섞어 썼지만 각각 큰 단점이 있었음
  • 며칠간 실험한 뒤 받은 인상은 “정말 똑똑한 그렘린들이, 다른 그렘린들의 피드백을 많이 모아 설계한 언어”에 가까웠음

특이한 연산자 체계

  • Raku는 Unicode 연산자를 적극적으로 씀
    • 집합 포함 여부는 로 확인함
    • , , 도 있음
  • 영숫자 중위 연산자도 허용함
    • 문자열 반복 연산자는 x
    • 함수 합성은 o
  • 리스트 조합도 짧은 기호로 표현함
    • X는 리스트의 카테시안 곱을 만듦
    • Xf는 카테시안 곱의 각 요소에 f를 적용함
    • Zf는 zip 방식으로 같은 일을 함
  • 중위 연산자 f에 대해 [f]는 리스트를 리듀스하고, [\f]는 누적 결과를 만듦
    • [+] <1 2 3 4 5>15
    • [\+] <1 2 3 4 5>(1 3 6 10 15)

~~ 매처와 ... 시퀀스

  • ~~는 여러 종류의 비교를 한 문법으로 처리하는 매처로 쓰임
    • "abc" ~~ "abc"는 문자열 일치를 확인함
    • "abc" ~~ Str은 문자열 타입인지 확인함
    • "abc" ~~ {.chars == 3}은 길이가 3인지 검사함
    • "abc" ~~ /^b/abcb로 시작하는지 확인함
  • ...는 앞의 값들에서 패턴을 잡아 시퀀스를 만듦
    • 0,1,2...100부터 10까지 1씩 증가함
    • 0,2,4...10은 짝수 시퀀스가 됨
    • 1,2,4...101 2 4 8처럼 증가 패턴을 따름

사용자 정의 연산자

  • Raku는 일부 언어처럼 중위 연산자만 정의하는 데 그치지 않고, circumfixpostcircumfix 연산자도 만들 수 있음
  • 예를 들어 sub circumfix:<[∀ zz>($inner){sum($inner)}처럼 둘러싸는 연산자를 정의해 내부 값을 합산할 수 있음
  • 벡터 내적처럼 보이는 postcircumfix 연산자도 정의 가능함
    • sub postcircumfix:<| ⟩>(@left, @inside){[+] (@left Z* @inside)}
    • <1 2 3>|<4 5 6>⟩32
  • 연산자 결합성도 다양하게 지정할 수 있음
    • 일반적인 좌결합·우결합 중위 연산자를 정의 가능함
    • x < y < zx < y && y < z처럼 해석되는 체인 결합을 지정할 수 있음
    • a op b op cop(a, b, c)가 되는 리스트 결합도 지원함

다중 디스패치와 런타임 조건 분기

  • Raku는 다중 디스패치를 지원해, 서로 다른 타입 시그니처를 가진 여러 함수 정의 중 적절한 것을 고름
  • 예시 함수 f는 인자 조합에 따라 다르게 동작함
    • 스칼라와 배열을 받으면 배열 각 요소에 스칼라를 더함
    • 배열과 스칼라를 받는 경우도 지원함
    • 두 배열을 받으면 Z+로 각 요소를 더함
  • 더 특이한 점은 값의 런타임 조건자로도 디스패치할 수 있다는 점임
    • multi my_abs(Int $x where {$x > 0}) {$x}
    • multi my_abs(Int $x) {-$x}
  • 함수의 시그니처는 일급 값이며, 시그니처 안의 파라미터도 일급 값임

작은 기능들이 만드는 넓은 표면적

  • MAIN 함수를 정의하면 그 파라미터가 자동으로 CLI 플래그로 변환됨
  • 객체에는 미리 제공되는 메서드가 매우 많음
    • List object는 모든 순열, 모든 k-조합, 모든 슬라이딩 윈도를 얻는 메서드를 제공함
  • Junctions는 한 번에 여러 비교를 하기 위한 특이한 값 형태임
    • 1|2any(1, 2)로 확장되어 1 < 1|2가 성립함
    • 1&2all(1, 2)로 확장되어 1 !< 1&2가 성립함
  • 어떤 중위 연산자든 앞에 !를 붙여 부정 연산자로 만들 수 있음
  • Raku는 $kebab-case 이름과 중위 뺄셈을 동시에 가진 언어로 보이며, sigil이 x-y를 구분하게 해주는 것으로 추정됨
  • regex syntax는 Perl 5와 하위 호환되지 않음
    • 30년 동안 언어들이 PCRE “표준”을 따랐지만, Perl 6는 이를 버렸음

아직 보지 못한 영역과 작은 규모에서의 매력

  • 살펴본 내용은 계산기 용도 중심의 일부 기능에 불과함
  • 아직 객체 시스템, 패키지, grammars는 배우지 않았음
  • 함수 본문에서 samewith가 같은 함수를 새 인자로 다시 호출하는 기능처럼, 빠진 기능도 많음
  • Raku 레거시 코드베이스를 유지보수해야 한다면 매우 힘들 것 같지만, In The Small 프로그래밍에는 강력해 보임
    • 일회성 스크립트
    • 계산
    • 개인 도구
    • 처음에 원했던 종류의 작업

불만과 기대

  • 문서가 매우 부족하고, 기호 의존도가 높아 검색이 어려움
    • 문서가 부족한 언어를 여럿 배운 경험이 있어도, Raku는 그보다 훨씬 크고 복잡해 동기부여가 떨어질 수 있음
  • Windows에서 REPL에 Unicode를 입력하면 크래시가 남
  • 컴파일러도 꽤 느려 작은 파일도 0.5초 이상 걸리며, 반복 작업이 고통스러움
  • sigil 체계가 불편함
    • $x@x 대신 써서 문제를 디버깅하는 데 30분을 쓴 사례가 있음
  • 전반적으로 Raku가 마음에 들고 성공하길 바라지만, 시간이 지나며 컴파일 시간과 문서가 개선되길 기대함

댓글과 토론

Hacker News 의견들
  • 프로그래밍 언어를 2차원 공간에 놓는다면 축은 얼마나 놀라게 하는가와, 놀랐을 때 즐거운가/끔찍한가가 될 수 있음
    정상적인 언어는 보통 “거의 놀라게 하지 않지만, 가끔 놀라게 해도 즐거운” 좌하단에 있어야 한다고 암묵적으로 기대하는데, Raku는 드물게 비어 있는 좌상단을 대놓고 지향하는 느낌임. “이상하지? 멋지지 않아?”라는 태도에 가까움

    • 그 축들은 주관적이라 문제임. 어떤 것은 즐겁고 끔찍할 수 있는데, 예전에 document.write = function ... 같은 JavaScript를 쓴 적이 있고 필요한 일을 해냈다는 점에서는 즐거웠지만 동시에 꽤 끔찍했음
    • 대학 과제로 파서를 만들어야 했을 때 Raku의 grammar 기능을 알게 됐고, 거의 모든 걸 대신 해줘서 치트키처럼 느껴졌지만 그래도 재미있었음
    • 원래 Perl 6였으니 Perl 개발자들이 다른 언어와 전혀 닮지 않은 언어를 원했다는 게 놀랍진 않음
      Perl에도 “즐거운 놀라움”이 많았고, Raku는 주로 Perl의 끔찍한 놀라움을 없애려는 설계였다고 봄
    • 로 집합 포함 여부를 확인한다는 대목에서 무슨 뜻인지 알겠음
      0,2,4...10(0 2 4 6 8 10)이 되는데, 1,2,4...10(1 2 4 8)이 되는 건 “OEIS에서 다음 수를 찾는 건가?” 싶어짐
    • Raku는 문단이 넘어갈수록 점점 우상단, 즉 놀랍고 끔찍한 영역으로 가는 것처럼 보였음
  • Raku는 언어로서는 흥미롭지만, 일부 관용구가 머릿속에 잘 들어오지 않음
    AppleScript가 자연어처럼 보이려다 이상하게 느껴졌던 것과 비슷하게, my, say, sub, gather 같은 자연어풍 요소와 @ 같은 기호, 모듈 선언 등 외부인에게는 비잔틴처럼 보이는 문법 결정이 섞여 있음. 99 bottles 예제도 논리적으로는 따라갈 수 있지만 직관적으로 발견하기는 어려움. 기호가 많고 문맥에 따라 과부하되는 느낌이라, 자연어 파서처럼 Raku가 최적일 만한 작업에도 직접 쓰고 싶지는 않음
    https://examples.raku.org/categories/module-management/Fletc...

    • Perl을 안 해본 것 같음. Perl 배경이 있으면 저 문법 상당수, 특히 배열을 뜻하는 @ 시길은 꽤 익숙하게 보임
    • Bash를 볼 때도 똑같이 느낌
  • Raku에서 가장 좋아하는 기능은 정수 나눗셈과 십진 리터럴이 모두 유리수 타입인 Rat을 반환한다는 점임
    모두가 부동소수점이 별로라는 걸 알지만 실제로 벗어나려는 언어는 거의 없고, Raku는 과학적 표기법을 써야 부동소수점 리터럴이 됨

    • Common LispScheme 같은 더 오래된 언어들도 IEEE 754 부동소수점을 싫어하는 사람들이 알아봐 주길 기다리고 있음
      이들은 유리수와 복소 유리수까지 포함하는 숫자 계층을 갖고 있고, 임의 정밀도 숫자도 당연히 지원함. 조합 가능성은 훌륭함
    • 이건 실제로는 나쁜 기능에 가까움. Rat 표현이 너무 커지면 자동으로 부동소수점으로 바뀌기 때문임
      1/10Rat이지만 1/100000000000000000000Num이 됨. 승격되지 않는 FatRat도 있지만 기본값은 아님
    • Scheme의 숫자 계층은 정확한 표현을 수십 년 동안 제대로 처리해 왔음
      그래서 “부정확한 부동소수점을 명시적으로 요청하지 않았는데도 쓰는 방식에서 벗어났다”기보다는, 애초에 그런 상태였던 적이 없었다고 보는 게 맞음
    • Racket도 다르게 말할 것임. 제대로 동작함
      (/ 1.0 3.0)0.3333333333333333, (/ 1 3)1/3, (- (+ 0.1 0.2) 0.3)5.551115123125783e-17이 됨
    • 이게 좋은지 확신은 안 듦. 십진/유리수 타입과 부동소수점을 언제 써야 하는지는 알지만, 개인 Python 코드에는 Decimal()보다 float() 호출이 훨씬 많음
      돈을 직접 다루는 경우가 아니면 거의 항상 부동소수점이 원하는 선택임
  • Raku 문서가 “정말 형편없다”고 느끼진 않았고, 오히려 공식 문서 사이트가 개념 문서와 API 문서를 모두 담은 원스톱 자료라 인상적이었음
    https://docs.raku.org/
    개념 문서의 출발점으로는 이 페이지가 아주 훌륭함: https://docs.raku.org/language

    • 몇 년째 Raku를 쓰고 있는데, 문서는 훌륭하면서도 부족함
      있는 내용 대부분은 잘 쓰였고 유용한 예제 코드도 있지만, 아예 문서화되지 않았거나 단순한 경우만 다룬 부분을 가끔 만남. 특히 모듈 시스템이 가장 문제였고, 모듈/패키지 구분은 Modules 페이지만 읽어서는 이해하기 어렵다. 가져오는 이름공간과 선언된 이름공간이 다를 수 있지만, 컴파일러가 찾으려면 디렉터리 구조는 이름공간과 맞아야 하는 점은 유용하고 이상하게 말이 되지만 직접 만져보며 배워야 했음
    • 그건 Perl 문화 때문임. Perl FAQ와 매뉴얼 페이지는 Perl을 쓰는 프로그래머들의 성향 덕분에 최고 수준이었고, 재치 있고 간결하며 기묘했음
    • Perl 매뉴얼 페이지는 늘 훌륭했음
  • Raku의 멋진 유니코드 연산자에는 모두 ASCII 대체 표기가 있음
    예를 들어 , , , 의 대체 표기는 (elem), !(elem), (cont), !(cont)
    https://docs.raku.org/language/unicode_ascii#Other_acceptabl...

    • 나라면 확실히 ASCII 버전을 쓸 것 같음
  • 언어를 잘 알기 전에 나오는 전형적인 비판이 여전히 반복되는 것 같음. 예전에는 Perl의 “라인 노이즈”였고, 이제는 Raku가 유니코드 연산자를 거리낌 없이 쓴다는 식임
    하지만 선택 사항이고, 화면에서 코드를 작고 표현력 있게 보이게 하려고 직접 써봤음. 신중하고 창의적인 유니코드 사용에는 잘 맞음. 시길이 싫다는 반응도 흔하지만, Perl의 스위스 아미 전기톱 같은 표현력을 좋아해서 Raku/Perl 6를 써 왔고, Raku는 Perl을 Perl답게 제곱한 느낌임. 정리됐고 표현력이 좋으며, 좋은 옛 Perl 위에 거대한 기능 더미가 쌓였음. 문서도 좋지만 계속 손볼 필요는 있고, Perl 문서와 비교하면 기준이 매우 높음

    • 비ASCII 연산자는 어떻게 입력하는지 궁금함. 특수 키보드 배열인지, 편집기가 특정 시퀀스를 자동 변환하는지, 생 유니코드 이스케이프를 쓰는지 모르겠음
      몇 글자 아끼려고 이렇게 하는 건 복잡하고 별 의미 없어 보임
  • 문법 설탕으로 가득 찬 프로그래밍 언어가 어떤 모습일지 가끔 궁금했는데 이제 알겠음
    “끔찍한데 이상하게 끌리고, 눈을 뗄 수 없고, 더 보여줘” 같은 느낌임

    • 최근 여러 Advent of Code에서 우승한 사람이 만든 취미 언어 noulith를 좋아할지도 모름
      GitHub 소개에는 “slaps roof of [programming language]* this bad boy can fit so much [syntax sugar] into it.”라고 되어 있음. 가장 최근 Advent of Code에서도 그 언어를 써서 우승했음: https://github.com/betaveros/noulith
    • Raku의 Grammars를 알게 될 때까지 기다려 보셈
    • 현대 C++를 볼 때마다 같은 반응이 나옴
  • Raku가 원래 Perl 6로 시작했고, 많은 설계 철학이 Perl식 사고에서 나왔다는 점은 기억할 만함
    문자열 반복용 x 연산자에 바로 반응한 걸 보면 작성자가 Perl과 Raku의 역사를 잘 모르는 것처럼 보이는데, 그건 Perl에서 수십 년 동안 그래 왔음

    • 본문에 “정규식 문법은 Perl 5와 하위 호환되지 않는다. 30년 동안 언어들이 PCRE ‘표준’을 따랐는데 Perl 6가 그냥 다 버렸다”는 문장이 있으니, 적어도 어느 정도는 알고 있는 듯함
    • 첫 번째 각주에 Raku가 예전에 Perl 6로 알려졌다고 되어 있음
    • “Perl6/Raku는 Perl 5와 전혀 다르다”는 과장은 너무 부풀려졌음
      괜히 Perl 6라고 불린 게 아니고, 거의 같은 Perl 팀이 개발했음. Perl 5를 꽤 써본 사람이라면 Perl6/Raku의 유산은 분명히 보임. Raku의 객체 모델 전체도 CPAN의 Perl 5 모듈인 Moose.pm을 조금 더 강력하게 만든 버전에 가까움
  • 솔직히 Perl 5/PCRE 정규식 문법은 끔찍함
    존재하는 이유도 예전 정규식 문법에서 (?가 문법 오류였기 때문에 아무 의미로나 재정의할 수 있었던 것뿐임. Raku는 정규식이 무엇을 표현해야 하는지 알게 된 지금, 처음부터 제정신인 정규식 언어를 설계하려는 시도임. 대안은 앞으로 30년 더 (?:this|(?>or that)) 같은 것에 갇히는 일임

    • 끔찍하다기보다 해독 불가능한 흑마법이고, 이해하고 나면 멋짐
      Perl을 안 만진 지 오래됐지만 아직도 정규식은 자주 쓰게 됨
    • 동의하지만, 정말 유용하긴 함
  • 특정한 의미에서 확실히 그렘린임. 기묘하고 복잡하지만 생산성을 높여주는 도구를 좋아함
    다만 “큰 프로그램 vs 작은 프로그램” 비교에는 동의하지 않음. 덜 현명한 사람은 그게 큰 작업에 나쁜 언어라는 뜻으로 받아들일 수 있지만, 실제로는 다른 언어만큼 좋거나 더 나을 수도 있음. 문제는 다른 그렘린 언어와 마찬가지로, 잘 쓰려면 지혜가 필요하다는 것임. 예를 들어 $x@x를 헷갈리는 사람은 비슷한 언어를 충분히 써본 사람이라면 거의 없음. 시길은 코드를 읽을 때 변수의 단순 타입, Raku에서는 인터페이스를 바로 알려줘서 오히려 편해지고, 같은 변수 이름공간을 다른 시길로 유용하게 쓸 수 있음. 이상해 보이고 불필요한 글자처럼 보이며 의미를 알아야 하지만 삶을 쉽게 만들 수 있음: https://www.perl.com/article/on-sigils/
    문제는 무엇을 하는지 잘 모르는 사람들에게 생김. 그런 사람들에게 이 그렘린 언어는 살아 있는 악몽일 수 있고, 볼링 범퍼, 물놀이 튜브, 케블라 장갑, 안전모, GPS 같은 보호장치가 많이 필요함. 그렘린 언어로 마천루를 못 짓는다는 뜻은 아니고, 사고 치기 쉬운 비그렘린이 못 지을 뿐이며 현명한 그렘린은 지을 수 있음

    • “이 도구는 충분히 잘하는 사람만 쓸 수 있다”는 사고방식은 거대한 설계 냄새라고 봄
      도구는 팀이 필요한 일을 더 잘하거나 더 빠르게 하도록 돕기 위해 존재함. 주니어를 걸러내거나 자기 자존심을 채우려고 불필요하게 복잡한 도구를 쓴다면, 그 도구는 조직의 나머지 사람들에게 도움이 아니라 무기에 가까움