【问题标题】:Non-contiguous ranges for subtypes in Ada?Ada 中子类型的非连续范围?
【发布时间】:2012-08-26 17:48:19
【问题描述】:

作为一个 Ada 类型系统的学习练习,我试图制作 3 种类型(或者更确切地说,一种类型和 2 个子类型):

  • Month_Type,所有月份的枚举
  • Short_Month_TypeMonth_Type 子类型,只有 30 天的月份
  • February_Month_Type,只有二月的子类型

似乎子类型必须使用range 机制,对吗? (还有其他类型的子类型吗?)为了让它在连续范围内工作,我必须按以下顺序排列 Month_Type 枚举:

   type Month_Type is (February, April, June, September, November, January, March, May, July, August, October, December);

显然这不是几个月的自然顺序,我可以看到人们/我试图做Month_Type'First 或期待一月份的事情。

所以,这个愚蠢的例子有两个一般性问题:

  1. 我可以有一个子类型来指定其基本类型的特定组件而不是范围吗?
  2. 我能否以某种方式隐藏我放置月份的顺序的实施细节(例如,让“First”不可见)?

谢谢!

【问题讨论】:

    标签: types visibility ada


    【解决方案1】:

    您可以使用subtype predicates。在你的情况下:

    subtype Short_Month_Type is Month_Type with
      Static_Predicate => Short_Month_Type in April | June | September | November
    

    【讨论】:

    • 在 Ada 2012 中添加了 子类型谓词 可能会很有用,因此在提出原始问题时(几个月后)不可用
    【解决方案2】:

    不,enumerationsubtype 在这种情况下只承认range_constraint,但您可以使用Ada.Containers.Ordered_Sets 创建任意数量的Sets。有herehere的例子。

    【讨论】:

    • 这是可用的,但除了复杂情况外不需要它。
    • 所以,这就是我刚刚处理其他语言的方式。我感兴趣的是能够使用类型系统本身来指定诸如短月份或奇数之类的东西。但感谢您让我知道此功能并非总是可行的!
    【解决方案3】:

    您可以创建一个对象,它只指定枚举中的某些值。我们通常称其为“集合”。

    许多语言都将集合作为基本类型(以及数组和记录)。当然有些没有。艾达在中间。它官方没有名为“set”的类型或任何东西,而是boolean operations are defined to work like bitwise logical operationsboolean 的数组上。如果你打包这个数组,你得到的几乎就是其他语言的“set”类型给你的。所以Ada 确实支持集合,它们只是被称为“布尔数组”。

    type Month_Set is array (Month) of Boolean;
    Short_Month : constant Month_Set := 
        (September => true, April => true, June => true, November => true, 
         February => true, others => false);
    Y_Month : constant Month_Set :=
        (January => true, February => true, May => True, July => true, 
         others => false);
    
    -- Inclusion
    if (Short_Month(X)) then ...
    
    -- Intersection (Short_Y will include only February)
    Short_Y := Short_Month and Month_Ending_in_Y;
    
    -- Union (Short_Y will include All Short_Months and all Y_Months
    Short_Y := Short_Month or Month_Ending_in_Y;
    
    -- Negation (Short_Y will include all Short_Months not ending in Y
    Shorty_Y := Short_Month and not Month_Ending_in_Y;
    

    【讨论】:

    • +1 是一个很好的选择;另见4.5.1 Logical Operators and Short-circuit Control Forms
    • 这是一个很好的答案,但我对 Ada 并不了解。正如我在另一条评论中解释的那样,我对类型系统本身能够从 Y_Month 识别 Short_Month 感兴趣,希望在编译时。但显然不是所有的愿望都是可能的 :) 再次感谢。
    【解决方案4】:

    垃圾神回答了第一个问题。 要回答第二个问题,请将类型本身设为私有。

    【讨论】:

    • 是的,这样就可以公开尽可能多或尽可能少的抽象数据类型,只要对应用程序有意义。
    • 我想我的措辞很糟糕,但如果我将整个枚举设为私有,那么包的任何消费者都无法真正使用它,对吧?我想我必须提供公共 Make_Month 函数,如果我希望他们能够在二月左右摇摆,但不允许做 Month_Type'First?
    • 是的;将实现隐藏在抽象数据类型中的另一个优点是您可以根据需要对其进行更改,而客户端则不会更明智。例如,Java 的 EnumSet 在内部使用压缩布尔数组来提高效率,如 T.E.D.建议。
    猜你喜欢
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-05
    相关资源
    最近更新 更多