0

使用 ML 作为编程语言,我们有列表和元组,在列表的情况下,我们可以通过从原始列表中删除或附加元素来从另一个列表中形成一个列表,例如,如果我们有:

val x = [7,8,9] : int list  

在 REPL 中,我们可以进行如下操作:

- hd x;
val it = 7 : int
- tl x;
val it = [8,9] : int list 

现在如果我们有一个元组让我们说:

val y = (7,8,9) :int*int*int

现在的问题是,我们可以通过从原始元组中删除第一个元素来获得一个更小的元组吗?换句话说,如何以与我们在 list 情况下类似的方式 删除(#1 y)和拥有新元组。(8,9)

谢谢。

4

2 回答 2

3

元组与列表非常不同。对于列表,大小不需要在编译时知道,但对于元组,不仅在编译时知道元素的数量,每个元素的类型都独立于其他元素。

取 的类型签名tl

- tl;
val it = fn : 'a list -> 'a list

它是'a list -> 'a list- 换句话说,tl接受一个并返回另一个。为什么我们没有一个用于元组的呢?假设我们想要类似的东西list'a

y = (1,2,3);
tail y;        (* returns (2,3) *)

为什么这没有意义?想想tail. 那会是什么?在这种情况下,显然是

'a * 'b * 'c -> 'b * 'c

获取a 、 'aa'b'ca 的乘积并返回 a 和 a 的'b乘积'c。在 ML 中,定义的所有函数都必须具有静态确定的类型签名。不可能有一个处理所有可能的元组大小tail的元组函数 ,因为每个元组大小本质上是不同的类型

'a list

可以是多种列表的类型:[1,2,3,4], or ["A", "short", "sentence"], or [true, false, false, true, false]。在所有这些情况下,类型变量的值'a都绑定到不同的类型。(整数、字符串和布尔值)。并且'a list可以是任意大小的列表。

但是采取元组:

(1, true, "yes");   (* (int * bool * string) *)
("two", 2)          (* (string, int) *)
("ok", "two", 2)    (* (string, string, int) *)

与列表不同,这些都是不同的类型。'a list因此,虽然所有列表的类型签名都很简单(

所以你必须这样做:

y = (7, 8, 9);
(a, b, c) = y;

是你的头,a你可以用 . 重新创建尾巴(b,c)。或者创建自己的尾巴:

fun tail (a,b,c) = (b, c)

这也让我们直观地理解为什么这样的函数没有意义:如果不可能定义一个tail用于所有元组类型的单一函数:

fun tail (a,b) = (b)
  | tail (a,b,c) = (b, c)  (* won't compile *)

您还可以使用#速记来获取元组的某些元素:

#1 y;   (* returns 7 *)

但请注意,这#1不是函数,而是编译时的简写。

于 2013-01-18T18:55:26.557 回答
1

列表和元组是不可变的,因此没有像从中删除元素这样的事情。

您可以通过分解原始元组来构造一个新的元组。在 SML 中,首选方法是使用模式匹配:

fun getLastTwo (x, y, z) = (y, z)

如果你喜欢#n函数,你也可以使用它们:

val xyz = (7, 8, 9)
val yz = (#2 xyz, #3 xyz) (* (8, 9) *)
于 2013-01-18T19:03:18.557 回答