Eiffel:将参数传递给代理作为参数接收

时间:2019-03-28 20:32:51

标签: eiffel

我真的陷入了如何将参数传递给Eiffel代理程序调用的第二级的问题。希望我的例子足以说明自己:

main_call
    do
        b (agent d(?, ?))
    end

b (a_proc: PROCEDURE[STRING])
    local
        l_something_else: INTEGER
    do
        l_something_else := 1
--        z("a_line", a_proc(l_something_else)) -- How can I pass at this stade l_something_else to the d procedure!!!
    end

d (line: STRING; something_else: INTEGER)
    do
--        do_some_stuff_with_line (line, something_else)
        do_nothing
    end

z (a_line: STRING; a_proc: PROCEDURE[STRING])
    do
        a_proc.call([a_line])
    end

我希望能够做类似的事情

z("a_line", a_proc(?, something_else))

但是不可能,因为我尝试使用agent关键字时,无法识别a_proc参数!

那么语法是什么?我什至尝试使用a_proc.set_operands向a_proc添加一个参数,但由于OPEN_ARGS类而迷路了

实施案例

如果您需要一个目标...想象一下我想使用d函数的2种不同实现,而在我的情况下,我想使用2种UT_CSV_HANDLER函数CVS的每一行都有不同的功能

以下代码给出了Non-compatible actual argument in feature call

Feature: import_from_csv_impl
Called feature: import_from_csv_impl (a_rest_request: REST_REQUEST; a_procedure: PROCEDURE [DS_ARRAYED_LIST [STRING_8], INTEGER_64, STRING_8]): [detachable like items] detachable SIT_LINKED_LIST [MEASURING_POINT] from MEASURING_POI...
Argument name: ia_name
Argument position: 2
Formal argument type: STRING_8
Actual argument type: INTEGER_64
Line: 258
                ia_procedure.call (ia_measuring_point_id, ia_name)
->            end (?, l_measuring_point_id, l_s)
            l_csv_handler.read_file (l_is, l_partially_closed)

完整的示例:

-- Main call
import_from_abb_csv (a_rest_request: REST_REQUEST): detachable like items 
    do
        Result := import_from_csv_impl (a_rest_request, agent impl_for_each_csv_line_import_from_abb_csv)
    end

-- Second call
import_from_csv_impl (a_rest_request: REST_REQUEST; a_procedure: PROCEDURE[DS_ARRAYED_LIST [STRING_8], INTEGER_64, STRING]): detachable like items
    local
        l_csv_handler: UT_CSV_HANDLER
        l_is: KL_STRING_INPUT_STREAM
        l_measuring_point_id: INTEGER_64
        l_s: STRING
        l_partially_closed: PROCEDURE[DS_ARRAYED_LIST[STRING]]
    do
        l_s := "whatever"
        l_measuring_point_id := 12
        create l_csv_handler.make_with_separator (',')

        l_partially_closed := agent (i_al: DS_ARRAYED_LIST[STRING]; ia_measuring_point_id: INTEGER_64; ia_name: STRING; ia_procedure: PROCEDURE[INTEGER_64, STRING])
            do
                ia_procedure.call (ia_measuring_point_id, ia_name)
            end (?, l_measuring_point_id, l_s)

        l_csv_handler.read_file (l_is, l_partially_closed)

    end

-- end call
impl_for_each_csv_line_import_from_abb_csv (a_csv_line: DS_ARRAYED_LIST [STRING_8]; a_measuring_point_id: INTEGER_64; l_cu_name: STRING)
    do
        -- do_my_business
    end


-- for information signature of read_file is:
--     read_file (a_file: KI_TEXT_INPUT_STREAM; a_action: PROCEDURE [DS_ARRAYED_LIST [STRING]])

1 个答案:

答案 0 :(得分:2)

agent dagent d (?,?)(它们都是等效的)产生PROCEDURE [STRING, INTEGER],而d的两个操作数仍然打开。由于元组协方差,PROCEDURE [STRING, INTEGER]符合PROCEDURE [STRING],因此编译了您的a实现,但是尝试仅用TUPLE [STRING]而不是{{1}来调用代理}作为操作数(TUPLE [STRING, INTEGER]会这样做)将导致运行时异常(可能是catcall)。

一种逐步关闭代理操作数的方法是将其包装在另一个操作数少的代理中:

b

或者,可以在内联代理中声明b (a_procedure: PROCEDURE [STRING, INTEGER]) local l_something_else: INTEGER l_partially_closed: PROCEDURE [STRING] do l_something_else := 1 l_partially_closed := agent (ia_operand_1: STRING; ia_operand_2: INTEGER; ia_procedure: PROCEDURE [STRING, INTEGER]) do ia_procedure.call (ia_operand_1, ia_operand_2) end (?, l_something_else, a_procedure) -- Notice how only one operand is left open z ("a_line", l_partially_closed) end

l_something_else

您也可以使用b (a_procedure: PROCEDURE [STRING, INTEGER]) local l_partially_closed: PROCEDURE [STRING] do l_partially_closed := agent (ia_operand_1: STRING; ia_procedure: PROCEDURE [STRING, INTEGER]) local il_something_else: INTEGER do il_something_else := 1 ia_procedure.call (ia_operand_1, il_something_else) end (?, a_procedure) z ("a_line", l_partially_closed) end {ROUTINE}.set_operands,但我认为它不那么灵活,更容易出错,而且不是线程安全的。

{ROUTINE}.apply

更新

鉴于您的实施案例,请查看以“ HERE”开头的注释:

b (a_procedure: PROCEDURE [STRING, INTEGER])
local
    l_something_else: INTEGER
    l_partially_closed: PROCEDURE [STRING]
do
    l_something_else := 1
    a_procedure.set_operands ("some string you will override later", l_something_else)
    z ("a_line", a_procedure)
end

z (a_line: STRING; a_proc: PROCEDURE [STRING]) -- or PROCEDURE [STRING, INTEGER]
do
    -- You have no guarantee that `a_proc' has any operands set (though you could make it a precondition)
    -- This is why it is less safe and less reusable than the previous approach
    check attached a_proc.operands as la_operands then
        la_operands [1] = a_line
    end
    a_proc.apply
end