Eiffel 中关于跨语法的 Ensure 子句
Ensure clause in Eiffel regarding across syntax
find(c: CHARACTER; position: INTEGER): INTEGER
此功能通过从位置 i 开始并搜索来查找字符。一旦找到索引,它就会输出它。但是,如果单词中不存在这样的字符,则输出 0
问题:
post条件必须断言查询 returns 字符 c 在范围 pos .. word.count 中的索引,如果没有这样的字符则为零。
我的代码:
find(c: CHARACTER; position: INTEGER): INTEGER
require
.....
do
.....
ensure
across word as w
some
(w.item = c and w.cursor_index >= position)
end
end
此布尔等式的问题在于,当使用 find(c,pos) 并且未找到任何内容时,该功能会引发 post 条件违规。
我试图让它仅在单词中不存在给定的 c 字符时才允许该功能输出
假设应该是一个完整的后置条件,让我们在case-by-case的基础上看问题:
问。允许的输出值范围是多少?
A. 结果可以是 0
或 word
中从 position
:
开始的任何有效位置
valid_result_range: Result = 0 or position <= Result and Result <= word.count
这里我们假设position
是non-negative(希望在前置条件中指定)。
问。如果没有匹配的字符,输出值是多少?
A. 输出是 0
。索引从 position
开始的所有字符都不匹配:
zero_if_not_found: (Result = 0) =
across word as wc all
position <= wc.target_index implies wc.item /= c
end
问。如果有匹配的字符,输出值是多少?
A.是从position
:
开始的对应字符的第一个位置
non_zero_if_found: (Result /= 0) implies
(
word [Result] = c
and
across word as wc all
(position <= wc.target_index and w.target_index < Result) implies
wc.item /= c
end
)
这个后置条件有两部分。一个检查是否找到了该字符。另一个检查在该位置之前没有匹配的字符。
编辑: 原始代码以 (Result /= 0) = ...
而不是 (Result /= 0) implies ...
开头。当 Result = 0
时,这将导致 word [Result]
中的断言冲突。 implies
if 的代码没有这个问题,因为如果 implies
之前的表达式是 False
那么它之后的表达式不会被计算。
最后的后置条件是上述所有断言的组合。断言的顺序很重要,因为 non_zero_if_found
依赖于 Result
是 word
.
的有效索引这一事实
我会略微更改亚历山大的回答:
zero_if_not_found: (Result = 0) 意味着...
non_zero_if_found: (Result /= 0) 表示 ...
要了解原因,请考虑当 Result = 0 时会发生什么,我们计算 Alexander 的 non_zero_if_found:
(Result /= 0) 计算结果为 False
然后 word [Result] = c 评估为先决条件失败(valid_index - 我假设 word 是 STRING 类型)。 (将 w [Result] 改为单词 [Result],我认为这是 Alexander 的错字)
使用 imply 可以保护您免受这种情况的影响,因为 RHS 不会被评估。
find(c: CHARACTER; position: INTEGER): INTEGER
此功能通过从位置 i 开始并搜索来查找字符。一旦找到索引,它就会输出它。但是,如果单词中不存在这样的字符,则输出 0
问题: post条件必须断言查询 returns 字符 c 在范围 pos .. word.count 中的索引,如果没有这样的字符则为零。
我的代码:
find(c: CHARACTER; position: INTEGER): INTEGER
require
.....
do
.....
ensure
across word as w
some
(w.item = c and w.cursor_index >= position)
end
end
此布尔等式的问题在于,当使用 find(c,pos) 并且未找到任何内容时,该功能会引发 post 条件违规。
我试图让它仅在单词中不存在给定的 c 字符时才允许该功能输出
假设应该是一个完整的后置条件,让我们在case-by-case的基础上看问题:
问。允许的输出值范围是多少?
开始的任何有效位置
A. 结果可以是0
或word
中从position
:valid_result_range: Result = 0 or position <= Result and Result <= word.count
这里我们假设
position
是non-negative(希望在前置条件中指定)。问。如果没有匹配的字符,输出值是多少?
A. 输出是0
。索引从position
开始的所有字符都不匹配:zero_if_not_found: (Result = 0) = across word as wc all position <= wc.target_index implies wc.item /= c end
问。如果有匹配的字符,输出值是多少?
开始的对应字符的第一个位置
A.是从position
:non_zero_if_found: (Result /= 0) implies ( word [Result] = c and across word as wc all (position <= wc.target_index and w.target_index < Result) implies wc.item /= c end )
这个后置条件有两部分。一个检查是否找到了该字符。另一个检查在该位置之前没有匹配的字符。
编辑: 原始代码以(Result /= 0) = ...
而不是(Result /= 0) implies ...
开头。当Result = 0
时,这将导致word [Result]
中的断言冲突。implies
if 的代码没有这个问题,因为如果implies
之前的表达式是False
那么它之后的表达式不会被计算。
最后的后置条件是上述所有断言的组合。断言的顺序很重要,因为 non_zero_if_found
依赖于 Result
是 word
.
我会略微更改亚历山大的回答:
zero_if_not_found: (Result = 0) 意味着... non_zero_if_found: (Result /= 0) 表示 ...
要了解原因,请考虑当 Result = 0 时会发生什么,我们计算 Alexander 的 non_zero_if_found:
(Result /= 0) 计算结果为 False 然后 word [Result] = c 评估为先决条件失败(valid_index - 我假设 word 是 STRING 类型)。 (将 w [Result] 改为单词 [Result],我认为这是 Alexander 的错字)
使用 imply 可以保护您免受这种情况的影响,因为 RHS 不会被评估。