Skip to content

간단한 값

닉스는 다음의 기본 데이터 타입을 가집니다:

  • 문자열은 세가지 방법으로 작성 가능합니다.

    가장 흔한 방법은 문자열을 쌍따옴표로 닫는 것입니다. 예를 들어, "foo bar"와 같습니다. 문자열은 여러 줄에 걸쳐 존재할 수 있습니다. 특수 글자 "\, 그리고 글자열 ${은 반드시 그것들에 백슬래시(\)를 붙여야 표기할 수 있습니다. 새 줄 입력(newline)과 캐리지 리턴, 탭은 각각 \n, \r, \t을 사용합니다.

    표현식의 결과물을 문자열로 포함하고자 한다면 ${...}로 닫아야 합니다. 이를, 인용방지(antiquotation)이라 부릅니다. 위처럼 닫혀 있는 내부 표현식은 반드시 문자열로 변환할 수 있는 결과를 반환해야 합니다 (이는 문자열 자체이거나, 경로, 제작물이어야 함을 의미합니다). 예를들어, 아래처럼 쓰기보다

    "--with-freetype2-library=" + freetype + "/lib"
    

    (freetype이 제작물일 때), 아래처럼 더 자연스럽게 작성할 수 있습니다.

    "--with-freetype2-library=${freetype}/lib"
    

    후자가 전자보다 더 자동적으로 번역됩니다. 더 복잡한 예시는 Qt를 위한 닉스 표현식입니다:

    configureFlags = "
      -system-zlib -system-libpng -system-libjpeg
      ${if openglSupport then "-dlopen-opengl
        -L${mesa}/lib -I${mesa}/include
        -L${libXmu}/lib -I${libXmu}/include" else ""}
      ${if threadSupport then "-thread" else "-no-thread"}
    ";
    

    닉스 표현식과 문자열은 임의로 내부에 포함할 수 있음(nested)을 주목하세요; 이 경우 바깥 문자열은 다양한 인용 방지를 포함하는데 그것들 자체가 문자열(예, "-thread") 를 가지고 있고, 일부는 표현식(예, ${mesa})을 가지고 있습니다.

    문자열을 표기할 수 있는 두번째 방법은 들여쓴 문자열입니다. 이는 두개의 홑 따옴표 쌍으로 둘러 쌓인 문자열을 가리킵니다. 아래와 같습니다:

    ''
      This is the first line.
      This is the second line.
        This is the third line.
    ''
    

    이러한 종류의 문자열은 각 줄의 들여쓰기를 똑똑하게 제거합니다. 더 정확히 표현하자면, 전체에서 들여쓰여진 것중 최소의 빈칸만큼 각 줄에서 제거합니다 (빈 줄의 들여쓰기는 고려하지 않음). 예를 들어, 첫 째와 둘째 줄은 2칸이 들여쓰였지만, 셋 째 줄은 4칸이 들여쓰였습니다. 따라서, 2칸만 제거되고 결과는 아래와 같습니다.

    "This is the first line.\nThis is the second line.\n  This is the third line.\n"
    

    첫 줄에 공백문자가 아닌 글자를 포함하지 않는 이상 ''다음에 나오는 공백이나 새 줄 입력은 무시된다는 것을 주의하기 바랍니다.

    인용 방지(${exprt})는 들여쓴 문자열에서도 지원됩니다.

    ${''는 들여쓴 문자열에서 특수 의미를 지니기 때문에 그것들 자체를 인용하는 다른 방법이 필요합니다. $''를 앞에 붙임으로써 작성할 수 있습니다(이는, 두개의 홑 따옴표를 의미함), 예를 들어, ''$과 같습니다. ''는 앞에 '를 붙임으로써 작성하라 수 있습니다, 예를 들어, '''. $는 뒤따라오는 $의 특수 의미를 제거합니다. 새 줄 입력과, 캐리지 리턴, 탭 글자는 ''\n, ''\r, ''\t, ''\와 같이 써서 작성할 수 있습니다.

    들여쓴 문자열은 둘러쌓인 닉스 표현식의 들여쓰기를 여러 줄에 걸쳐 따를 수 있으므로 특히 유용합니다. 뿐만 아니라 쉘 스크립트에서 특수 문자 작성에 공을 덜 들여도 되므로 편하고, 일반적으로 설정 파일에서 ''"보다 덜 사용된다는 점도 유용합니다. 예시:

    stdenv.mkDerivation {
      ...
      postInstall =
        ''
          mkdir $out/bin $out/etc
          cp foo $out/bin
          echo "Hello World" > $out/etc/foo.conf
          ${if enableBar then "cp bar $out/bin" else ""}
        '';
      ...
    }
    

    마지막으로, 편의를 위해, URI들은 RFC 2396의 부록 B에 적힌 것처럼 있는 그대로, 인용 부호 없이 작성이 가능합니다. 예를 들어, 문자열 "http://example.org/foo.tar.bz2"http://example.org/foo.tar.bz2처럼 사용해도 무방합니다.

  • 숫자, 정수형 (like 123)이거나 부동 소수점 (like 123.43 or .27e13).

    숫자들은 서로 타입-호환적입니다: 순수 정수형 연산은 정수형을 반환하는 반면 어느 연산이든 적어도 하나의 부동 소수점 숫자를 사용하는 경우 부동 소수점을 결과로 반환합니다.

  • 경로, 예시, /bin/sh 혹은 ./builder.sh. 경로는 경로로 인식되기 위해서 반드시 적어도 하나의 슬래시를 포함해야 합니다. 예를 들어, builder.sh는 경로가 아닙니다: 이는 builder 변수의 sh 특성을 선택하는 닉스 표현식으로 이해될 것입니다. 만약 파일 이름이 상대적 경로면, 예를 들어, 슬래시로 시작하지 않는 경우, 그런 경로를 포함하는 닉스 표현식은 해석 시점에 절대 경로로 변경됩니다. 예를 들어, /foo/bar/bla.nix의 닉스 표현식이 ../xyzzy/fnord.nix를 지칭하는 경우, 절대 경로는 /foo/xyzzy/fnord.nix로 변환됩니다.

    만약 첫 구성이 ~로 시작하는 경우, 사용자의 홈 디렉터리를 지칭하는 것으로 해석됩니다. 예를 들어, ~/foo/home/edolstra를 홈 디렉터리로 사용하는 사용자에게 /home/edolstra/foo와 동일합니다.

    경로는 화살 괄호(<) 사이에 쓰일 수 있습니다. 에를 들어, <nixpkgs>. 이는 주어진 파일이나 디렉터리 이름이 NIX_PATH 환경 변수에 적혀있는지 탐색된다는 것을 의미합니다.

    인용 방지는 화살 괄호를 제외한 모든 경로에서 지원됩니다. ./${foo}-${bar}.nix./. + "/" + foo + "-" + bar + ".nix"./. + "/${foo}-${bar}.nix" 를 적기 위한 더 편리한 방법입니다. 이런 표현 방식이 경로로 이해되기 위해서는 반드시 그 어떤 인용 방지라도 등장하기 전에 적어도 하나의 슬래시가 등장해야 합니다. a.${foo}/b.${bar}는 문법적으로 유효한 나누기 연산입니다. ./a.${foo}/b.${bar}는 경로입니다.

  • 불린truefalse를 가집니다.

  • 널(null) 값은 null로 표기됩니다.

리스트

리스트는 대괄호로 표기하며, 공백 문자로 구분되는 값들의 목록입니다. 예를 들어,

[ 123 ./foo.nix "abc" (f { x = y; }) ]

위 는 네 요소로 이루어진 리스트를 정의합니다. 마지막 요소는 함수 f를 호출한 결과값으로 이루어집니다. 함수 호출은 소괄호로 둘러쌓여야 한다는 점을 확인하시기 바랍니다. 만약 생략된다면, 예를 들어,

[ 123 ./foo.nix "abc" f { x = y; } ]

결과값은 5개 요소로 이루어진 리스트가 되며 네 번째 요소는 함수, 5번째 요소는 집합이 됩니다.

리스트는 값에 있어서만 게으르고, 길이에는 엄격함을 기억하시기 바랍니다.

집합

집합은 정말 언어의 핵심에 해당합니다. 닉스 언어가 궁극적으로 제작물을 생성해내고, 그 제작물이란 결국 빌드 스크립트에 전달되는 특성 집합이기 때문입니다.

집합은 단지 이름과 값 쌍(특성이라고 부름)으로 이루어진 리스트입니다. 이는 중괄호로 둘러쌓여져 있고 각 값은 임의의 표현입니다. 해당 표현들은 세미콜론으로 종료됩니다. 예를 들어:

{ x = 123;
  text = "Hello";
  y = f { bla = 456; };
}

위는 xtext, y 특성으로 구성된 집합을 정의합니다. 특성의 순서는 상관없습니다. 하나의 특성은 반드시 한번만 등장해야 합니다.

특성은 . 연산을 통해 접근이 가능합니다. 예를 들어,

{ a = "Foo"; b = "Bar"; }.a

위 명령은 "Foo"로 평가됩니다. 특성 집합에서 기본값을 제공하는 것도 가능합니다. 이는 or 키워드를 사용합니다. 예를 들어,

{ a = "Foo"; b = "Bar"; }.c or "Xyzzy"

위 명령은 c 특성이 집합에 존재하지 않기 때문에 "Xyzzy"로 평가됩니다.

임의의 쌍따옴표로 둘러쌓인 문자열을 특성 이름으로 사용할 수 있습니다:

{ "foo ${bar}" = 123; "nix-1.0" = 456; }."foo ${bar}"

위 명령은 123으로 평가됩니다(bar가 인용 방지용이라고 가정할 경우). 특성 네임이 하나의 인용방지로 이루어진 경우, 따옴표는 생략 가능합니다:

{ foo = 123; }.${bar} or 456

위 명령은 bar"foo"로 평가되는 문자열인 경우 123이 될 것이고 그렇지 않으면 456이 됩니다(다시 강조하지만 bar가 인용 방지 가능하다고 가정합니다).

집합 내부 평가 결과 집합 선언 내부 특성 이름이 null이 되는 특수한 경우 (일반적으로 null은 인용방지 불가하기 때문에 오류입니다), 그 특성은 단순히 집합에 추가되지 않을 뿐입니다:

{ ${if foo then "bar" else null} = true; }

이는 foofalse로 평가될 경우 {}가 됩니다.

__functor 특성이 호출 가능한 값을 갖는 집합의 경우 (예를 들어 그 자체가 함수이거나 __functor 특성의 값이 호출 가능한 것으로 하는 집합의 경우) 스스로가 함수인 것 처럼 적용이 가능하고, 집합 자체는 첫 번째로 전달됩니다. 예를 들어,

let add = { __functor = self: x: x + self.x; };
    inc = add // { x = 1; };
in inc 1

위 명령은 2로 평가됩니다. 이는 함수 호출자가 특별하게 다루는 방법을 제공하거나, 객체 지향 언어의 일부 특성을 구현할 필요가 없이도 함수에 메타 데이터를 부착할 수 있도록 해줍니다.


Last update: November 4, 2021
Back to top