有没有办法在Ruby中执行编译时类型检查?

时间:2014-01-19 01:08:26

标签: ruby compile-time typechecking

我知道Ruby是动态且强类型的,但是AFAIK,当前语法不允许在编译时检查参数的类型,因为缺少每个参数的显式类型表示法(或契约)。

如果我想执行编译时类型检查,我有哪些(几乎成熟的)选项?

更新

我的意思 type-check 就像典型的静态类型语言。如C. 例如,C函数表示每个参数的类型,编译器检查传入参数是否正确。

void func1(struct AAA aaa)
{
    struct BBB bbb;
    func1(bbb);  // Wrong type. Compile time error.
}

作为另一个例子,Objective-C通过提供显式类型信息来实现这一点。

- (id)method1:(AAA*)aaa
{
    BBB* bbb = [[AAA alloc] init];  // Though we actually use correctly typed object...
    [self method1:bbb];             // Compile time warning or error due to type contract mismatch.
}

我想要那样的东西。

更新2

另外,我的意思是编译时=在运行脚本之前。我没有更好的词来描述它......

6 个答案:

答案 0 :(得分:1)

有一个项目,用于开发一个类型系统,一个类型推断器,一个类型检查器和一个类型注释的语法,用于Ruby的一个子集,称为Diamondback Ruby。它被废弃了4年前,你可以找到its source on GitHub

但是,基本上,那种语言将不再是Ruby。如果静态类型对你来说如此重要,你应该只使用静态类型语言,如Haskell,Scala,ML,Agda,Coq,ATS等。毕竟,这就是他们的目的。

答案 1 :(得分:1)

RDL是一个用于Ruby / Rails程序的静态类型检查的库。它包含标准库和(我认为)Rails的类型注释。它允许您向方法/变量/等添加类型。像这样:

file.rb:

require 'rdl'

type '(Fixnum) -> Fixnum', typecheck: :now
def id(x)
  "forty-two"
end

然后运行file.rb将执行静态类型检查:

$ ruby file.rb
.../lib/rdl/typecheck.rb:32:in `error':  (RDL::Typecheck::StaticTypeError)
.../file.rb:5:5: error: got type `String' where return type `Fixnum' expected
.../file.rb:5:     "forty-two"
.../file.rb:5:     ^~~~~~~~~~~

似乎有很好的记录!

答案 2 :(得分:0)

似乎你想要静态类型。由于语言的动态特性,在Ruby中没有一种有效的方法可以做到这一点。

我能想到的一个天真的方法就是制定一个这样的“契约”:

def up(name)
  # name(string)

  name.upcase
end

因此,每个方法的第一行将是一个注释,声明每个参数必须具有的类型。

然后实施一个静态扫描的工具&通过扫描上述方法的调用站点来分析源并捕获此类错误,并在可能的情况下检查传递的参数的类型

例如,这很容易检查:

x = "George"
up(x)

但你怎么检查这个:

x = rand(2).zero? "George" : 5
up(x)

换句话说,大多数情况下,在运行之前无法推断出类型。

但是,如果你不关心静态发生“类型检查”,你也可以这样做:

def up(name)
  raise "TypeError etc." unless name.is_a? String
  # ...
end

无论如何,我认为你不会从中受益。我建议改用鸭子打字。

答案 3 :(得分:0)

虽然您无法在静态时间检查中进行检查,但只有在检查对象后才能使用方法中的条件运行。
这里#is_a?#kind_of?派上用场......

def method(variable)
    if variable.is_a? String
        ...
    else
        ...
    end
end

您可以选择返回指定的错误值或引发异常。希望这接近你想要的。

答案 4 :(得分:0)

您要求进行“编译时”类型检查,但在Ruby中,没有“编译”阶段。 Ruby代码的静态分析几乎是不可能的,因为任何方法,甚至是内置类,都可以在运行时重新定义。还可以在运行时动态创建和实例化类。如何在程序启动时对类甚至不存在的类进行类型检查?

当然,您的真正目标不仅仅是“对代码进行类型检查”。你的目标是“编写有效的代码”,对吧?类型检查只是一种工具,可以帮助您“编写有效的代码”。但是,虽然类型检查很有用,但它有其局限性。它可以捕获一些简单的错误,但不是大多数错误,而不是最困难的错误。

当您选择使用Ruby时,您放弃了类型检查的好处。但是,Ruby 可能允许您使用 less 代码完成任务,而不是您习惯使用的其他语言。使用 less 代码编写程序意味着通常可以解决更少的错误。如果你巧妙地使用Ruby,我相信这种权衡是值得的。

虽然您无法在Ruby中对代码进行类型检查,但使用检查方法参数的断言具有很大的价值。在某些情况下,这些断言可能会检查参数的类型。更常见的是,他们会检查参数的其他属性。然后你需要一些练习代码的测试。您会发现,只需要进行相对较少的测试,您就会发现比C / C ++编译器更多的错误。

答案 5 :(得分:0)

您可能对"可插拔类型系统"的想法感兴趣。这意味着将静态类型系统添加到动态语言中,但程序员决定应该键入什么以及什么是无类型。类型检查器不使用核心语言,它通常作为库实现。它可以在运行时通过特殊的"检查"进行静态检查或检查类型。应该在开发期间使用的模式以及执行测试。

我发现的Ruby I的类型检查器称为Rtc(Ruby Type Checker)。 Githubacademic paper。其动机是明确对函数或方法的参数类型的要求,将需求从测试中移出到类型注释中,并将类型注释转换为可执行文档"。 Source