埃菲尔:将参数传递给作为参数接收的代理
Eiffel: passing argument to agent received as argument
我真的很困惑如何将参数传递给 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
class
实施案例
如果你需要一个目标......想象一下我想要 d
函数的 2 个不同的实现,在我的例子中它使用了我想要的 UT_CSV_HANDLER
CVS 的每一行都有 2 个不同的函数
下面的代码给出了一个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]])
agent d
或 agent d (?,?)
(它们是等价的)产生一个 PROCEDURE [STRING, INTEGER]
,d
的两个操作数仍然打开。由于元组协方差,PROCEDURE [STRING, INTEGER]
符合 PROCEDURE [STRING]
,因此您的 a
实现可以编译,但尝试仅使用 TUPLE [STRING]
而不是 [=22= 来调用代理] 作为操作数(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
,但在我看来,它不太灵活且更容易出错,而且线程不安全。
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
更新
鉴于您的实施案例,请参阅以 'HERE':
开头的评论
-- 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[DS_ARRAYED_LIST [STRING_8], INTEGER_64, STRING]) -- HERE, change the declared type of `ia_procedure' to match `a_procedure'
do
ia_procedure.call (i_al, ia_measuring_point_id, ia_name) -- HERE, add `i_al' to `call'
end (?, l_measuring_point_id, l_s, a_procedure) -- HERE, add `a_procedure'
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]])
我真的很困惑如何将参数传递给 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
class
实施案例
如果你需要一个目标......想象一下我想要 d
函数的 2 个不同的实现,在我的例子中它使用了我想要的 UT_CSV_HANDLER
CVS 的每一行都有 2 个不同的函数
下面的代码给出了一个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]])
agent d
或 agent d (?,?)
(它们是等价的)产生一个 PROCEDURE [STRING, INTEGER]
,d
的两个操作数仍然打开。由于元组协方差,PROCEDURE [STRING, INTEGER]
符合 PROCEDURE [STRING]
,因此您的 a
实现可以编译,但尝试仅使用 TUPLE [STRING]
而不是 [=22= 来调用代理] 作为操作数(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
,但在我看来,它不太灵活且更容易出错,而且线程不安全。
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
更新
鉴于您的实施案例,请参阅以 'HERE':
开头的评论-- 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[DS_ARRAYED_LIST [STRING_8], INTEGER_64, STRING]) -- HERE, change the declared type of `ia_procedure' to match `a_procedure'
do
ia_procedure.call (i_al, ia_measuring_point_id, ia_name) -- HERE, add `i_al' to `call'
end (?, l_measuring_point_id, l_s, a_procedure) -- HERE, add `a_procedure'
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]])