Ada, Pascal and many other languages support ranges, a way to subtype integers. A range is a signed integer value which ranges from a value (first) to another (last). It's easy to implement a class that does the same in OOP but I think that supporting the feature natively could let the compiler to do additional static checks.
Ada,Pascal和许多其他语言支持范围,一种子类型整数的方法。范围是有符号整数值,其范围从值(第一个)到另一个(最后一个)。在OOP中实现相同的类很容易,但我认为本机支持该功能可以让编译器进行额外的静态检查。
I know that it's impossible to verify statically that a variabile defined in a range is not going to "overflow" runtime, i.e. due to bad input, but I think that something could be done. I think about the Design by Contract approach (Eiffel) and the Spec# ( C# Contracts ), that give a more general solution.
我知道静态验证在一个范围内定义的变量不会“溢出”运行时,即由于输入错误,我不可能,但我认为可以做些什么。我想到了契约式设计方法(Eiffel)和Spec#(C#契约),它们提供了更为通用的解决方案。
Is there a simpler solution that checks, at least, static out-of-bound assignment at compile time in C++, C# and Java? Some kind of static-assert?
是否有一个更简单的解决方案,至少在C ++,C#和Java的编译时检查静态的越界分配?某种静态断言?
edit: I understand that "ranges" can be used for different purpose:
编辑:我知道“范围”可以用于不同的目的:
- iterators
- enumerators
- integer subtype
I would focus on the latter, because the formers are easily mappable on C* language . I think about a closed set of values, something like the music volume, i.e. a range that goes from 1 up to 100. I would like to increment or decrement it by a value. I would like to have a compile error in case of static overflow, something like:
我会专注于后者,因为前者很容易在C *语言上映射。我想到一组封闭的值,比如音乐音量,即从1到100的范围。我想用一个值递增或递减它。我希望在静态溢出的情况下出现编译错误,例如:
volume=rangeInt(0,100);
volume=101; // compile error!
volume=getIntFromInput(); // possible runtime exception
Thanks.
11 个解决方案
#1
Subrange types are not actually very useful in practice. We do not often allocate fixed length arrays, and there is also no reason for fixed sized integers. Usually where we do see fixed sized arrays they are acting as an enumeration, and we have a better (although "heavier") solution to that.
子范围类型在实践中实际上并不是非常有用。我们不经常分配固定长度数组,也没有理由使用固定大小的整数。通常我们看到固定大小的数组,它们作为枚举,我们有一个更好的(虽然“更重”)解决方案。
Subrange types also complicate the type system. It would be much more useful to bring in constraints between variables than to fixed constants.
子范围类型也使类型系统复杂化。在变量之间引入约束比固定常数更有用。
(Obligatory mention that integers should be arbitrary size in any sensible language.)
(强制性地提到整数应该是任意合理语言的任意大小。)
#2
Java has had an assert keyword since version 1.4. If you're doing programming by contract, you're free to use those to check proper assignment. And any mutable attribute inside an object that should fall within a certain range should be checked prior to being set. You can also throw an IllegalArgumentException.
Java从版本1.4开始就有一个断言关键字。如果您按合同进行编程,则可以*地使用这些来检查正确的分配。并且应该在设置之前检查对象内应该落在某个范围内的任何可变属性。您还可以抛出IllegalArgumentException。
Why no range type? My guess is that the original designers didn't see one in C++ and didn't consider it as important as the other features they were trying to get right.
为什么没有范围类型?我的猜测是,原始设计师没有在C ++中看到它,并且认为它不像其他功能那样重要。
#3
Ranges are most useful when you can do something over that range, concisely. That means closures. For Java and C++ at least, a range type would be annoying compared to an iterator because you'd need to define an inner class to define what you're going to do over that range.
简洁地说,当你可以在这个范围内做某些事情时,范围是最有用的。这意味着关闭。至少对于Java和C ++,与迭代器相比,范围类型会很烦人,因为您需要定义一个内部类来定义您将在该范围内执行的操作。
#4
Pascal (and also Delphi) uses a subrange type but it is limited to ordinal types (integer, char and even boolean).
Pascal(以及Delphi)使用子范围类型,但它仅限于序数类型(整数,字符和偶数布尔值)。
It is primarilly an integer with extra type checking. You can fake that in an other language using a class. This gives the advantage that you can apply more complex ranges.
它是一个带有额外类型检查的整数。您可以使用类来伪造其他语言。这样可以使您可以应用更复杂的范围。
#5
For C++, a lib for constrained values variables is currently being implemented and will be proposed in the boost libraries : http://student.agh.edu.pl/~kawulak/constrained_value/index.html
对于C ++,目前正在实现受约束值变量的lib,并将在boost库中提出:http://student.agh.edu.pl/~kawulak/constrained_value/index.html
#6
In C# you can do this:
在C#中你可以这样做:
foreach(int i in System.Linq.Enumerable.Range(0, 10))
{
// Do something
}
#7
C++ allows you to implement such types through templates, and I think there are a few libraries available doing this already. However, I think in most cases, the benefit is too small to justify the added complexity and compilation speed penalty.
C ++允许您通过模板实现这些类型,我认为已经有一些库可用。但是,我认为在大多数情况下,其好处太小,不足以证明增加的复杂性和编译速度的损失。
As for static assert, it already exists. Boost has a BOOST_STATIC_ASSERT
, and on Windows, I think Microsoft's ATL library defines a similar one.
至于静态断言,它已经存在。 Boost有一个BOOST_STATIC_ASSERT,在Windows上,我认为微软的ATL库定义了一个类似的。
boost::type_traits
and boost::mpl are probably your best friends in implementing something like this.
boost :: type_traits和boost :: mpl可能是你实现这样的东西的最好朋友。
#8
The flexibility to roll your own is better than having it built into the language. What if you want saturating arithmetic for example, instead of throwing an exception for out of range values? I.e.
滚动自己的灵活性比将其内置到语言中更好。例如,如果您想要饱和算术,而不是为超出范围的值抛出异常,该怎么办?即
MyRange<0,100> volume = 99;
volume += 10; // results in volume==100
#9
I would add to Tom Hawtin response (to which I agree) that, for C++, the existence of ranges would not imply they would be checked - if you want to be consistent to the general language behavior - as array accesses, for instance, are also not range-checked anyway. For C# and Java, I believe the decision was based on performance - to check ranges would impose a burden and complicate the compiler.
我想补充Tom Hawtin的回应(我同意),对于C ++,范围的存在并不意味着它们会被检查 - 如果你想要与一般的语言行为保持一致 - 例如,数组访问是无论如何也没有范围检查。对于C#和Java,我认为决定是基于性能 - 检查范围会增加负担并使编译器复杂化。
Notice that ranges are mainly useful during the debugging phase - a range violation should never occur in production code (theoretically). So range checks are better to be implemented not inside the language itself, but in pre- and post- conditions, which can (should) be stripped out when producing the release build.
请注意,范围在调试阶段主要是有用的 - 在生产代码中(理论上)不应发生范围违规。因此,范围检查最好不是在语言本身内部实现,而是在前后条件下实现,在生成发布版本时可以(应该)将其删除。
#10
This is an old question, but just wanted to update it. Java doesn't have ranges per-se, but if you really want the function you can use Commons Lang which has a number of range classes including IntRange:
这是一个老问题,但只是想更新它。 Java本身没有范围,但是如果你真的想要这个函数,可以使用Commons Lang,它有很多范围类,包括IntRange:
IntRange ir = new IntRange(1, 10);
Bizarrely, this doesn't exist in Commons Math. I kind of agree with the accepted answer in part, but I don't believe ranges are useless, particularly in test cases.
奇怪的是,这在Commons Math中并不存在。我部分同意接受的答案,但我不认为范围是无用的,特别是在测试用例中。
#11
JSR-305 provides some support for ranges but I don't know when if ever this will be part of Java.
JSR-305为范围提供了一些支持,但我不知道它何时会成为Java的一部分。
#1
Subrange types are not actually very useful in practice. We do not often allocate fixed length arrays, and there is also no reason for fixed sized integers. Usually where we do see fixed sized arrays they are acting as an enumeration, and we have a better (although "heavier") solution to that.
子范围类型在实践中实际上并不是非常有用。我们不经常分配固定长度数组,也没有理由使用固定大小的整数。通常我们看到固定大小的数组,它们作为枚举,我们有一个更好的(虽然“更重”)解决方案。
Subrange types also complicate the type system. It would be much more useful to bring in constraints between variables than to fixed constants.
子范围类型也使类型系统复杂化。在变量之间引入约束比固定常数更有用。
(Obligatory mention that integers should be arbitrary size in any sensible language.)
(强制性地提到整数应该是任意合理语言的任意大小。)
#2
Java has had an assert keyword since version 1.4. If you're doing programming by contract, you're free to use those to check proper assignment. And any mutable attribute inside an object that should fall within a certain range should be checked prior to being set. You can also throw an IllegalArgumentException.
Java从版本1.4开始就有一个断言关键字。如果您按合同进行编程,则可以*地使用这些来检查正确的分配。并且应该在设置之前检查对象内应该落在某个范围内的任何可变属性。您还可以抛出IllegalArgumentException。
Why no range type? My guess is that the original designers didn't see one in C++ and didn't consider it as important as the other features they were trying to get right.
为什么没有范围类型?我的猜测是,原始设计师没有在C ++中看到它,并且认为它不像其他功能那样重要。
#3
Ranges are most useful when you can do something over that range, concisely. That means closures. For Java and C++ at least, a range type would be annoying compared to an iterator because you'd need to define an inner class to define what you're going to do over that range.
简洁地说,当你可以在这个范围内做某些事情时,范围是最有用的。这意味着关闭。至少对于Java和C ++,与迭代器相比,范围类型会很烦人,因为您需要定义一个内部类来定义您将在该范围内执行的操作。
#4
Pascal (and also Delphi) uses a subrange type but it is limited to ordinal types (integer, char and even boolean).
Pascal(以及Delphi)使用子范围类型,但它仅限于序数类型(整数,字符和偶数布尔值)。
It is primarilly an integer with extra type checking. You can fake that in an other language using a class. This gives the advantage that you can apply more complex ranges.
它是一个带有额外类型检查的整数。您可以使用类来伪造其他语言。这样可以使您可以应用更复杂的范围。
#5
For C++, a lib for constrained values variables is currently being implemented and will be proposed in the boost libraries : http://student.agh.edu.pl/~kawulak/constrained_value/index.html
对于C ++,目前正在实现受约束值变量的lib,并将在boost库中提出:http://student.agh.edu.pl/~kawulak/constrained_value/index.html
#6
In C# you can do this:
在C#中你可以这样做:
foreach(int i in System.Linq.Enumerable.Range(0, 10))
{
// Do something
}
#7
C++ allows you to implement such types through templates, and I think there are a few libraries available doing this already. However, I think in most cases, the benefit is too small to justify the added complexity and compilation speed penalty.
C ++允许您通过模板实现这些类型,我认为已经有一些库可用。但是,我认为在大多数情况下,其好处太小,不足以证明增加的复杂性和编译速度的损失。
As for static assert, it already exists. Boost has a BOOST_STATIC_ASSERT
, and on Windows, I think Microsoft's ATL library defines a similar one.
至于静态断言,它已经存在。 Boost有一个BOOST_STATIC_ASSERT,在Windows上,我认为微软的ATL库定义了一个类似的。
boost::type_traits
and boost::mpl are probably your best friends in implementing something like this.
boost :: type_traits和boost :: mpl可能是你实现这样的东西的最好朋友。
#8
The flexibility to roll your own is better than having it built into the language. What if you want saturating arithmetic for example, instead of throwing an exception for out of range values? I.e.
滚动自己的灵活性比将其内置到语言中更好。例如,如果您想要饱和算术,而不是为超出范围的值抛出异常,该怎么办?即
MyRange<0,100> volume = 99;
volume += 10; // results in volume==100
#9
I would add to Tom Hawtin response (to which I agree) that, for C++, the existence of ranges would not imply they would be checked - if you want to be consistent to the general language behavior - as array accesses, for instance, are also not range-checked anyway. For C# and Java, I believe the decision was based on performance - to check ranges would impose a burden and complicate the compiler.
我想补充Tom Hawtin的回应(我同意),对于C ++,范围的存在并不意味着它们会被检查 - 如果你想要与一般的语言行为保持一致 - 例如,数组访问是无论如何也没有范围检查。对于C#和Java,我认为决定是基于性能 - 检查范围会增加负担并使编译器复杂化。
Notice that ranges are mainly useful during the debugging phase - a range violation should never occur in production code (theoretically). So range checks are better to be implemented not inside the language itself, but in pre- and post- conditions, which can (should) be stripped out when producing the release build.
请注意,范围在调试阶段主要是有用的 - 在生产代码中(理论上)不应发生范围违规。因此,范围检查最好不是在语言本身内部实现,而是在前后条件下实现,在生成发布版本时可以(应该)将其删除。
#10
This is an old question, but just wanted to update it. Java doesn't have ranges per-se, but if you really want the function you can use Commons Lang which has a number of range classes including IntRange:
这是一个老问题,但只是想更新它。 Java本身没有范围,但是如果你真的想要这个函数,可以使用Commons Lang,它有很多范围类,包括IntRange:
IntRange ir = new IntRange(1, 10);
Bizarrely, this doesn't exist in Commons Math. I kind of agree with the accepted answer in part, but I don't believe ranges are useless, particularly in test cases.
奇怪的是,这在Commons Math中并不存在。我部分同意接受的答案,但我不认为范围是无用的,特别是在测试用例中。
#11
JSR-305 provides some support for ranges but I don't know when if ever this will be part of Java.
JSR-305为范围提供了一些支持,但我不知道它何时会成为Java的一部分。