Toolbox languages

Hillel Wayne

툴박스 언어

원문은 Hillel Wayne님이 에 게재했습니다. 이 블로그 구독하기

툴박스 언어란 서드파티 패키지 없이도 문제를 잘 해결할 수 있는 프로그래밍 언어를 말한다. 내 기본 툴박스 언어는 여러분도 아마 잘 아는 Python과 셸 스크립트다. 여기서는 좀 더 잘 알려지지 않은 언어들을 소개한다.

AutoHotKey

빠질 수 없죠! AutoHotkey는 기본적으로 “GUI를 위한 셸 스크립팅”이다. 프로그래밍을 할 수 없는 애플리케이션을 쓸 때의 불편함을 매끄럽게 해소해 주는 환상적인 도구다. Windows 전용이지만 Mac과 Linux용 비슷한 도구들도 있다.

유용한 기능:

  • 특정 프로그램에서만 동작하거나, 전역 플래그가 설정된 경우, 화면에 특정 텍스트가 나타난 경우 등에만 활성화되는 단축키를 설정할 수 있다.
  • 수많은 기본 win32 기능을 간단하게 사용할 수 있다. 파일 선택 대화상자를 여는 건 f := FileSelect() 한 줄이면 된다.
  • GUI 프레임워크가 정말, 정말 훌륭하다. 솔직히 내가 써 본 어떤 언어 중에서도, 적어도 가벼운 용도에서는 최고다.

활용 예시:

Audacity는 마우스 단축키를 설정할 수 없게 되어 있어서, AutoHotkey를 이용해 가운데 마우스 버튼을 키보드 단축키로 매핑했다.

#HotIf WinActive("ahk_exe audacity.exe")
  MButton::Send "^l" ; silence selection
#HotIf

;iso를 입력하면 현재 날짜가 자동으로 채워지도록 만들었다.

:R:;iso:: 
{
    Send(FormatTime(,"yyyy-MM-dd"))
}

타임스탬프가 찍힌 메모를 하기 위해 쓰는 도구다.

; right-ctrl + d
>^d::
{
  TimeString := FormatTime(,"MM/dd hh:mm tt")
  t_msg := InputBox(,TimeString,"w200 h100")
  if t_msg.Result = "OK" {
    timestampfile := A_WorkingDir . "\Config\timestamps.txt"
    FileAppend(TimeString . "`t" . t_msg.Value . "`r`n", timestampfile)
  }
}

그 밖의 용도: 툴박스 언어용 REPL 실행하기. 어떤 비디오 게임을 클리어하는 데 필요한 100번 키 입력 시퀀스 입력하기(아는 사람은 알 것이다).

더 읽어보기:

J

APL과 같은 배열 언어다. 배열 연산은 정말 잘하지만, 문자열이나 구조화된 데이터를 다루는 건 머리를 쥐어뜯게 할 정도로 답답하다. 예전에는 자주 썼지만 지금은 Excel이나 Raku 같은 다른 도구로 대부분 갈아탔다. 그래도 특정 분야에서는 여전히 놀랍도록 훌륭하다.

유용한 기능:

  • 미칠 듯이 간결하다. 다른 언어에서는 몇 줄이 필요한 작업이 J에서는 몇 글자면 되기 때문에, 빠르게 수학 계산을 많이 해야 할 때 유용하다.
  • 일급 다차원 배열을 지원한다. +는 두 수를 더할 수도, 두 배열을 원소별로 더할 수도, 배열의 모든 원소에 하나의 수를 더할 수도, 고차원 배열의 모든 행(또는 열)에 배열 하나를 더할 수도 있다.
  • 수를 소인수로 분해하는 것처럼 특수한 수학적 연산을 수행하는 최상위 프리미티브가 아주 많다.

활용 예시:

어떤 수의 모든 소인수를 구하기:

    q: 2520
2 2 2 3 3 5 7

각각 4단계 알고리즘을 실행하는 두 프로세스가 있을 때, 가능한 인터리빙은 몇 가지일까?

    ni =: !@:(+/) % */@:!
    ni 4 4
70

1~3개의 프로세서와 1~3단계 각각에 대한 인터리빙 표를 만들고 싶다면?

   (ni@:$)"0/~ >: i. 3
1  1    1
2  6   20
6 90 1680

더 읽어보기:

Frink

