我知道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
另外,我的意思是编译时=在运行脚本之前。我没有更好的词来描述它......
答案 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)。 Github,academic paper。其动机是明确对函数或方法的参数类型的要求,将需求从测试中移出到类型注释中,并将类型注释转换为可执行文档"。 Source