3P by GN⁺ | ★ favorite | 댓글 1개
  • Hylo는 값 의미론을 기반으로 안전한 시스템·제네릭 프로그래밍을 지향하며, 컴파일러와 표준 라이브러리는 초기 단계지만 Compiler Explorer에서 예제를 실행해볼 수 있음
  • 언어 연구는 Swift subscript의 inout projection 확장, method bundles, 구조적 동시성, 값 의미론 기반 이중 연결 리스트 같은 주제에 집중됨
  • 컴파일러는 LLVM을 사용하고, coherence를 갖춘 제네릭 컴파일, 프로그램 상태의 캐싱·직렬화, C 상호운용성 연구를 함께 다룸
  • 개발 환경은 VSCode 확장, 문서 컴파일러, Language Server 프로토타입을 제공하며 SPM/CMake, Ninja/Xcode, Windows/Linux/macOS, Docker 개발 툴체인 이미지를 지원함
  • 예제는 안전한 projection과 sink method를 통해 소유권·해제 규칙을 코드 수준에서 드러내며, 시스템 언어가 안전성을 어떻게 강제할 수 있는지 보여줌

Hylo의 범위와 현재 상태

  • Hylo의 컴파일러와 표준 라이브러리는 아직 초기 단계
  • 고급 Hylo 코드 예제는 Compiler Explorer에서 실행해볼 수 있음
  • 첫 화면에서도 Hylo를 Compiler Explorer에서 시도할 수 있는 링크를 제공함

값 의미론과 언어 연구

컴파일러와 표준 라이브러리

  • 컴파일러 작업은 LLVM 기반 컴파일, 제네릭, 상태 저장, C 상호운용성에 걸쳐 있음
  • 표준 라이브러리 쪽에서는 현재 구현 문서와 컬렉션 알고리듬 관련 작업을 공개함

개발자 경험과 빌드 환경

  • 편집기, 문서, 언어 서버를 위한 도구가 함께 제공됨
  • 빌드와 개발 환경은 여러 운영체제와 컨테이너 기반 흐름을 지원함
    • Development Containers 지원으로 시작 절차를 줄임
    • SPM/CMake, Ninja/Xcode, Windows/Linux/macOS 지원
    • 테스트 생성 컴파일러 플러그인
    • 사전 빌드된 Hylo development toolchain Docker 이미지
    • 컴파일러는 Swift 6.2로 작성됨

Hylo 관련 연구와 발표 자료

코드 예제: 안전한 projection과 명시적 해제

  • Subscripts - A Safe Projection Mechanism 예제는 Angle 타입이 radians 값을 저장하고 degrees 프로퍼티를 letinout 블록으로 제공하는 구조를 보여줌
    • degreeslet은 radians를 degree로 변환해 반환함
    • inout은 임시 degree 값 dyield &d로 노출한 뒤, 변경된 값을 다시 radians로 변환해 self.radians에 반영함
    • maininout d = &a.degrees로 projection을 얻고, d0.0으로 바꾼 뒤 a.radians == 0.0을 확인함
  • Sink Methods - Capability for Deinitializing 예제는 Computer 타입이 shutdown()을 sink method로 제공하는 구조임
    • shutdown()은 메모리 내용을 출력한 뒤 self.ram을 sink 처리함
    • test1Computer를 만들고 shutdown하지 않아 Cannot deinit computer가 발생함
    • test2if random_bool() 안에서만 shutdown하므로, if에 들어가지 않는 경로에서 Cannot deinit computer가 발생함
    • test3while 안에서 shutdown을 호출하면 첫 반복 이후 consumed object 사용 문제가 생기고, while에 들어가지 않는 경로에서는 deinit 불가가 남음
  • 추가 예제는 compiler test suite에서 확인할 수 있음

댓글과 토론

