首页 文章

只有当它表示一个整数时,我怎样才能将Str转换为Int?

提问于
浏览
7

在Perl 6中,您可以指定可以强制类型的类型 . 如果你需要一个 Int 但得到一些可以转换成 Int 的东西 . 当您不希望 IntStr 的单独候选者(其中字符串表示整数值)时,这很方便 .

但是,转换似乎有点激进,因为转换不仅改变了类型,而且愿意改变数据 . 这部分是改变类型的混淆和将数字截断为整数的预期操作的问题 . 从概念上讲,这些是不同的想法,但它们在 Str.Int 中交织在一起(实际上是将一次旅行夹在了 Numeric ):

sub foo ( Int:D() $n ) { put "Got <$n> of type {$n.^name}" }
foo( 80 );     # Got <80> of type Int
foo( '99' );   # Got <99> of type Int
foo( 1.5 );    # Got <1> of type Int
foo( '1.5' );  # Got <1> of type Int

试图将此限制为 Str 并不是更好:

sub foo ( Int:D(Str:D) $n ) { put "Got <$n> of type {$n.^name}" }
foo( '1.5' );  # Got <1> of type Int

我可以制作一些似乎最容易理解的适配器:

multi foo ( Int:D $n ) {
    put "Got <$n> of type {$n.^name}"
    }
multi foo ( Str:D $n where { $^n.Int == $^n.Numeric } ) {
    foo( $n.Int );
    }

foo( '1.5' );  # Cannot resolve ...

我可能会想出一些子集,但这并不令人满意 . 所以诀窍是,我可以在不改变 Value 的情况下强制这样做(即使它改变了表示)吗?


事实证明,此功能已损坏,并且没有修复时间表:RT 132980 . 基本上,不强制执行目标类型 . 文档已更新 . 我的建议是根本不使用它 .

2 回答

  • 6

    Int:D(Any) 在Rakudo中的工作方式是创建一个接受 Any 的多候选者,将其转换为Int,并使用结果调用原始子例程 .

    如果您自己这样做,您可以更好地控制它的工作方式 .

    proto sub foo ( Int:D() $n ) {*}
    
    multi sub foo ( Any:D $n ) {
      my $i = try $n.Numeric.narrow;
    
      if $i ~~ Int:D {
    
        samewith $i
    
      } else {
    
        X::TypeCheck::Binding::Parameter.new(
    
          # there are more arguments that should be added here
          got => $n,
          expected => Int:D(),
    
        ).throw
    
      }
    }
    
    multi sub foo ( Int:D $n ) { put "Got <$n> of type {$n.^name}" }
    
  • 7

    一个可能的签名是

    Numeric() $ where Int
    

    或者,限制为字符串,

    Numeric(Str:D) $ where Int
    

相关问题