【问题标题】:Are there any languages that allow units?有没有允许单位的语言?
【发布时间】:2010-11-21 16:08:20
【问题描述】:

今天在 C# 中编写以下内容时

DateTime.Now.AddYears(-60)

我想知道是否有任何语言允许使用更自然的单位语法:

DateTime.Now - 60years

有人知道吗?具体来说,我对将“60 年”变成例如单元操作员(?)的存在感兴趣。 “时间跨度。从年(60)”。能够定义自己的单位运算符也很好,类似于在 C# 中编写转换运算符

(是的,我知道 TimeSpan 多年来都无法满足 - 这是一个例子。)

【问题讨论】:

  • 对 NASA 非常有用,因此他们可以安全地添加米和英尺。
  • 或者安全地捕捉到米和英尺不会天生混合。
  • C++11 支持用户定义的文字,用于实现单位。

标签: programming-languages syntax


【解决方案1】:

【讨论】:

  • 如果我没看错,a) 太棒了... b) F# 必须实现自己的float 类型,然后与System.Float 分开?如果是这样,我们可以从其他 .NET 语言中使用这个系统吗?
  • a) F# 使用标准的 .Net Float 和 Double,但添加了它自己的类型推断和检查。 b) F# 和其他 .Net 语言之间有很好的互操作性
  • F# 太棒了我想知道后台发生了什么,因为我在代码中看到的只是字符串文字,它们以某种方式扮演某种运算符的角色。
【解决方案2】:

您可能对 F# Units of Measure 支持感兴趣

