问题描述
range(2,12,3) 应该返回列表 [2,5,8,11]
range(10,2,~1) 应该返回列表 [10,9,7,6,4,3]
对于 range(2,3) 这有效:
fun range(start,stop,step) =
if start > stop then nil
else start::range(start+step,step);
对于 range(10,~1) 这有效:
fun range(start,step) =
if start <= stop then nil
else start::range(start+step,step);
但是,我需要一个函数来处理这两种情况。我尝试使用 orelse 和 else if 如下,但该函数返回一个空列表。
奥雷尔:
fun range(start,step) =
if start > stop orelse start <= stop then nil
else start::range(start+step,step);
否则如果:
fun range(start,step) =
if start > stop then nil
else if start <= stop then nil
else start::range(start+step,step);
两种方法都返回
val it = [] : int list
我认为这与在基本情况下使用 nil 有关,但我不知道为什么。
谢谢
解决方法
不要将 stop
与 start
进行比较,而是考虑 stop - start
的符号和 step
的符号。
如果你想一想,你会发现只要你在这个范围内,符号都是一样的。
fun sgn x = if x < 0
then ~1
else if x > 0
then 1
else 0;
fun range (start,stop,step) = if sgn(stop-start) = sgn(step)
then start :: range (start + step,step)
else []
,
问题:
在您的两个解决方案中,条件将始终为 true
,因为您正在检查 start
是否小于、大于或等于 stop
,这是对任何一对数字都为真。
解决方案:
您必须根据step
的符号检查当前情况。
如果 step
为零,则不要检查其他任何内容,因为无法创建步骤 0 的范围。抛出异常将是一个不错的选择。
如果 step
为正,请检查 start
是否低于 stop
。如果没有,请停止。
如果 step
为负数,请检查 start
是否高于 stop
。如果没有,请停止。
完整代码:
fun range(start,step) =
if start = stop orelse
(start < stop andalso step < 0) orelse
(start > stop andalso step > 0) then nil
else start::range(start+step,step);