Raku의 매개 변수화 된 유형, 런타임 값을 매개 변수로 사용하는 방법

Nov 28 2020

Raku에 대한 매개 변수화 된 유형 을 만들고 싶습니다 . 기본적으로 속성 중 하나의 값 범위가 주요 차이점 인 몇 가지 다른 클래스를 만들고 싶습니다. 예를 들어, 클래스는 건물의 유형을 나타내며, 3 층 또는 기타 여러 층의 건물에 대해 다른 클래스를 갖고 싶습니다. 그래서 이것이 제가 생각할 수있는 최고입니다.

subset Two-Tops of UInt where * <=2;
subset Three-Tops of UInt where * <=3;

role Zipi[ ::Capper ] {
    has Capper $.floor; } class Capped-at-three does Zipi[Three-Tops] {} my $capped = Capped-at-three.new( floor => 2 );
say $capped.raku;

여러 층 수를 관리해야하는 즉시 이것은 분명히 비실용적입니다 (그라나다에있는 것은 아니지만, 최대 10 층이있는 것 같지만 ...). 여기서 문제는 기본적으로 컴파일 타임에 하위 집합에 대한 정보가 있어야하므로 매크로 를 사용하지 않는 한 (아직 실험적인) 변수를 사용할 수있는 방법이 없습니다. 매개 변수 값에 대해 이러한 종류의 커리 역할 을 정의하는 실용적인 방법을 생각할 수 있습니까?

답변

8 user0721090601 Nov 28 2020 at 15:51

사실, 이전에 말했듯이 where 절에서 문제없이 조건을 사용할 수 있습니다. 중괄호로 묶기 만하면됩니다.

role Zipi[$condition] { has $.floor is rw where {$_ ~~ $condition}
    method foo($x) { $!floor = $x } } class A does Zipi[2 < * < 5] { method bar($x) { $.floor = $x }
}

#my $a = A.new( floor => 10); # error my $a = A.new( floor => 4); # OK

#$a.foo(10); # error $a.foo(3); # OK

#$a.bar(0); # error $a.bar(4); # OK

#$a.floor = 9; # error $a.floor = 3; # OK

모든 할당 유형을 포함해야합니다.

5 raiph Nov 28 2020 at 04:15

나는 매우 제한된 MOP 찹을 가지고 있으며 다음은 추악 해 보이지만 작동하며 올바른 방향으로 나아가는 단계 일 수 있습니다.

내가 한 것:

  • subsetMOP를 통해 10,000 초의 배열을 동적으로 구성했습니다 .

  • 시간은 BEGIN.

  • 역할을 매개 변수화하기 위해 배열에서 적절한 요소를 사용했습니다.

my @max-floors-checkers; 
BEGIN {
  @max-floors-checkers = do for ^10_000 -> \floors {
    Metamodel::SubsetHOW.new_type: 
      refinee => UInt,
      refinement => { $^floors <= floors } } } role BuildingCategory[ ::MaxFloorsCheck ] { has MaxFloorsCheck $.floors }
    
class Capped-at-three does BuildingCategory[ @max-floors-checkers[3] ] {}

my $capped3 = Capped-at-three.new( floors => 2 ); say $capped3.raku;                                # Capped-at-three.new(floors => 2

my $capped4 = Capped-at-three.new( floors => 4 ); # Type check failed 
3 user0721090601 Nov 28 2020 at 01:40

익명의 where절을 사용해 보았지만 아무 소용이없는 것과 비슷하지만 문제를 추적했습니다. where절이 BUILD메서드에 의해 분명히 무시되고 있습니다. 절 $!floor을 우회하는 직접 액세스 (를 통해 ) 가 있기 때문인지 where또는 다른 이상한 일이 진행 중인지 (아마 후자 일 Nil경우 where절 에서 매개 변수화 된 값을 사용하려고하면 일반적으로 얻었습니다 ) 확실하지 않습니다 .

그럼에도 불구하고 이것은 유용한 오류 메시지를 제공하는 것을 포함하여 잘 작동합니다.

role Zipi[$condition] {
    has $.floor; submethod BUILD(:$floor, |c) {
        die "Invalid floor number."
            unless $floor ~~ $condition;
        $!floor = $floor;
    }
}

바닥이 항상이라고 가정 할 수 0 .. x있거나 x .. y훨씬 더 유용한 오류 메시지를 제공 할 수 있다면 수정하기가 얼마나 쉬운 지 알 수 있습니다 .

1 raiph Nov 29 2020 at 21:38

독자가 Java를 알고 있지만 Raku를 아는 경우를 다루는 nanswer.

Collection<String> coll = new LinkedList<String>();

Raku의 매개 변수화 된 유형

링크 된 Java 예제는 다음과 같습니다.

실제 형식 인수가있는 제네릭 형식의 인스턴스화를 매개 변수가있는 형식이라고합니다. 예 (매개 변수화 된 유형) :

Collection<String> coll = new LinkedList<String>();

합리적인 Raku 아날로그는 다음과 같습니다.

my Positional[Str] \coll = Array[Str].new;

Positional유형은 매개 변수화입니다 역할 . 역할은 인터페이스 및 / 또는 유형의 부분 구현을 지정합니다. 나는 Raku 가이 nanswer의 목적을 위해 제공된다는 점 Positional에서 Java와 충분히 유사 하다고 생각 Collection합니다.

Array유형은 매개 변수화입니다 클래스 . Positional역할 을 준수하는 데이터 구조를 지정합니다 . 연결된 목록은 아니지만이 nanswer의 목적에 충분합니다.