아마 이 목록에서 가장 생소한 언어일 것이다. Frink는 차원 분석(단위가 있는 수학)을 위해 설계된 언어지만, 개발자가 흥미롭다고 생각하는 것들을 다루기 위한 온갖 기능도 갖추고 있다. 그게 꽤 많다! 내가 본 어떤 프로그래밍 언어보다 “더 나은 계산기”에 가장 가깝다고 할 수 있다. 시작하기 쉽고, 강력하며, J나 Raku처럼 낯선 문법을 가지고 있지도 않다.

유용한 기능:

  • 내장 단위와 단위 수식어가 아주 많다. calendaryear는 정확히 365일, tropicalyear는 365.24일이며, half nanocentury는 약 1.6초다.
  • 날짜 리터럴 표기법: # 2000-01-01 # - # 200 BC #는 2199.01년이다.
  • 불확실성을 다루기 위한 내장 interval 타입이 있다. 조금 투박하지만 동작은 한다.

활용 예시:

1970년 1월 1일 자정에 태어난 사람이 10억 초가 되는 시점은 언제일까?

   # 1970 # + 1 billion seconds
AD 2001-09-09 AM 02:46:40.000 (Sun) Central Daylight Time

특정 거리를 특정 시간에 달렸다면 평균 페이스는 어떻게 될까?

   // In miles per hour
   2.5 miles / (27 minutes + 16 seconds) -> mph
5.5012224938875305623

   // In meters per hour
   2.5 miles / (27 minutes + 16 seconds) -> meters / hour
8853.3594132029339854

   // In (minutes, seconds) per mile
   1 / (4.5 miles / hour) -> [minutes/mile, seconds/mile, 0]
13, 19

(6 ± 2) * (8 ± 1)은 얼마일까?

   x = new interval [2, -2]
   (6 + x) * (8 + x/2)
[28, 72] // range is between 28 and 72

더 읽어보기:

Raku

Raku(구 Perl 6)는 온갖 암흑 마법으로 가득 찬 정말 괴상한 언어다. 매우 강력하지만 망치기도 아주 쉽다. 아직 프로덕션 프로그램에 쓰기에는 망설여진다. 하지만 개인용 스크립팅이나 툴킷으로는 믿을 수 없을 정도로 훌륭하다.

유용한 기능

  • 자신만의 중위 연산자를 정의할 수 있다! 후위 연산자도. 그리고 circumfix 연산자도.
  • 걱정될 정도로 엄청나게 많은 신택틱 슈가가 있다. 예를 들어 [1, 2] 대신 <1 2>라고 쓸 수 있다. 그리고 ["a", "bc"] 대신 <a bc>라고 쓸 수 있다. Raku는 Just Knows™ 알아서 처리한다.
  • MAIN 함수를 정의하면 그 매개변수가 CLI 인자로 바뀐다.
  • 런타임 값을 기반으로 한 다중 디스패치 멀티메서드를 지원한다. 이를 MAIN과 결합하면 작은 CLI 도구를 아주 쉽게 만들 수 있다.
  • 많은 수학 연산자에 유니코드 대응 기호가 있다(예: (elem)에 대한 ∈). 이는 내 모든 AutoHotkey 핫스트링과 시너지가 잘 난다.

활용 예시

무작위 소문자 10글자 문자열 세 개 생성하기.

> for ^3 {say ('a'..'z').roll(10).join}
fflqymxapa
znyxehaqvo
qwqxusudqw

그래머로 특이한 구조의 데이터 형식 파싱하기(링크 참조).

SVG id들을 Inkscape 레이블로 일괄 복사하기.

use XML;

my $xml = from-xml-file("file.svg");

for $xml.elements(:NEST, :RECURSE<99>) -> $e {
  with $e ~~ /k\w/ {
    say $_.target;
    $e.set("inkscape:label", $_.target);
  }
}
$xml.save()

옵션 조합이 좀 까다로운 CLI 작성하기(예시).

더 읽어보기:

Picat

내 가장 최근의 툴박스 언어이자, 애초에 툴박스라는 개념을 고민하게 만든 언어다. 논리 프로그래밍, 제약 풀이, 그리고 명령형 탈출구가 현기증 날 정도로 뒤섞여 있다. 처음에는 더 나은 제약 솔버로 집어 들었다가 계속 새로운 용도를 찾아내고 있다.

