【问题标题】:Ada: declarative part, function and packagesAda:声明性部分、函数和包
【发布时间】:2010-09-23 11:43:30
【问题描述】:

我有一个关于声明性部分、函数和包的查询。我有一个如下所示的包裹。由于 Compute_X1 函数的复杂性,我创建了一个“独立的”来计算这个函数。 Compute_X1 返回的值是 X1,将在函数 J21 中使用(J21 将 X1 作为第一个参数)。

包装规格:

package Compute_Jacobian is

--compute X1
function Compute_X1 ( Force_Applied, Forcing_Frequency: Long_Float) return Long_Float;

--- use X1 in J21
function J21 ( X1, Forcing_Frequency, Natural_Frequency : Long_Float) return Long_Float;

end Compute_Jacobian;

包体是:

package body Compute_Jacobian is
 --compute X1

function Compute_X1 ( Force_Applied, Forcing_Frequency: Long_Float) return Long_Float is separate;

X1 := Compute_X1 ( Force_Applied, Forcing_Frequency);


function J21 ( X1, Forcing_Frequency, Natural_Frequency : Long_Float) return Long_Float is separate;

end Compute_Jacobian;

我已经为 Compute_X1 和 J21 创建了存根。

在编译包体 Compute_Jacobian.adb 时,我收到以下错误消息:

12.    X1 := Compute_X1 ( Force_Applied, Forcing_Frequency);
       |
    >>> statement not allowed in declarative part

我的问题是如何计算 X1 并将其用于函数 J21 的计算。

我可以尝试直接在“主”代码(此处未显示)中计算 X1(从那里创建“独立”),然后将其用作计算 J21 的正常参数。但是我想要上面的结构(在我上面的帖子中),并在 Compute_Jacobian 包中计算 X1。

非常感谢...

【问题讨论】:

    标签: function package ada declarative


    【解决方案1】:

    好吧,编译器会告诉你到底是什么问题:-)

    您正试图在只允许声明的代码区域中执行一个赋值语句。

    至少我没有看到您对 X1 的声明(尽管这可能是因为您没有在上面的代码中摘录它),也没有看到分配给 Force_Applied 和 Forcing_Frequency 的声明和值。

    这可以修复,使其编译接近原样:

    X1 : Long_Float := Compute_X1 ( Force_Applied, Forcing_Frequency);
    

    或者,通过在包体中添加一个初始化块:

    package body Computer_Jacobian is
        ...
        X1 : Long_Float;
        ...
    begin
       X1 := Compute_X1 ( Force_Applied, Forcing_Frequency);
    end Compute_Jacobian;
    

    但老实说,我真的不认为这两者都是你真正想要的。

    在您的主程序中,您可以只声明 X1(以及作为参数传递的变量),然后调用您的 Compute 函数,例如(警告,未编译)

    with Compute_Jacobian;
    procedure Do_Computations is
    
      Force_Applied     : Long_Float := 1.0;
      Forcing_Frequency : Long_Float := 10.0;
      Natural_Frequency : Long_Float := 5.0;
    
      X1  : Long_Float;
      J21 : Long_Float;
    
    begin
       X1  := Compute_Jacobian.Compute_X1 (Force_Applied, Forcing_Frequency);
       J21 := Compute_Jacobian.Compute_J21 (X1, Forcing_Frequency, Natural_Frequency);
    end Do_Computations;
    

    这是获得您可能正在寻找的东西的一种方法。

    或者,如果 X1 仅在 Compute_J21 中使用,您应该只调用 Compute_X1 作为在该函数中执行的第一个语句之一(或作为 X1 声明的初始化)(并将 Force_Applied 而不是 X1 作为参数传递给Compute_J21):

    function Compute_J21 (Force_Applied, 
                          Forcing_Frequency,
                          Natural_Frequency : Long_Float)
                                       return Long_Float is
    
       -- Declarations...
       X1 : Long_Float := Compute_X1(Force_Applied, Forcing_Frequency);
    
    begin
       -- Computations that utilize X1...
    
    end Compute_J21;
    

    还有一个关于使用“分离”的注意事项......我理解将这些功能实现分开的冲动,因为它们很复杂,但我仍然建议不要这样做。它只是添加了另一个文件来跟踪,如果你使用 GNAT,你不会通过尝试单独编译它们来获得任何性能提升,因为整个包体最终都会得到处理,现在使用“is separate”在主流 Ada 编程中相当罕见。这个answer 在您之前提出的问题中涵盖了其中的一些内容。

    【讨论】:

    • 非常感谢。事实上,您的第一个解决方案让我意识到我根本没有在代码中声明 X1。您为我提供了几种选择,这将帮助我考虑一下最适合在这里使用的选择。我一直专注于编写包含非常长的数学表达式的存根(可以在横向模式下在 A3 纸上可视化)。
    • 是的,有人指出,“分开”是不行的,你是告诉这一点的人之一。在我的理解水平上,我不知道我是否可以取消“分离”。我在上面提供了一个最小的示例,但我有几个函数(如 J21、J22 等)要计算。由于这些是长表达式,我正在为它们中的每一个写一个“是分开的”。我想不出将它们放在一个整体中并不得不在屏幕上上下滚动。在我测试了一个单独的“独立”单元后,我忘记了它,因为我知道它工作正常。通过将所有代码都包含在 1 个代码中,我害怕输入意外的拼写错误。
    • 我试用了“了解”软件,了解文件之间的相互关系非常有用。我没有看到 GPS 具有这样的图形功能。我是唯一一个维护我的代码的人,所以我正在尽我所能让它变得简单。但我当然想学习正确的方法并尽量减少“分离”的使用。我看到,自从我学习了 Ada 及其单独的编译单元后,我更倾向于保持我的主要代码非常紧凑,并且不会因为过多的数字数学表达式而变得杂乱无章。如果数学很长,很大一部分数学最终会以“独立”的单位结束。
    • 就使用“分离”而言,如果它适合您,那么它适合您。没有错,只是现在很少使用。我支持您对“理解”的使用,我已经使用该工具很多年了,事实证明它对于我必须处理非常大的遗留代码库的项目来说绝对是必不可少的。
    • 谢谢。如果我不认识 Ada,我会设法将长数学表达式放在 C 或 Matlab 中的子程序中。一段时间后,这会让我感到困惑。为 1 个单一函数(例如我的代码中的 J21)编写表达式几乎需要 1 A3 页的 Ada 代码。如果我将两个或更多类似 J21 的函数放在同一个文件中,那么一段时间后我将很难处理文件内容。所以是的,也许就我而言,我应该感谢“是独立的”单位:)。
    猜你喜欢
    • 2011-03-11
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多