Mini Shell은 앞의 셋이 못 건드린 모양을 친다 — 파이프 하나는 끝이 둘이고 각각 다른 자식에게 간다. 부모에게 아무것도 안 남고 어느 블록에도 묶이지 않는다. 가장 어려운 자원 코드가 렉시컬하지 않다. 파싱을 자원에서 떼어 놓아 개밥이 처음으로 실제로 돈다 (test 5/5 통과). 보안 정리 (ii)의 구멍 셋 — 전부 "부분 move가 없다"는 하나의 규칙이 닿아야 할 자리가 비어 있던 것: - 열거형 생성자가 인자를 소비하지 않았다. Some(f)를 두 번 쓰면 복제됐고, LRU가 쓰는 우회(affine 값을 열거형으로 나르기)가 그래서 무의미했다 - 소유한 열거형을 두 번 분해할 수 있었다. match가 scrutinee를 늘 빌려서 조각만 owned로 나갔다 — 같은 파이프에서 같은 fd를 두 번 꺼낼 수 있었다 - 점 왼쪽을 이름 해소가 검사하지 않았다. Nonsense.whatever(1)이 통과했고 samples 셋(02, 04, 06)이 이 구멍에 기대고 있었다 (D1과 같은 병) 누수 lint를 넣었다. ?와 return 자리에서 소유하고 있고 아직 안 넘긴 affine 값을 말한다. 저장소 전체 네 곳, 오탐 0건 — naive 판만 걸리고 careful 판은 조용하다. 타입 층 정책은 그대로다 (오용 금지, 누수 허용). 결정: resource라는 새 종류는 넣지 않는다. capability가 이미 그것이고 own self가 정리를 말한다. with는 미룬다 — 두 갈래 중 고르기에 데이터가 부족하고, 셸이 with가 닿지 않는 모양을 보여줬다. List.rest 추가 (첫 원소를 뺀 나머지). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
64 lines
2.3 KiB
Plaintext
64 lines
2.3 KiB
Plaintext
// 표준 라이브러리: 리스트.
|
|
//
|
|
// 본문이 없다. 런타임이 구현하고, 이 파일은 그 계약을 말한다.
|
|
// 그래서 이 파일은 구현이 아니라 시험대다 — effect 다형성이 실제로 쓸 만한지가
|
|
// each, map, fold, filter에서 결정된다. 규칙이 틀렸으면 여기서 드러난다.
|
|
//
|
|
// e는 파라미터의 effect 슬롯에 홀로 나타난다 (결정 위치). 호출 지점에서
|
|
// 인자의 시그니처를 읽어 묶인다 — 추론이 아니라 읽기다.
|
|
|
|
pub fn len[a](xs: List[a]) -> Int
|
|
|
|
pub fn is_empty[a](xs: List[a]) -> Bool
|
|
|
|
// 인덱싱 연산자가 언어에 없다. n번째를 꺼내는 일은 이름 있는 함수가 하고,
|
|
// 없을 수 있다는 사실은 Option이 말한다 — 범위를 벗어나면 예외도 기본값도
|
|
// 아니고 None이다.
|
|
pub fn first[a](xs: List[a]) -> Option[a]
|
|
|
|
pub fn nth[a](xs: List[a], i: Int) -> Option[a]
|
|
|
|
// 첫 원소를 뺀 나머지. 비어 있으면 빈 리스트다 — 없는 것을 빼는 일은
|
|
// 오류가 아니라 아무 일도 아니다. first와 짝이고, 둘은 서로 어긋날 수 없다.
|
|
pub fn rest[a](xs: List[a]) -> List[a]
|
|
|
|
// 번호를 붙인 값. fold에 인덱스를 넣는 대신 이것 하나를 둔다 —
|
|
// fold_indexed를 만들면 map_indexed, each_indexed가 따라오고 그것이
|
|
// "한 개념 한 방식"을 깨는 방향이다. enumerate는 기존 각 함수와 조합된다.
|
|
pub copyable struct Indexed[a] {
|
|
i: Int,
|
|
value: a,
|
|
}
|
|
|
|
pub fn enumerate[a](xs: List[a]) -> List[Indexed[a]]
|
|
|
|
// 뒤에 하나 붙인 새 리스트. 제자리 수정이 아니다.
|
|
pub fn push[a](xs: List[a], x: a) -> List[a]
|
|
|
|
pub fn concat[a](xs: List[a], ys: List[a]) -> List[a]
|
|
|
|
pub fn reverse[a](xs: List[a]) -> List[a]
|
|
|
|
pub fn each[a, e: effects](
|
|
xs: List[a],
|
|
f: fn(a) effects e,
|
|
) effects e
|
|
|
|
pub fn map[a, b, e: effects](
|
|
xs: List[a],
|
|
f: fn(a) effects e -> b,
|
|
) effects e -> List[b]
|
|
|
|
pub fn filter[a, e: effects](
|
|
xs: List[a],
|
|
keep: fn(a) effects e -> Bool,
|
|
) effects e -> List[a]
|
|
|
|
// 누적자는 매 단계 소비되고 새것으로 바뀐다. own이 그 사실을 말한다 —
|
|
// 빌림으로 적으면 affine 값을 fold로 실어나를 수 없다.
|
|
pub fn fold[a, acc, e: effects](
|
|
xs: List[a],
|
|
own init: acc,
|
|
f: fn(own acc, a) effects e -> acc,
|
|
) effects e -> acc
|