代码之家  ›  专栏  ›  技术社区  ›  dharmatech

Perl6类型推断

  •  10
  • dharmatech  · 技术社区  · 8 年前

    鉴于:

    sub abc(Int $n) { say $n }
    

    如果传递的变量类型为 Str abc 我们得到一个编译时错误:

    my Str $s = "123";   abc $s;
    

    如果传递一个包含字符串的非类型化变量,则会得到一个运行时错误:

    my $s = "123";   abc $s;
    

    C++支持一个 auto 允许类型推断的关键字。

    是否可以定义 汽车 在Perl6中,这样:

    auto $s = "123";
    

    会导致 $s 打印为 STR ?

    也就是说,我们可以这样做:

    auto $s = "123";   abc $s;
    

    并得到一个编译时错误。

    3 回复  |  直到 7 年前
        1
  •  7
  •   raiph    8 年前

    是否可以定义 auto 在Perl 6中

    我想是的,差不多吧。但我要把你的问题翻译成三个不同的问题来提供一个更有用的答案。

    以下前两个问题的答案请参考 a reddit comment I wrote about this 。我的评论分为四部分,用横线分隔。第一部分和最后一部分与你的问题有关。

    是否可以修改Perl6语言?

    对。

    您可以或多或少地从userland代码中任意修改perl 6语言。

    引用我上面链接的评论的第一部分的要点:

    • 内部俚语DSL使用语法构建,与外部DSL类似,但通过俚语机制与标准Perl6语法混合。必须编写这些DSL,以便与标准Perl6语法至少有一些基本协调。用这种DSL编写的代码显示为内联,与常规代码不可区分。 Relevant slides .

    引用我写的最后一部分:

    虽然俚语可以实现…他们没有得到官方的支持…而且不像他们需要的那么甜。

    是否可以编写与编译器通信的编译时宏?

    对。

    不幸的是,您还不能定义语句宏,这是您需要的新类型的变量声明。引用我上面链接的评论中的最后一节:

    “如果您希望内部DSL,但它在语法上与标准Perl6冲突,无法仅使用用户定义的例程和运算符,那么您需要的设计选项是……写一个 is parsed 宏[或]写俚语。理论上,这两种方法都可以解析您想要的任何语法。但是 已分析 宏还没有着陆,看起来至少还有一到三年了——它们仍然只是一个正在讨论的设计概念。 007 ."

    Perl6中有没有可能有新的想法?

    对。

    只需实现你的想法并游说它的包含。可能从俚语开始。可能只是直接攻击整个编译器。

    我对最后一点很认真。

    Rakudo Perl6编译器当然是开源的。

    更重要的是,大部分 written in Perl 6 。(而不是Perl6的大部分内容是nqp,它基本上是完整Perl6的一个子集。)

    结论

    如果你能写一些基本的Perl6代码;愿意 ask loads of questions on the freenode IRC channel #perl6-dev ;并且是有耐心的;那么您应该能够在Perl6和您的 汽车 这个想法似乎相对简单。

    (在“相对”的情况下,我想象一个知识渊博的核心开发人员可以在几个小时内完成概念验证,前提是我正确理解了他们面临的问题。有一天,当俚语和/或宏更为精练时,可能需要一个小时左右。)

        2
  •  5
  •   jjmerelo    8 年前

    你要找的可能就是我们所说的 allomorphs 在Perl6中,根据上下文的不同,类型的行为会有所不同。对于您发布的特定案例,有 IntStr allomorph :

    sub abc(Int $n) { say $n }
    my IntStr $s = <123>;
    abc $s; # prints 123
    

    (请注意,它需要 quote-words <> 而不是平常 "" )同素异形通常是它们可以被类型化的类的子类; IntStr 子类 Int Str 。一般来说,这可以用于任何类型 auto ,只要它们是相互转换的。

    另一个选择是,如果你已经知道你将得到什么和它将变成什么,那就是 use coercion :

    sub bcd(Int(Str) $n) { say $n }
    my $t = "123";
    bcd $t; # prints 123
    

    在这种情况下,字符串将被强制为 int Capture 在被子程序体使用之前。

    最后,你可以使用 the number contextualizer ,只要在有效使用变量时使用。

    sub efg($n) { say +$n }
    my Int $u = 123;
    my Str $v = "123";
    efg $u;
    efg $v;
    

    + 将变量放入数字上下文中,自动将其转换为数字。如果您想将其限制为int或str,甚至可以将其转换为签名约束。

    sub xyz($n where $_ ~~ Int | Str ) { say +$n }
    xyz $u;
    xyz $v;
    xyz $t;
    xyz $s;
    

    (它使用上面定义的变量)在这里,无论变量是否没有指定类型(如 $t 或已被定义为 英特尔 , int STR )只要它可以智能匹配 int STR 将其输入子体并通过上下文化转化为数字。

    完整程序是 here ,以防您要下载并检查它。

        3
  •  5
  •   dwarring    7 年前

    我只是想提一下 Proxies 。这些工作在容器级别,并且只在运行时进行。但是给一些能力来控制或跟踪变量的变化。

    sub auto($v?) is rw {
        my $val = $v;
        Proxy.new(
            FETCH => -> $, { $val },
            STORE => -> $, $new-val {
                die "You canna change type from {$val.WHAT.^name} to {$new-val.WHAT.^name}"
                    unless $new-val.WHAT ~~ $val.WHAT;
                $val = $new-val;
            }
        )
    }
    
    my $i := auto(11);
    $i = 69;
    say $i;
    $i = 'blah'; # Boom
    

    代理可以用来实现类似 auto 类型,但仅在运行时和容器级别。它们也不像与变量相关联的容器那样防水。例如,使用绑定 := 操作人员

    $i := 'he he'; # changed container