二、cryptol数据类型

1.1 基本数据类型

Cryptol提供五种基本数据类型:位、序列、整数、元组和记录。字(即n位数)是序列的特例.请注意,除了位数和整数外,所有其他 Cryptol类型可以嵌套到您喜欢的深度。也就是说,我们可以拥有由其他记录组成的包含元组的序列的记录,这为我们提供了一个丰富的类型系统来精确地描述 我们的程序操作的数据形状。

Cryptol> 12 : [_]
0xc
Cryptol> 12 : [8]
0x0c
Cryptol>

12 : [8]:表示12有8bit位的字。

12 : [_]:意味着12有一个字类型,其位数未指定。

注:这里输出的都是16进制的数,我们可以使用命令:set base=10,将系统设置从10进制,当然你可以换成其他进制

1.2 位:Booleans 类型

类型位表示一位信息。这种类型的值有两个:true和false。位值在Cryptol中起着重要的作用,稍后我们将详细介绍。特别是,if-then-else s语句中的测试表达式必须具有类型位。逻辑运算符&& (and), || (or), ^ (xor), and ~ (complement) 提供了位的基本运算符。 

在cryptol命令行中尝试输入以下内容,看看输出结果和你预想的有什么不一样:

True
false
False : Bit
if True && False then 0x3 else 0x4
False || True
1.3. Words: Numbers
(True && False) ^ True
~False
~(False || True)

1.3 数字

默认情况下,Cryptol数字是16进制中打印单词。在处理下面的示例时,您可能会发现将输出基设置为10很有用。为此,请使用以下命令:

:set base=10

在cryptol中不同进制的表示:

0b11111011110 // binary
0o3736 // octal
2014 // decimal
0x7de // hexadecimal

十进制数字在一种有点精确的语言(如密码)中会产生问题。以一个二次幂明确指定存储每个数字所需的位数。例如,0b101占用三位存储,所以它的类型是[3]。十六进制数字需要4位来存储,因此0xabc需要12位,其类型为[12]。另一方面,一个十进制数字可能需要1到4位来表示,所以数字的数目不是确定类型。十进制数可以假定为密码中的任何一种类型;也就是说,它们是多态的。例如,19可以有无界类型integer类型[8]、类型[5]或任何其他字类型至少5位。

扫描二维码关注公众号,回复: 11582529 查看本文章

1.4 Integets:无界数

整数类型表示无限制大小的数学整数。要用cryptol编写整数值,只需编写十进制数,可选地用:integer注释以消除类型的歧义。以2,8为基数的数字,或16始终是N位字,并且从不具有整数类型。但是,它们可以转换为无边界整数。使用toInteger。例如,toInteger 0xff表示整数255。要写一个负整数,只需对结果:例如,-12和-toInteger 0xc表示整数'12。

练习1.4。比较计算表达式0x8+0x9和toInteger 0x8+toInteger 0x9的结果。也可以尝试计算整数(-0x5)。你能解释一下结果吗?

Cryptol> toInteger 0xff
255
Cryptol> - toInteger 0xff
-255
Cryptol> 0x8 + 0x9
0x1
Cryptol> toInteger 0x8 + toInteger 0x9
17

0x8 + 0x9为17 = 0x11但是只有1位表示16进制,所以溢出,剩下了0x1

1.5 元组

元组是具有任意类型的任意值的简单有序集合。元组是用括号写的包围两个或多个逗号分隔的元素。cryptol还支持一个特殊的零元素元组,元组类型的语法与元组值类似。它们是用括号括住两个或多个逗号分隔类型编写的。元组类型的值是相同长度的元组,其中每个位置的值具有相应的类型。例如,类型([8],bit)包含的对的第一个元素是一个8位单词,并且第二个元素是一个bit位。空元组()是类型()的唯一值。

tuples.n:是取tuples中的index位n的元素

Cryptol> (1, 2+4)
(1, 6)
Cryptol> (True, False, True ^ False)
(True, False, True)
Cryptol> ((1, 2), False, (3-1, (4, True)))
Cryptol> (1, 2+4).0
1
Cryptol> (1, 2+4).1
6
Cryptol> ((1, 2), False, (3-1, (4, True))).2.1
(4, True)

1.6 序列:同质集合

虽然元组包含异构数据,但序列用于同构的值集合,类似于传统语言中的值数组。序列包含任何单一类型的元素, 偶数序列本身,任意嵌套.我们简单地写一个序列,把它包在方括号内,用逗号分隔的元素。

[1, 2]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

错误示例:

[True, [True]]
[[1, 2, 3], [4, 5]]

1.6.1 枚举 

Cryptol枚举允许我们编写更紧凑的序列,而不是单独列出元素。枚举是通过提供(可能无限)范围来写入序列的一种方法。 Cryptol枚举不等同于主流编程语言的枚举类型概念,但这两种结构都保证枚举元素是不同的。这里的可以表示无限的序列,不同于其他的过程语言。尝试在编辑器中输入以下的序列,查看结果:

