문법은 건드리지 않았다. 표본이 한 사람이 쓴 300줄 하나뿐인데 되돌리기 비싼 축을 움직일 수는 없다. std 보강만 했다. 추가: List.first/nth, String.join, std/option.cool, std/result.cool. samples/app 재작성 결과 config.cool 196 → 148줄. head_or, second_or, Pick, take_at, first_text, first_entry가 통째로 사라졌다. 예측 40줄, 실제 48줄 — F1의 값이 확인됐다. F3은 줄 수로 값이 안 보인다. main.cool은 96줄 그대로다. 4단 중첩 String.concat이 4줄짜리 String.join 배열이 됐으니 줄 수가 같다. 읽기는 확실히 나아졌다. 줄 수는 읽기 좋음의 대리 지표일 뿐이고 여기서 그 대리가 깨진다 — 다음 개밥 먹기는 다른 것을 재야 한다. F7: Interp.implemented와 std/*.cool 선언이 서로를 덮는지 테스트가 양방향 으로 검사한다. 어긋나면 빌드가 깨진다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
48 lines
1.5 KiB
Plaintext
48 lines
1.5 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]
|
|
|
|
// 뒤에 하나 붙인 새 리스트. 제자리 수정이 아니다.
|
|
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]
|
|
|
|
pub fn fold[a, acc, e: effects](
|
|
xs: List[a],
|
|
init: acc,
|
|
f: fn(acc, a) effects e -> acc,
|
|
) effects e -> acc
|