SML-不使用List.nth从列表中获取特定元素

SML-不使用List.nth从列表中获取特定元素,sml,Sml,我正试图学习SML atm的基础知识,却偶然发现了一个我找不到答案的任务 它将编写一个函数,该函数接受一个int和一个list,返回给定int的索引上列表中的一个特定元素。正如您所看到的,它与list.nth()函数完全相同 现在我很好奇。这就是我取得的成就,但我就是想不出一种方法来手动定位特定的索引 fun nth(nil, _) = 0 | nth(x::xs, 0) = x; | nth(x::xs, y) = val list = [1, 2, 3]; nth

我正试图学习SML atm的基础知识,却偶然发现了一个我找不到答案的任务

它将编写一个函数,该函数接受一个int和一个list,返回给定int的索引上列表中的一个特定元素。正如您所看到的,它与list.nth()函数完全相同

现在我很好奇。这就是我取得的成就,但我就是想不出一种方法来手动定位特定的索引

fun nth(nil, _)     = 0
  | nth(x::xs, 0)   = x;
  | nth(x::xs, y)   = 

val list = [1, 2, 3];
nth(list, 0);

正如John所建议的,为空列表编制索引可能会引发异常,而不是返回0。这使得
nth
适用于任何类型的列表,而不仅仅是
int list
s的子集,0可以合理地被视为“无结果”。该函数似乎缺少递归,无法处理0以外的任何索引。以下是要使用的模板:

fun nth ([], _) = raise Empty
  | nth (x::_, 0) = x
  | nth (_::xs, n) = ...
这里添加了一个异常,并且在函数的每种情况下都不会使用的变量已被伪变量
\uuu
清除。您可能还需要更详细的错误消息

fun nth ([], n) = raise Fail "Failed to find the appropriate index!"
  | nth (x::_, 0) = x
  | nth (_::xs, n) = ...
nth
的“更安全”版本具有类型
'A list*int->'A选项
,即对于
nth(xs,i)
,如果
xs
具有
i
th元素
x
,则返回
一些x
,如果没有,则返回
NONE

fun nth_safe ([], _) = NONE
  | nth_safe (x::_, 0) = SOME x
  | nth_safe (_::xs, n) = ...
它“更安全”,因为如果列表不够长,它不会抛出异常。一个对抗性的例子:
n([0,1,2],3)

但如果指数为负,它仍然无法处理。一个对抗性的例子:
n([0,1,2],~1)

您可以在第三个函数体的
..
中使用
如果n<0,那么…
,解决这个问题,但是在每个递归步骤中都会执行该问题,即使您很可能只需要检查一次

此函数的健壮版本在传递负索引时会引发错误。否则,函数可能会导致负循环,直到内存耗尽,因为递归情况(第3种情况)不会收敛到两种基本情况(情况1和2)。对于基于异常的版本,您可以编写:

exception IndexError of int
fun nth (xs, n) =
    let fun go ([], _) = raise IndexError n
          | go (x::_, 0) = x
          | go (_::ys, i) = ...
    in if n < 0 then raise IndexError n else go (xs, n)
    end
一个简单的方法:

fun nth (nil,0) = raise Fail "You are out of bounds with nth element"
  | nth ((x::xr),n) = if n=0 then x else nth (xr,(n-1))

你的第一个基本案例似乎有问题。不应该保留未定义或触发异常而不是返回数字0吗?至于剩下的部分,这里有一个提示:请注意,例如,
x::xs
的第7个元素与
xs
的第6个元素相同。谢谢你的回答,我在最后已经介绍了这个提示。我的问题是,尽管我知道元素的索引,但我真的不知道如何单独与它们交互。在这种简单的递归方法中,你不会显式地与索引交互(除了从索引中减去1)。您只需倒计时(通过递归调用),直到索引达到0,然后返回剩余列表的开头。非常感谢,我还不太习惯SML的功能。我搜索的简单解决方案是:n(xs,y-1)
datatype ('a, 'b) either = Left of 'a | Right of 'b
fun nth (xs, n) =
    let fun go ([], _) = Left n
          | go (x::_, 0) = Right x
          | go (_::ys, i) = ...
    in if n < 0 then Left n else go (xs, n)
    end

val example_1 = nth ([2,3,5], 5)  (* gives: Left 5  *)
val example_2 = nth ([2,3,5], ~1) (* gives: Left ~1 *)
val example_3 = nth ([2,3,5], 2)  (* gives: Right 5 *)
fun nth (nil,0) = raise Fail "You are out of bounds with nth element"
  | nth ((x::xr),n) = if n=0 then x else nth (xr,(n-1))