[1 .. 10] 
[1, 3 .. 10] 
[10, 9 .. 1] 
[10, 9 .. 20]
[10, 7 .. 1]
[10, 11 .. 1] 

1.6.2 理解

密码理解是一种编程计算新序列元素的方法。这种句法使人想起了普通数学中的集合理解符号覆盖平行的分支(如下面的练习所述)。注意,密码理解并不是泛化的。数字理解(如求和、乘积、最大值或最小值),尽管这样的理解肯定可以使用密码理解来定义。

[ (x, y) | x <- [1 .. 3], y <- [4, 5] ]
[(1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)]

[ x + y | x <- [1 .. 3], y <- [] ]
[]

[ (x + y, z) | x <- [1, 2], y <- [1], z <- [3, 4] ]
[(2, 3), (2, 4), (3, 3), (3, 4)]

具有多分支的理解称为平行理解,我们可以有任意数量的平行分支,每个分支的内容将被压缩以获得结果。一定要注意平行这个概念的理解,每次取平行分支的相同位置元素,如果平行分支结束,此此代码结束。实验以下的表达方式:

[ (x, y) | x <- [1 .. 3] | y <- [4, 5] ]
[(1, 4), (2, 5)]

[ x + y | x <- [1 .. 3] | y <- [] ]
[]

[ (x + y, z) | x <- [1, 2] | y <- [1] | z <- [3, 4] ]
[(2, 3)]

理解可以嵌套:

Cryptol> [ [ (x, y) | y <- [1 .. 5] ]| x <- [1 .. 5]]


[[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5)],
 [(2, 1), (2, 2), (2, 3), (2, 4), (2, 5)],
 [(3, 1), (3, 2), (3, 3), (3, 4), (3, 5)],
 [(4, 1), (4, 2), (4, 3), (4, 4), (4, 5)],
 [(5, 1), (5, 2), (5, 3), (5, 4), (5, 5)]]

1.6.3 追加和索引

对于序列,两个基本操作附加(#)并选择元素(@,@@,!而且!!!).前选择运算符(@)从开头开始计数,而(!)从结尾开始向前。索引始终以零开始:即,xs@0是xs的第一个元素,而xs!0是最后一个。动手尝试输入以下,查看输出结果:

[] # [1, 2]
[1, 2] # []
[1 .. 5] # [3, 6, 8]
[0 .. 9] @ 0
[0 .. 9] @ 5
[0 .. 9] @ 10
[0 .. 9] @@ [3, 4]
[0 .. 9] @@ []
[0 .. 9] @@ [9, 12]
[0 .. 9] @@ [9, 8 .. 0]
[0 .. 9] ! 0
[0 .. 9] ! 3
[0 .. 9] !! [3, 6]
[0 .. 9] !! [0 .. 9]
[0 .. 9] ! 12

1.6.4 有限和无限序列

到目前为止,我们只看到有限的序列。无限序列是与流相对应的具有无限数量的元素的序列。CryptoL支持无限序列,其中元素是按需访问,不会急于分配内存。这意味着密码不会进入无限循环,因为您已经创建了无限的序列:它将自动地构造序列并使其元素可用 根据程序的要求。动手尝试输入以下,查看输出结果:

Cryptol> [1:[32] ...]
[1, 2, 3, 4, 5, ...]
Cryptol> [1:[32], 3 ...]
[1, 3, 5, 7, 9, ...]
Cryptol> [1:[32] ...] @ 2000
2001
Cryptol> [1:[32], 3 ...] @@ [300, 500, 700]
[601, 1001, 1401]
Cryptol> [100, 102 ...]
[100, 102, 104, 106, 108, ...]

注:这里我们明确告诉cryptol,我们使用32位字作为单位。

1.6.5 序列操作

序列是Cryptol的核心,有许多内置函数可以各种方式操作它们。有必要尝试以下练习,以获得基本的熟悉程度,这是基本的操作。

Cryptol> take`{3} [1 .. 12]
[1, 2, 3]

Cryptol> drop`{3} [1 .. 12]
[4, 5, 6, 7, 8, 9, 10, 11, 12]

分成三组
Cryptol> split`{3} [1 .. 12]
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

分组,每组3个
Cryptol> groupBy`{3} [1 .. 12]
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]

