我有一个名为month_range
的函数,每年需要两天作为输入(例如,65和128,假设年份为365天)并返回一个列表,其中包含该日期的月份数第1天到第2天属于。
列表的大小必须为" day2 - day1 + 1"。
示例:month_range(25,35)应返回:[1,1,1,1,1,1,1,2,2,2,2]
我写了以下代码
fun month_range (day1:int,day2:int) =
let
val month_days= [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
fun what_month(day :int) =
let
fun aux(sum :int, numbers: int list) =
let
val numbers_tail = tl numbers
in
if sum <= (hd numbers)
then 1
else
1 + aux(sum, (hd numbers + hd numbers_tail)
:: (tl numbers_tail))
end
in
aux(day, month_days)
end
in
if (day1>day2)
then []
else what_month(day1) @ what_month(day1 + 1)@::what_month(day2)
end
但它给了我以下错误
/tmp/emacs-region5156f3r:21.51-21.54 Error: unbound variable or constructor: @::
/tmp/emacs-region5156f3r:21.12-21.70 Error: operator is not a function [literal]
operator: int
in expression:
(what_month (day1 + 1)) <errorvar>
/tmp/emacs-region5156f3r:21.12-21.70 Error: operator and operand don't agree [literal]
operator domain: 'Z list * 'Z list
operand: int * _
in expression:
what_month day1 @ (((what_month <exp>) <errorvar>) what_month) day2
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:296.17-296.20
答案 0 :(得分:2)
首先,您可以从错误消息中看到您正在使用@::
,这实际上没有任何意义。
您很可能已将函数what_month
用于另一个赋值,因此没有理由将其放在let-expression中。
现在,如果我们简化你的代码
val month_days= [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
fun what_month(day :int) =
let
fun aux(sum :int, numbers: int list) =
let
val numbers_tail = tl numbers
in
if sum <= (hd numbers)
then 1
else
1 + aux(sum, (hd numbers + hd numbers_tail)::(tl numbers_tail))
end
in
aux(day, month_days)
end
fun month_range (day1:int,day2:int) =
if (day1>day2)
then []
else what_month(day1)
然后我们会看到它仍然没有输入。这是因为what_month
函数的类型是int -> int
,但是month_range
体内的if-expression返回then分支中的列表,那么你还必须返回一个列表其他分支。我们将解决这个问题。
目前,该函数仅返回day1所属月份的编号(理论上,因为尚未键入)。我们不想返回所有日子的日期1 ... day2
这就是递归的地方。如果我们返回what_month(day1)
与month_range( day1 + 1, day2)
的递归调用连接起来,那么我们最终会建立一个列表
what_month(day1) :: what_month(day1 + 1) :: what_month(day1 + 1 + 1) ...
并且由于您返回空列表,当您达到条件day1 > day2
时,递归将为您提供这样的结果
what_month(day1) :: what_month(day1 + 1) :: what_month(day1 + 1 + 1) :: ...
:: what_month(day2) ::[]
结果代码如下所示
fun month_range (day1:int,day2:int) =
if (day1>day2)
then []
else what_month(day1) :: month_range(day1 + 1, day2)
- month_range(25,35);
val it = [1,1,1,1,1,1,1,2,2,2,2] : int list