我知道Ruby是动态且强烈键入的,但是Afaik,当前语法不允许在编译时间检查由于缺乏明确的类型符号(或合同)而在编译时间检查的类型参数。
如果我想执行编译时类型检查,我有什么(实际上是成熟的)选项?
update
我的意思 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
另外,我的意思是 compile time =在运行脚本之前。我没有更好的词来描述它……
有一个用于开发类型系统,类型推断器,类型检查器和语法的项目用于(一个子集的)Ruby的类型注释,称为Diamondback Ruby。它是4年前被放弃的,您可以在Github上找到其来源。
但是,基本上,该语言不再是Ruby。如果静态类型对您如此重要,那么您可能应该只使用静态打字的语言,例如Haskell,Scala,Ml,Agda,Coq,ATS等。Div>
RDL是用于静态类型检查Ruby/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: ^~~~~~~~~~~
它似乎已经有很好的记录!
虽然您无法在静态时间内检查一下,但是您可以在您的仅在检查对象后才运行的方法。#is_a?
和#kind_of?
派上用场...
def method(variable)
if variable.is_a? String
...
else
...
end
end
您可以选择返回指定的错误值或提出异常。希望这与您要寻找的东西很近。
您正在要求使用" compile-time"类型检查,但是在Ruby中,没有"编译"阶段。红宝石代码的静态分析几乎是不可能的,因为即使从内置类中也可以在运行时重新定义任何方法。类也可以在运行时动态创建和实例化。您将如何对程序启动时甚至不存在的类进行类型检查?
当然,您的真正目标不仅是"键入检查您的代码"。您的目标是"编写有效的代码",对吗?类型检查只是一种工具,可以帮助您"编写有效的代码"。但是,尽管类型检查很有帮助,但它具有限制。它可以捕获一些简单的错误,但不是大多数错误,也不是最困难的错误。
选择使用Ruby时,您将放弃类型检查的好处。但是,Ruby May 允许您比您习惯的其他语言更少的代码完成工作。使用少的代码编写程序,这意味着通常需要修复的错误。如果您巧妙地使用Ruby,我相信这是值得的。
尽管您无法在Ruby中键入代码,但是使用检查方法参数的断言具有很大的价值。在某些情况下,这些断言可能会检查参数的类型。他们会更频繁地检查参数的其他属性。然后,您需要一些练习代码的测试。您会发现,使用相对较少的测试,您会捕获的错误比C/C 编译器可以做的更多。
似乎您似乎想要静态类型。由于语言的动态性质,在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
无论如何,我认为您不会从上述中受益。我建议改用鸭子打字。
您可能对"可插拔类型系统"的想法感兴趣。这意味着将静态类型系统添加到动态语言中,但是程序员决定应输入的内容和剩下的内容。Typechecker搁置了核心语言,通常将其实现为库。它可以在开发过程中应使用并执行测试时使用的特殊"检查"模式进行静态检查或在运行时检查类型。
我发现的Ruby的类型检查器称为RTC(Ruby Type Checker)。Github,学术论文。动机是要对函数或方法的参数的类型提出要求,将要求从测试中移出到类型注释中,然后将类型注释转换为"可执行文件"。来源。