Hacker News 의견들
  • C++ 후계자로는 Herb Sutter의 훌륭한 CppFront보다 Val이 더 기대될지도 모르겠음. 아래 두 발표만 본 상태지만, 정적 컴파일·정적 타입·C++ 상호운용·메모리 안전·타입 안전·데이터 경쟁 없음이 핵심으로 보임
    내가 설명할 때는 “새 C++ 프로젝트를 시작하면서 성능을 신경 쓰지 않는다고 치고, 포인터나 참조 없이 전부 값으로 넘기고 값으로 반환하면 부작용이나 데이터 경쟁 걱정이 없어 좋지 않겠나”라고 말함. Val은 언어에서 포인터와 참조를 제거해도 컴파일러가 내부적으로 const 참조 전달과 반환값 최적화를 적용해 원하는 의미론과 성능을 동시에 보존하게 만든다는 점이 흥미로움
    Val: A Safe Language to Interoperate with C++ - Dimitri Racordon - CppCon 2022 https://www.youtube.com/watch?v=ws-Z8xKbP4w
    https://cppcast.com/val-and-mutable-value-semantics/

    • Sean Parent가 Val을 다룬 ADSP Podcast 최근 두 에피소드를 들어보면 좋음. Adobe Research Labs가 개발을 꽤 진지하게 후원하고 있음
      https://adspthepodcast.com/
    • “C++와 상호운용”은 의심스러움. 다른 언어가 C++와 제대로 상호운용할 수 있다고 믿기 어렵고, C++ 컴파일러끼리도 바이너리 호환성이 깨지며 같은 컴파일러의 버전끼리도 다를 때가 있음
    • 컴파일러를 너무 많이 믿는 구조처럼 들림. 작은 변경 하나가 멀리 떨어진 코드의 최적화를 깨서 성능을 망칠 가능성이 생기지 않을까 걱정됨
    • “하루 종일 값으로 넘기고 값으로 반환한다”면 더 이상 구조체 안에서 참조를 효율적으로 변경하거나 저장하기 어려움. 프로그램에 조금이라도 비표준적이거나 복잡한 자료구조가 필요하면 치명적인 제약처럼 보임. 물론 그런 자료구조를 올바르게 구현하기 어렵다는 점을 생각하면 오히려 장점일 수도 있음
    • PHP 프로그램을 몇 년 동안 실제로 이런 식으로 작성해 왔고, 배열을 신경 쓰지 않고 계속 넘겨 왔음
      PHP 인터프리터가 실제로는 쓰기 시 복사(copy-on-write) 를 쓸 만큼 똑똑하다고 생각하지만, 직접 프로파일링해 본 적은 없음. 그래도 꽤 복잡한 데이터 처리, DSL 문자 단위 파싱, 동적 SQL 생성, 결과를 임의 구조로 마사지하는 일을 페이지 로드마다 해도 체감 성능 문제는 없었음
      PHP 4 시절에는 객체도 변수에 저장된 값처럼 동작했는데, 이후 객체 변수를 참조 의미론으로 바꿀 때 “값, 변수 참조, 값에 대한 포인터”를 저장 타입과 직교하는 변수 속성으로 만들지 않은 건 아쉬운 기회였다고 봄
      $a = $b; // $b의 값을 $a로 복사
      $a = &$b; // $a와 $b는 이제 같은 변수
      $a = *$b; // $a는 $b와 같은 객체를 가리키지만, $a = &$b와 달리 변수 자체는 연결되지 않음
  • 무비용 추상화 언어가 이렇게 많이 등장하는 건 한편으로 좋지만, 시스템 프로그래머들이 이제 승자를 하나 골랐으면 하는 마음도 있음. 이미 작은 시스템 프로그래머 커뮤니티가 Rust, Zig, Val 등으로 더 잘게 갈라지지 않았으면 하고, 시스템 언어 전쟁이 빨리 끝나길 바람

    • 어쩌면 너무 일찍 하나를 골라서 이 분야의 혁신이 너무 오래 부족했을지도 모름. 전쟁은 환영함
    • 지금 시점에서는 Rust가 승자라고 봄. Linux와 Windows 커널에 실제로 들어가는 엄청난 장벽을 이미 넘었기 때문임. 그런 점에서 이제 새로운 시스템 언어가 더 들어설 공간은 별로 없어 보임
    • 그렇게 되진 않을 것 같음. 그래서 더더욱 wasm + wasi 지원을 어디서나 넓혀야 할 이유가 커짐
  • 오늘 처음 Val을 알게 된 감정의 흐름은 이랬음. “오, 새 시스템 언어네. 별거 아닐 수 있지만 한번 보자. 문서는 괜찮네. 소유권 관련 아이디어가 꽤 사려 깊고 문법도 말이 되네. 그런데 독자적 존재 이유가 있을 만큼 다른가? 누가 만들지?”
    그러다 Dave Abrahams가 작업 중이라는 걸 보고 관심이 커졌음. Apple에서 마주친 적이 있고 Swift에 대한 Crusty 발표[1]도 기억남. 강한 견해가 좋았지만, Apple은 나중에 오래된 조언이 있다는 이유로 그 영상을 내렸음. 지금은 Adobe에 있다니, 이게 Adobe 언어인가 싶음
    결론은 지켜볼 가치가 있고, 링크된 발표를 본 뒤 기다려보자는 쪽임
    [1] Crusty 발표를 찾았음: "I don't do Object Oriented!" https://www.youtube.com/watch?v=p3zo4ptMBiQ

    • David Abrahams는 Apple에 있기 전부터 Boost의 매우 중요한 기여자였고, C++ 위원회 멤버이자 Stepanov식 제네릭 프로그래밍의 강한 지지자였음. Val 프로젝트에 합류한 건 놀랍지 않음
  • 컴파일러 개발자로서 아래 이슈들을 보고 충격받았음
    https://github.com/val-lang/val/issues/758
    https://github.com/val-lang/val/issues/711
    구현 상태가 좋지 않은 냄새가 남. 가능한 빨리 자가 호스팅해야 하고, 그러면 이런 기본 버그를 더 많이 찾게 될 것임. 그런데도 별이 500개가 넘음

    • 다른 컴파일러 개발자로서 보면, 너무 이른 자가 호스팅만큼 해로운 실수도 드묾. 언어가 소·중형 프로그램에는 순이익이 되더라도, 컴파일러처럼 큰 프로젝트에 적합하고 도구까지 갖추려면 훨씬 오래 걸림. 서두르지 않는 게 다행임
    • 저런 버그가 운영 중인 컴파일러에 있다면 걱정스럽지만, 아직 정의 중인 언어의 컴파일러라면 그렇게까지 문제는 아님. Rust 1.0과 1.71을 비교해 보면 “첫 안정 릴리스”와 “실사용이 많은 안정 언어의 컴파일러” 사이에 얼마나 큰 간극이 있는지 알 수 있음
      자가 호스팅도 전부가 아님. 무엇보다 상징적 이정표에 가깝고, 달성하면 축하할 일이지만 개발 주기의 훨씬 뒤까지는 그 언어의 약점으로 삼을 일은 아니라고 봄
    • Swift 자체도 아직 자가 호스팅하지 않으며 버전 6 릴리스를 앞두고 있음. 컴파일러 개발자는 아니지만, Swift 커뮤니티에서 이 주제를 둘러싼 논의의 결론은 아직 그럴 가치가 없다는 쪽이었음
  • 예전부터 “Val 가지고 놀기”를 미뤄 두다가 오늘 드디어 시도했는데, 커밋이 4,000개가 넘었어도 아직 사용 가능 상태와는 거리가 멂. 언어 둘러보기의 예제 대부분이 컴파일되지 않고, 겉보기에 단순한 예제도 실패함
    Carbon은 아직 제대로 내놓은 게 없고, Sean Baxter는 Circle 컴파일러에서 많은 진전을 내며 Carbon의 좋은 부분도 여럿 구현하고 있음. 아직 언어라고 보기 어려우면 후계자가 되기도 어렵다

  • 이제 V, Val, Vala, Vale이 있음. 내가 잊은 다른 언어도 있나?

    • VAL도 있음. 80년대 언어 중 하나로, SISAL을 통해 Haskell에 영향을 줬음. 다만 병렬 언어 커뮤니티 밖에서는 그 VAL을 아는 사람이 많지 않을 듯함
    • 비슷한 이름은 오히려 유리하게 작용할 수 있음. 이런 언어를 배우는 사람은 “새로운 핫한 것”을 찾는 중일 가능성이 크고, 비슷한 이름의 다른 언어도 알게 되어 찾아볼 수 있음. JavaScript도 그랬는데, 결과가 나쁘진 않았음
    • 이게 정말 Vale인 줄 알았음. 이름 충돌이 꽤 아쉬움
    • 덤으로 V는 Vlang이라고도 불리고, Vale도 예전에는 Vlang이라고 불렸음
  • 매번 나오는 얘기지만, Val에서 유일하게 마음에 안 드는 건 ValeV도 새 시스템 언어라는 점임. 이름 때문에 셋이 너무 쉽게 헷갈림

    • Vala도 있음. 영역은 좀 다르지만 비슷한 이름의 언어가 하나 더 있음
    • 이게 projection 언어인지 region 언어인지 확인하려고 링크까지 들어가 봐야 했음
    • VAL: Variable Assembly Language도 있음 https://en.m.wikipedia.org/wiki/Variable_Assembly_Language
  • 관련 글이 있음. 또 있나?
    Val, a new programing language inspired by Swift and Rust - https://news.ycombinator.com/item?id=31788527 - 2022년 6월, 댓글 19개

  • “mutable value semantics” 논문을 훑어봤는데, 저자들이 참조와 포인터를 a) 중첩 구조체와 Any를 통한 일부 간접화 및 런타임 검사, b) 배열 인덱스로 대체하자고 제안하는 것으로 이해하면 맞는지 궁금함
    “가변 값 타입으로 이중 연결 리스트나 방향 그래프 같은 자기 참조 자료구조를 어떻게 표현할 수 있느냐고 묻는 건 타당하다. 사실 임의의 그래프는 인접 리스트로 표현할 수 있다…”라는 구절이 눈에 띄었음. 구현 안에서 메모리 힙과 일종의 가비지 컬렉션을 다시 만들지 않고 이중 연결 리스트를 합리적으로 구현하는 방법은 잘 안 보임
    추가로 https://github.com/orgs/val-lang/discussions/736에서 논의를 찾았고, Rust의 unsafe 같은 탈출구가 생길 듯함. 그러면 모든 문제는 해결되지만, “Val의 안전한 부분집합만으로 실용적인 애플리케이션을 만들기에 충분한가”라는 질문은 앞으로 오랫동안 논쟁거리로 남을 듯함

    • 배열을 쓰고 포인터 대신 배열 인덱스를 쓰면 실제로 메모리를 다시 만들 수 있음
      생각보다 덜 어리석은 방식인 이유는, 이 인덱스들이 특정 자료구조, 예를 들어 이중 연결 리스트나 그래프에 묶여 있어서 프로그램의 다른 곳에 접근하도록 조작하기가 쉽지 않기 때문임. 컴파일러가 이를 검사하는 경우에도, 프로그램을 깨려는 시도에도 해당됨
  • 홈페이지 예제의 설명을 어떻게 읽어야 할지 모르겠음. “불필요한 할당은 발생하지 않는다. longer_of의 결과는 더 긴 인자의 projection이므로 emphasize가 z를 변경하면 y 값에 직접 변경이 일어난다. 값은 복사되지도 이동되지도 않지만, emphasize에 참조로 전달되는 것도 아니다”라고 되어 있음
    문자열 인자가 함수에 전달되고 문자가 덧붙여지는 상황인데, 기존 문자열은 초기 길이와 스택상의 특정 위치·크기를 가졌을 텐데 어떻게 y의 새 복사 없이 가능하다는 건지 모르겠음. 혹시 누군가 덧붙일 경우를 대비해 문자열 끝에 여분 패딩을 두는 건가? 그렇다면 패딩을 얼마나 두고, 왜 전반적으로 더 비효율적이지 않은가?

    • 네 칸 접두사는 인용이 아니라 코드/고정폭 블록용임. HN에서는 보통 > 관습을 써서 인용하는데, 파서가 특별 처리하지 않아도 잘 통함
    • 불변 값이라고 해서 반드시 스택에 있어야 하는 건 아님
      다만 비슷한 의문은 있음. 1GB 문자열을 수정하면 어떻게 되나? 쓰기 시 복사인가?
      99%의 경우 최적화로 사라질 수는 있겠지만, 남은 1%에서 찾기 매우 어려운 성능 저하가 생길 것 같은 느낌임
    • 며칠 뒤 스스로 답해 보자면, 변경된 변수 이름을 더 긴 새 값으로 스택에서 은밀히 shadowing한다면 가능한 듯함. 아마 이게 “projection”의 의미일 수도 있음. 이 경우 스택은 이미 할당되어 있으니 새 할당은 일어나지 않음. 언어나 컴파일러 전문가는 아니라서 이 용어가 그쪽에서는 잘 알려져 있을 수도 있음
    • 아래쪽에 더 설명이 있음. longer_of는 함수가 아니라 subscript이고, subscript는 값을 반환하지 않고 값을 projection하여 호출자에게 임시 읽기/쓰기 접근권을 준다고 함
      이게 어떻게 이동에 해당하지 않는지는 잘 모르겠음. 문자열의 경우 Rust처럼 가변 크기를 허용하려고 힙에 둘 수도 있음