【讨论】:

    【解决方案3】:

    Ruby 的 ActiveSupport 库使用 hours 和 days 等方法扩展了 Integer 类,它允许您编写如下内容:

    Time.now + 5.days
    

    但这并不是真正的语法特性——它只是一个方法调用,并且可以在任何允许您向现有类中添加方法的语言中使用。您可以使用扩展方法在 C# 中执行此操作 - 尽管那里必须是 5.days()

    【讨论】:

    • 或扩展属性 -> 5.days 。总之,它会打破我所知道的几乎所有“好的编程建议”。
    • 是的,扩展方法是 .NET 中的一种方法,将 5.Days() 转换为 TimeSpan.FromDays(5)。
    【解决方案4】:

    有一个用于 Units 的 Boost C++ 库,它广泛使用模板元编程来提供与您想要的语法相似的东西。

    quantity<force>     F(2.0*newton);
    quantity<length>    dx(2.0*meter);
    quantity<energy>    E(work(F,dx));
    

    http://www.boost.org/doc/libs/1_37_0/doc/html/boost_units.html

    【讨论】:

    • 对于 C++0x 我们可以说auto Table = 2.0*meter * 3.0*meter;
    【解决方案5】:

    Sun 的新语言 Fortress 支持单位,如果没记错的话,它足够聪明,可以阻止您做奇怪的事情,例如从长度度量中减去时间度量。

    而且 Mathematica 有度量单位和处理它们的不太笨拙的语法。

    【讨论】:

    【解决方案6】:

    Unum 对 Python 所做的几乎完全一样,允许以下代码:

    >>> TON + 500*KG
    
    1.5 [t] 
    
    >>> 5E-8*M - 28*ANGSTROM
    
    472.0 [angstrom]
    
    >>> 3*H + 20*MIN + 15*S
    
    3.3375 [h]
    
    >>> H == 60*MIN
    
    True
    
    >>> 10000*S > 3*H + 15*MIN
    
    False
    
    >>>
    

    【讨论】:

      【解决方案7】:

      请参阅C# Extensions 上的答案,其中将 int 类扩展为支持 Hours()、Days() 等方法。

      Powershell 有 kB, MB, and GB operators 用于处理文件大小等。

      MSSQL 中的DATE_ADD() function 接受日期算术的单位,例如日、小时等。

      【讨论】:

        【解决方案8】:

        Java 的 JODA 库就是这样工作的。

        还有JSR-275 提出了一个单元框架。

        我早在 1997 年从 Martin Fowler 那里第一次听说这个问题。他在他的"Analysis Patterns" 中写道。

        【讨论】:

        • OP不是指语言对单位符号的支持,而不是API对单位概念的支持吗?
        • 当然,但我不知道有哪一个。甚至 FORTRAN,科学计算语言中的佼佼者,在我上次使用时也不支持单位。
        【解决方案9】:

        本质上不是单位...而是一种使用扩展方法为您提供类似单位的功能的方法。此示例专门针对 TimeSpan。

        static class TimeExtensions
        {
            public static TimeSpan ToDays(this int i)
            {
                return new TimeSpan(i, 0, 0, 0, 0);
            }
        
            public static TimeSpan ToHours(this int i)
            {
                return new TimeSpan(0, i, 0, 0, 0);
            }
        
            public static TimeSpan ToMinutes(this int i)
            {
                return new TimeSpan(0, 0, i, 0, 0);
            }
        
            public static TimeSpan ToSeconds(this int i)
            {
                return new TimeSpan(0, 0, 0, i, 0);
            }
        
            public static TimeSpan ToMilliseconds(this int i)
            {
                return new TimeSpan(0, 0, 0, 0, i);
            }
        }
        

        然后,只需 4.ToMinutes() 即可为您提供 4 分钟的 TimeSpan。如果您有类似的基类可用于表示其他单元类型,则可以添加相同类型的扩展功能。

        (注意:这只是 Ruby 示例的 C# 表示。)

        【讨论】:

          【解决方案10】:

          当您使用单位时,您实际上是在分配一个类型。转换可以通过强制转换来实现,或者通过基于参数类型区分函数调用(函数重载)来实现。几乎任何静态类型语言(允许您彻底定义类型)都可以让您做类似的事情。这将使您的程序更加健壮,尽管那些喜欢动态类型语言的人可能会争辩说,相对于为大多数应用程序实现如此彻底的类型系统所花费的时间而言,收益是很小的。另一方面,构建Mars Climate Orbiter 将值得这样的类型系统。

          语法有点不同,但你的例子让我觉得与一些如何使用 Haskell 的类型系统(或任何类型的函数式语言)的常见例子非常相似,不过,正如我所提到的,这在类 C 中也是可行的语言也是如此。

          【讨论】:

            【解决方案11】:

            Ada 及其近亲 VHDL 直接支持单位的概念。由于这些语言是非常强类型的,因此单位是类型严格性的一种自然能力。

            【讨论】:

              【解决方案12】:

              我猜是 C++,你可以用重载的运算符和一些#define 宏来创建单元类

              【讨论】:

              【解决方案13】:

              我不知道是否存在,但我希望在接下来的几年中会开始看到像DSLs 这样的东西。我在想有点像下一代MATLAB 之类的。我确信这些东西有大量的数学、科学和工程用途。

              【讨论】:

                【解决方案14】:

                MySQL 有this feature

                
                mysql> SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND;
                        -> '2009-01-01 00:00:00'
                mysql> SELECT INTERVAL 1 DAY + '2008-12-31';
                        -> '2009-01-01'
                mysql> SELECT '2005-01-01' - INTERVAL 1 SECOND;
                        -> '2004-12-31 23:59:59'
                

                【讨论】:

                  【解决方案15】:

                  SQL,或者至少 MySQL 有一些基本的基于时间的单元支持。

                  mysql> SELECT DATE_SUB(NOW(), INTERVAL 1 DAY) AS `yesterday`, NOW() + INTERVAL 1 DAY AS `tomorrow`;
                  +---------------------+---------------------+
                  | yesterday           | tomorrow            |
                  +---------------------+---------------------+
                  | 2009-08-20 06:55:05 | 2009-08-22 06:55:05 |
                  +---------------------+---------------------+
                  1 row in set (0.00 sec)
                  

                  【讨论】:

                  • 比那个还要好:)
                  【解决方案16】:

                  我知道你的意思,我也一直对此感到好奇。 (我的高中化学老师坚持认为没有单位的数字毫无意义。无论如何......)

                  使用任何强类型语言,您都可以为这些概念编写类。我用 C++、Java 和 Pascal 编写了它们。谷歌“Units”和“Java”,你可以找到一个像这样封装了各种物理测量的库。

                  C++,它的类型转换和运算符重载可以让这看起来更自然。实际上,您可以使事情变得非常光滑,得到我认为您想要的东西。尽管 Java 会这样做,但它需要更明确的转换和笨拙的语法。

                  但不,我没见过。

                  寻找为科学家创建的特定领域语言,甚至是“教育”语言。

                  【讨论】:

                    【解决方案17】:

                    Frink 是一种专门为这样的“物理计算”而构建的语言。来自文档:

                    Frink 是一个实用的计算工具 和编程语言旨在 使物理计算变得简单, 帮助确保答案出来 正确的 [..]。它跟踪测量单位 (英尺、米、公斤、瓦特等) 通过所有计算,让您 透明地混合计量单位 [..]

                    你在弗林克的例子:

                    now[] - 60 years
                    

                    【讨论】:

                      【解决方案18】:

                      我还没有见过这样一种天生就支持它的语言。但是,如果您愿意的话,您当然可以用多种语言编写您自己的基于日期的对象。

                      【讨论】:

                        【解决方案19】:

                        我确定这不是您要寻找的,但在测试和测量设备领域,“测试程序”包含对电压、电流或时间单位。

                        不过,非常专业的东西,大多数人几乎认不出它是编程语言。

                        【讨论】:

                          【解决方案20】:

                          PHP 的 strtotime() 函数做得非常好。它需要一个字符串和一个可选的时间作为参数,并将解析字符串以找出新的时间。

                          例子:

                           $newTime = strtotime('last monday');
                           $newTime = strtotime('- 2 days', $originalTime);
                           $newTime = strtotime('- 60 years', $originalTime);
                           $newTime = strtotime('+ 1 week 1 day', $originalTime);
                          

                          更多:http://us2.php.net/strtotime

                          【讨论】:

                          • 字符串解析算不上编程语言的语法特性!!
                          【解决方案21】:

                          不是语言的一部分,但我以前在 C 中看到过类似的东西:

                          #define NOW     time(0)
                          #define PLUS    +
                          #define AND     +
                          #define MINUS   -
                          #define SECOND  * 1
                          #define SECONDS * 1
                          #define MINUTE  * 60
                          #define MINUTES * 60
                          #define HOUR    * 3600
                          #define HOURS   * 3600
                          #define DAY     * 86400
                          #define DAYS    * 86400
                          
                          time_t waitUntil = NOW PLUS 1 HOUR AND 23 MINUTES;
                          

                          当时对我来说这似乎很可恶,与 "#define begin {""#define end }" 在同一班 - 如果您不喜欢该语言的工作方式,请使用不同的语言;不要试图以这种可怕的方式屈从于你的意志。

                          这似乎仍然令人憎恶,但我已经成熟了,至少可以理解为什么有人认为这是个好主意。

                          【讨论】:

                          • 谢谢,@Dave,我错了。
                          • 如果你扔掉了前 4 个#defines 并使用了正确的数学,那就不会是糟糕的 C。
                          【解决方案22】:

                          PowerShell 有一些基本的支持。例如5GB/1MB 计算结果为 5120

                          【讨论】:

                            【解决方案23】:

                            从句法上讲,我不太确定这样做的好处是什么

                            DateTime.Now + 60 years
                            

                            结束

                            DateTime.Now.AddYears (60)
                            

                            我处理“单位”的典型方法是定义将这些单位相乘时转换为数据对象基本单位的常量。由于有人(简要地)用 Ada 标记了此内容,因此 Ada 版本将是:

                            Years : constant := 60.0 * 60.0 * 24.0 * 365.0;
                            DateTime.Now := DateTime.Now + (60.0 * Years);
                            

                            我认为你可以在 C++ 中做几乎相同的想法,只是它们的时间对象可能是大整数而不是实数。

                            【讨论】:

                            • 我并不是出于对这种语法的需要,而是出于好奇。当然,对于我的示例,单元语法并没有真正提供太多。
                            【解决方案24】:

                            在 Perl 中,您可以使用 DateTime,它允许以下操作:

                            my $dt = DateTime->now
                            $dt->subtract( hours => 1 );
                            

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2021-08-05
                              • 2021-05-25
                              • 1970-01-01
                              • 2012-01-09
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2012-02-21
                              相关资源
                              最近更新 更多