Cryptol> join [[1 .. 4], [5 .. 8], [9 .. 12]]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Cryptol> join [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

举证的转置
Cryptol> transpose [[1, 2, 3, 4], [5, 6, 7, 8]]
[[1, 5], [2, 6], [3, 7], [4, 8]]

Cryptol> transpose [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

CryptoL原始函数Split将一个序列分割为任意数量的等长部分。

Cryptol> split [1..12] : [1][12][8]
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
Cryptol> split [1..12] : [2][6][8]
[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
Cryptol> split [1..12] : [3][4][8]
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

1.6.6 移位和旋转

对序列的常见操作包括移位和旋转。Cryptol支持这两个版本的左/右变体。尝试输入以下,查看结果:

<<       >>   是不循环操作

<<<    >>> 是循环操作

[1, 2, 3, 4, 5] >> 2
[1, 2, 3, 4, 5] >> 10
[1, 2, 3, 4, 5] << 2
[1, 2, 3, 4, 5] << 10
[1, 2, 3, 4, 5] >>> 2
[1, 2, 3, 4, 5] >>> 10
[1, 2, 3, 4, 5] <<< 2
[1, 2, 3, 4, 5] <<< 10

1.7 数字作为序列

我们在Cryptol中引入了数字作为一种独特的值类型。事实上,密码中的一个数字只不过是一个有限的位序列,所以单词不是一个单独的类型。例如,字面表达式42:[6]与位序列[True, False, True, False, True, False]完全相同.类型[6]实际上只是[6]Bit的缩写。请尝试下列数字:(提示:setbase=2以查看位模式 )

Cryptol> 12:[4]
0b1100   //将12装在4bit中

Cryptol> 12 # [False]
0b11000  //False是一个0

Cryptol> [False, False] # 12
0b001100  //[False, False] 是 0b00

Cryptol> [True, False] # 12
0b101100

Cryptol> 12 # [False, True]
0b110001

Cryptol> 32:[6]
0b100000

Cryptol> 12 # 32
0b1100100000

Cryptol> [True, False, True, False, True, False] == 42
True

在cryptol中将数字当成学列来处理

Cryptol> take`{3} 0xFF
0b111    //0xFF = 0b11111111  取它的前三位

Cryptol> take`{3} (12:[6])
0b001    // 12 = 0b001100 下面同理

Cryptol> drop`{3} (12:[6])
0b100

Cryptol> split`{3} (12:[6])
[0b00, 0b11, 0b00]

Cryptol> groupBy`{3} (12:[6])
[0b001, 0b100]

想一想,如果我们把一个数字右移依次,说12:[6],会发生什么?

(12:[6]) >> 1

= [False, False, True, True, False, False] >> 1
= [False, False, False, True, True, False]
=0b00110
= 6

自己尝试下面位移,查看结果:

(12:[8]) >> 2
(12:[8]) << 2

1.8 字符和字符串

严格地说,Cryptol没有单独类型的字符和字符串。但是,Cryptol确实允许程序中的字符,这些字符只是对应于它们的ASCII等价物。类似的,字符串仅仅是字符的序列,也就是单词的序列。以下例子说明:

Cryptol> :set base=10
Cryptol> :set ascii=off
Cryptol> 'A'
65

Cryptol> "ABC"
[65, 66, 67]

Cryptol> :set ascii=on
Cryptol> "ABC"
"ABC"

Cryptol> :set ascii=off
Cryptol> ['A' .. 'Z']
[65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90]

Cryptol> :set ascii=on
Cryptol> ['A' .. 'Z']
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"

1.9 记录:命名集合(我理解就是键值对)

{xCoord = 12:[32], yCoord = 21:[32]}
{xCoord = 12:[32], yCoord = 21:[32]}.yCoord
{name = "Cryptol", address = "Galois"}

{name = "Cryptol", address = "Galois"}.address //这里是取一个值

{name = "test", coords = {xCoord = 3:[32], yCoord = 5:[32]}}
{name = "test", coords = {xCoord = 3:[32], \
yCoord = 5:[32]}}.coords.yCoord
{x=True, y=False} == {y=False, x=True}

1.10 零

是cryptol中最有用的数字之一,在这个语言中0由所有的False位组成:

Cryptol> zero : Bit
False
Cryptol> zero : [8]
0
Cryptol> zero : ([8], Bit)
(0, False)
Cryptol> zero : [8][3]
[0, 0, 0, 0, 0, 0, 0, 0]
Cryptol> zero : [3](Bit, [4])
[(False, 0), (False, 0), (False, 0)]
Cryptol> zero : {xCoord : [12], yCoord : [5]}
{xCoord=0, yCoord=0}
Cryptol> ~zero : Bit
True
Cryptol> ~zero : [8]
255
Cryptol> ~zero : ([8], Bit)
(255, True)
Cryptol> ~zero : [8][3]
[7, 7, 7, 7, 7, 7, 7, 7]
Cryptol> ~zero : [3](Bit, [4])
[(True, 15), (True, 15), (True, 15)]
Cryptol> ~zero : {xCoord : [12], yCoord : [5]}
{xCoord=4095, yCoord=31}

1.11 计算

猜你喜欢

转载自blog.csdn.net/qq_38234785/article/details/100897883