我正在编写一个range函数,它应该返回指定范围内的整数列表。
range(2,12,3)应该返回列表[2,5,8,11]
范围(10 2 ~ 1)应该返回列表(10、9、8、7、6、5、4、3]
for range(2,12,3) this works:
fun range(start, stop, step) =
if start > stop then nil
else start::range(start+step, stop, step);
for range(10,2,~1):
fun range(start,stop,step) =
if start <= stop then nil
else start::range(start+step, stop, step);
但是,我需要一个函数来处理这两种情况。我已经尝试使用orelse和else if如下,但函数返回一个空列表。
orelse:
fun range(start, stop, step) =
if start > stop orelse start <= stop then nil
else start::range(start+step, stop, step);
else if:
fun range(start,stop,step) =
if start > stop then nil
else if start <= stop then nil
else start::range(start+step,stop,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, stop, step)
else []
问题:
在你的两个解中,条件总是true
,因为你要检查start
是否小于、大于或等于stop
,这在数学上对任何一对数字都是成立的。
解决方案:
您必须根据step
的标志检查当前情况。
如果step
为零,则不检查任何其他内容,因为创建步骤0的范围是不可能的。抛出异常是个不错的选择。
如果step
为正,检查start
是否小于stop
。如果没有,请停止。
如果step
为负,检查start
是否高于stop
。如果没有,请停止。
完整代码:
fun range(start,stop,step) =
if start = stop orelse
(start < stop andalso step < 0) orelse
(start > stop andalso step > 0) then nil
else start::range(start+step, stop, step);