유용한 기능:

  • 변수에 대한 할당. 논리 언어에서는 놀랍도록 유용하다. 많은 문제가 논리 프로그래밍에 거의 딱 맞는 듯하면서도, 알고리즘의 작은 한 부분을 100% 논리적으로 어떻게 표현해야 할지 모르겠는 경우가 늘 있었다. 명령형이 내가 필요로 하던 탈출구를 제공했다.
  • planner 모듈. 나는 planner 모듈을 사랑한다. 내 최고의 친구다. 목표와 가능한 액션 목록을 주면, Picat이 그 목표에 도달하는 액션 시퀀스를 찾아준다. 정말 멋지다.

활용 예시:

시속 4.5마일로 X분, 시속 5.1마일로 Y분을 달려 38분 안에 3.1마일을 달리려면 X와 Y는 각각 얼마여야 할까?

import cp.
[X, Y] :: 1..60, 45*X + 51*Y #= 31*60,  X+Y #= 38, solve([X,Y]).
X = 13
Y = 25
yes

여러 활동과 시간 제약, 충돌 조건이 주어졌을 때, 휴가 계획 짜기.

논리 퍼즐에 해가 여러 개인지 확인하기. 논리 퍼즐의 단서 중 중복되는 것이 있는지, 혹은 하나를 제거해도 유일한 해가 유지되는지 확인하기.

간단한 페트리 넷 도달 가능성 솔버 빠르게 만들어 보기.

더 읽어보기:

좋은 툴박스 언어란 무엇인가?

내가 본 좋은 툴박스 언어 대부분은 계산을 위한 언어다. AutoHotkey 같은 이펙트와 자동화를 위한 툴박스 언어도 가능하다고 생각하지만, 그 영역은 아직 덜 탐구된 것 같다.

툴박스 언어는 정말, 정말 작성 속도가 빨라야 한다. 최소한 Python보다 빨라야 한다. “무작위 숫자 10쌍”을 비교해 보자:

# python

from random import randint
[(randint(10), randint(10)) for _ in range(10)]

# Raku
^10 .roll(2) xx 10

# J
10 2 ?@$ 10

이를 가능하게 하는 몇 가지 요소가 있다. 간결한 문법은 타이핑을 줄여 준다. 풍부한 빌트인은 기본적인 것들을 직접 작성할 일을 줄여 준다. 표준 라이브러리에서 가져오는 건 이상적이진 않지만 용인할 수 있다. 서드파티 패키지를 설치해야 하는 건 거슬린다. Raku는 여기서 멋진 방식을 제공한다. Rakudo Star Bundle에는 유용한 커뮤니티 패키지들이 미리 설치되어 함께 제공된다.

뭔가를 한 줄로 할 수 있다면 REPL에 바로 던져 넣을 수 있다. 그래서 좋은 REPL이 필요하다. 내가 쓰는 언어 대부분은 REPL이 괜찮은 편이지만, Lisp나 Smalltalk를 쓰는 독자들은 “좋은 REPL”이 무엇인지에 대해 할 말이 많을 거라 생각한다.

이상적으로는 진입 장벽이 낮아야 한다. Raku는 복잡한 부분이 많지만 조금만 배워도 유용하게 쓸 수 있는 반면, J는 학습 곡선이 너무 가팔라서 대부분의 사람에게 추천하기 어렵다. 다만 이는 “빠르게 작성할 수 있다”는 장점과 종종 충돌한다.

툴박스에 추가하고 싶은 다른 도구들

  • JSON 처리를 위한 jq
  • 개발자 콘솔로 다른 사람의 웹사이트를 수정할 수 있는 Javascript
  • J의 장점은 제공하면서 내가 계속 겪는 답답함은 없는 어떤 종류의 APL
  • 연결형 프로그래밍 언어가 정확히 어떤 작은 문제에 정말 잘 맞는지 알게 된다면, 그런 언어 하나
  • 웹 스크래핑과 파싱을 계산만큼 쉽게 만들어 주는 무언가. Requests와 bs4는 그게 아니다.

피드백을 준 Saul Pwanson에게 감사드립니다. 이 글이 마음에 들었다면 뉴스레터에 가입해 주세요! 매주 새로운 에세이를 올립니다.

저는 기업을 대상으로 형식 기법(formal methods) 교육을 진행하며, 소프트웨어 개발을 더 빠르고, 더 저렴하고, 더 안전하게 만듭니다. 더 자세한 내용은 여기에서 확인하세요.

제 신간 Logic for Programmers가 현재 얼리 액세스로 공개되었습니다! 여기에서 확인해 보세요.

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.

댓글