Factor Overview
Factor 언어 개요 — 스택 기반 프로그래밍부터 주요 라이브러리까지
Factor를 처음 접하는 개발자를 위한 실습 중심 안내서입니다. 데이터 스택과 스택 효과부터 조합자, 객체 모델, 메타프로그래밍, 파일·네트워크·C 연동까지 언어와 표준 라이브러리의 사용법을 코드로 설명합니다.
- 주제
AI 요약
Factor의 공식 가이드 투어를 보완하는 코드 중심 개요입니다. 스택 기반 언어를 써본 적은 없어도 프로그래밍 경험은 있는 독자를 대상으로, 일상적인 문법과 제어 흐름부터 라이브러리 활용까지 한 문서에서 따라가도록 구성했습니다. 예제는 대화형 REPL인 listener에서 바로 실행할 수 있습니다.
스택과 기본 문법
Factor에서는 값을 데이터 스택에 올리고, 단어(word)가 스택 맨 위의 값을 소비해 결과를 올립니다. 코드는 왼쪽에서 오른쪽으로 실행하며 함수 인자를 괄호로 묶지 않습니다. 2 3 +는 2와 3을 차례로 올린 뒤 더합니다. 단어의 스택 효과 ( 입력 -- 출력 )는 소비하고 내놓는 값의 수와 순서를 문서화합니다. 정의에 적은 효과는 컴파일러가 검사하며, 하나의 단어가 여러 값을 반환할 때도 별도의 return은 필요하지 않습니다.
리터럴에는 정수, 정확한 유리수, 부동소수점 수, 복소수, 문자열, 배열, 벡터, 해시테이블, 실행 코드인 quotation 등이 있습니다. 배열은 { ... }, quotation은 [ ... ]로 씁니다. 문자열은 유니코드 이스케이프를 지원하며 길이는 화면에 보이는 글자 수가 아니라 코드 포인트 수로 계산합니다. 이름 끝의 ?는 흔히 조건 판별 단어, !는 변경 단어를 나타내지만, 모두 단어 이름의 일부입니다.
제어 흐름과 조합자
if에는 조건과 두 quotation을 전달합니다. Factor에서는 f만 거짓으로 취급하므로 0이나 빈 문자열도 참입니다. when, unless, cond, case로 조건 분기를 작성하고, while이나 times로 반복합니다. 여러 시퀀스 연산은 map, filter, reduce, each 같은 조합자로 표현합니다. map은 각 결과를 모으고, each는 부수 효과를 내며, reduce는 누산값을 순서대로 갱신합니다.
Quotation은 값으로 전달하거나 저장하고 호출할 수 있는 코드입니다. 이를 인자로 받는 단어를 조합자(combinator)라고 합니다. curry는 quotation 앞에 값을 고정하고, compose는 두 quotation을 이어 붙입니다. bi 계열은 같은 입력에 여러 quotation을 적용하거나 입력을 나눠 처리합니다. dip은 값을 잠시 숨긴 채 quotation을 실행하며, keep은 값을 quotation에 전달하면서 원래 값도 보존합니다. 이런 도구를 쓰면 스택을 직접 뒤섞는 코드를 줄일 수 있습니다. 필요하면 locals의 ::로 어휘적 변수를 선언하고 quotation에서 바깥 변수를 캡처할 수 있습니다.
자료형과 객체 모델
배열, 벡터, 문자열 등은 공통 시퀀스 프로토콜을 따릅니다. 해시테이블과 연관 컬렉션은 assocs 프로토콜을 제공하며, at*는 키가 없을 때와 값이 f일 때를 구분하도록 존재 여부와 값을 함께 돌려줍니다. 반복적인 멤버십 검사에는 시퀀스를 매번 훑는 대신 해시 집합을 쓰도록 안내합니다.
TUPLE:로 이름 있는 슬롯을 가진 튜플 클래스를 정의하고, 접근자 단어로 슬롯을 읽거나 갱신합니다. C와 호환되는 메모리 배치가 필요하면 STRUCT: 또는 패딩을 제거하는 PACKED-STRUCT:를 사용합니다. 제네릭 단어는 맨 위 입력의 클래스에 따라 메서드를 선택합니다. 튜플 상속, 다음 메서드 호출, 술어 클래스, 클래스 합집합과 교집합, 믹스인, 싱글턴, 열거형도 지원합니다. 일반 레코드에는 튜플을 쓰고 C 메모리 구조나 명시적인 바이너리 레이아웃이 필요할 때 구조체를 쓰는 기준도 설명합니다.
오류, 자원, 메타프로그래밍
ERROR:로 오류를 정의하고 recover로 처리할 수 있습니다. 보호한 quotation이 실패하면 스택을 실행 전 상태로 되돌린 뒤 오류 객체를 핸들러에 전달합니다. finally는 성공과 오류 모두에서 정리 코드를 실행합니다. 일반 객체는 가비지 컬렉션 대상이지만 파일 스트림 같은 자원은 결정적 해제가 필요합니다. with-disposal은 quotation이 끝나거나 오류가 나면 자원을 닫습니다. 여러 자원을 등록할 때는 등록 순서의 역순으로 해제하며, 자원 생성 도중 실패하면 먼저 만든 자원만 정리하고 성공하면 호출자에게 소유권을 넘기는 방식도 보여줍니다.
Factor에서는 단어도 객체입니다. 매크로는 컴파일 시점에 입력을 받아 quotation을 만들고, 파싱 단어는 소스 코드를 읽는 동안 실행해 문법을 확장합니다. 매크로 입력은 컴파일 시점에 알려져 있어야 합니다. MEMO:는 입력별 결과를 캐시하지만, 캐시된 변경 가능 객체를 호출자가 수정하면 결과가 공유된다는 점에 주의해야 합니다.
개발과 라이브러리
어휘(vocabulary)는 이름 공간이자 소스 구성 단위입니다. USING:으로 어휘를 가져오고 IN:으로 정의할 어휘를 지정하며, MAIN:으로 실행 진입점을 정합니다. listener에서는 정의를 다시 입력해 즉시 시험할 수 있고, 저장된 어휘는 reload나 refresh-all로 다시 읽습니다. tools.test는 기대하는 스택 결과를 명시하는 단위 테스트를 제공하며, 개발 환경에서 문서 조회, 정의 확인, 실행 시간 측정도 할 수 있습니다.
안내서 후반부는 파일 입출력과 UTF-8, JSON 변환, 정규식, HTTP 클라이언트, 날짜·시간, 난수, 협력형 스레드, C 외부 함수 인터페이스(FFI)를 예제로 다룹니다. 스레드는 yield로 실행을 양보하며 블로킹 입출력은 스케줄러와 연동됩니다. C 함수 선언에서는 인자와 반환형을 지정하고, 외부 메모리를 다룰 때는 관리 객체와 달리 수명 관리가 필요합니다. 저자는 작은 단어부터 작성하고 스택 효과를 따라가며 조합자로 값의 흐름을 분명히 하라고 안내합니다.
원문: Factor 블로그 / 번역·요약: Trawling