日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
編程語言中索引簽名是什么?

一、背景

最近在參與 KusionStack? 內(nèi)置的領(lǐng)域語言 —— KCL 配置語言編譯器 的開發(fā),語言的語法中包括一個 “索引簽名” 的概念,在參與社區(qū)討論的時候發(fā)現(xiàn)很多小伙伴不明白這個 “索引簽名” 是什么,于是自己也想了一下,發(fā)現(xiàn)自己也只是知道是什么樣子,但是不知道 “索引簽名” 完整的定義,因此,決定寫一篇貼子來梳理一下 “索引簽名” 到底是什么。

10多年的興寧網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。全網(wǎng)整合營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整興寧建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)公司從事“興寧網(wǎng)站設(shè)計”,“興寧網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。

二、見名知意

首先,索引簽名的想法并不神秘新鮮。早期 Windows 開發(fā)中應(yīng)該見過類似的編程規(guī)范:

  • bool (BOOL) 用 b 開頭 bIsParent
  • byte (BYTE) 用 by 開頭 byFlag
  • short (int) 用 n 開頭 nStepCount
  • long (LONG) 用 l 開頭 lSum
  • char (CHAR) 用 c 開頭 cCount

只要看到變量和類成員的名字就知道其類型,提高了代碼類型方面的可讀性。但是這種約定并沒有沉淀到 C++ 語言中,如果語言能夠支持定義以 b 開頭的成員是 BOOL 類型這種特性就厲害了 —— 這其實就是索引簽名的樸實目的。

先從字面意義上看,“索引簽名 (index signature)” 包含 “索引 (index)” 和 “簽名 (signature)” 兩部分。

1. 索引 (index)

從開發(fā)人員的角度來看,索引,類似于 C 語言中指針,它像一個箭頭一樣可以指向一個特定的事物,出于某些原因我們可能無法直接訪問這個事物,或者這個事物與其他的東西混合在一起,直接訪問這個事物可能要在很多其他事物中尋找很久。因此,我們使用索引指向這個事物,可以理解為我們在我們需要的事物上綁了一根線,并且留了一個線頭在身邊,每當(dāng)我們想要使用這個事物的時候,我們不需要再從一堆事物中去尋找它,只需要拿起這個線頭,并順著這根線就能找到這個特定的事物,這個線頭就是 "索引 index",并且很明顯,一根線不允許分叉綁定兩個事物,所以通常大家默認(rèn)某個事物的 "索引 index" 是不會再指向另一個事物的。

因此,在開發(fā)的過程中,“索引 index” 最主要的使用場景就是 “在一堆事物中,查找特定的事物”。例如:最常見的數(shù)據(jù)結(jié)構(gòu) - 數(shù)組,就是 “索引” 的一個優(yōu)秀案例。在數(shù)組中,索引是一個整形的數(shù)字,這個數(shù)字是數(shù)組中每個元素的位置信息,通過位置,快速的定位某個數(shù)組元素。

int a[3] = [1, 2, 3];

// 使用索引0,就可以在1,2,3三個數(shù)字中,快速的找到排在最前面的元素。
assert a[0] = 1;
assert a[1] = 2;
assert a[3] = 3;

除了數(shù)組,另一個使用索引的數(shù)據(jù)結(jié)構(gòu)是我們常見的 Hash 表,只不過在有些編程語言中將哈希表中的索引叫做 key。

hashtable a;

// "Jack" 就可以視作一個索引,通過名字字符串作為索引,
// 在不考慮重名的情況下,它指向了一個結(jié)構(gòu)實例 Person("Jack")。
a.put("Jack", new Person("Jack"))
a.put("Tom", new Person("Tom"))
a.put("Lee", new Person("Lee"))

再舉一個例子,很多編程語言中都存在的結(jié)構(gòu) struct 或者類 class,也使用到了索引的思想。

// 可以看做是String和Integer的集合
// 如果沒有索引,我們就只知道Person內(nèi)部有兩個屬性,
// 一個類型為String表示名字,
// 一個為Integer表示年齡。
struct Person{
name: String,
age: Integer,
}

Person p = new Person(name: "Jack", age: 10);

// 通過索引name我們能夠輕松的獲取到Person的名字Jack。
assert p.name == "Jack"

// 通過索引age我們能夠輕松的獲取到Person的年齡10。
assert p.age == 10

綜上,索引可以被看作一個指針,沒有具體的格式約束,只要能唯一的指向一個事物即可,不能具有二義性,即不能指向 A 的同時又指向 B?;蛘咚饕部梢钥醋饕粋€方法,以索引值為參數(shù),返回索引指向的事物。

注:這個概念不包括一些特殊情況,比如某些應(yīng)用場景就是需要同時指向 A 和 B 的索引也是有可能的,這里討論的是大多數(shù)的通用情況。

2. 簽名 (Signature)

在編程語言領(lǐng)域,Signature 這個詞除了使用在 IndexSignature 中,在很多常見的編程語言中也有 Signature 這個概念。比如 C++ 中的類型簽名:

char c;
double d;

// 他的簽名為 (int) (char, double)
int retVal = (*fPtr)(c, d);

通過上面這個類型簽名,我們雖然不知道這個函數(shù)指針未來可能會指向的函數(shù)的具體定義,但是通過這個簽名,我們能看到這個指針指向的函數(shù)如何使用,它以 char 和 double 為傳入?yún)?shù),返回值為 int,并且,這個簽名也對指針未來指向的函數(shù)進(jìn)行了約束,它只能指向以 char 和 double 為傳入?yún)?shù),返回值為 int 的函數(shù)。相似的概念在 Rust 語言中也有體現(xiàn)。在 Rust 中,我們可以直接使用一個函數(shù)的簽名如下:

// add 方法的簽名 fn(i32, i32) -> i32
fn add(left: i32, right: i32) -> i32 { left + right }

// sub 方法的簽名 fn(i32, i32) -> i32
fn sub(left: i32, right: i32) -> i32 { left - right }

// 通過方法簽名,我們可以為某一類結(jié)構(gòu)相近的方法提供工廠。
fn select(name: &str) -> fn(i32, i32) -> i32 {
match name {
"add" => add,
"sub" => sub,
_ => unimplemented!(),
}
}

fn main() {
let fun = select("add");
println!("{} + {} = {}", 1, 2, fun(1, 2));
}

再來看看 Java 中的類型簽名:

可以看到,核心的思想與 C/C++/Rust 中的類型簽名一樣,通過描述方法的傳入?yún)?shù)與返回值的類型,來概述一個方法如何使用,而不需要關(guān)心這個方法的具體實現(xiàn)。

Python/Golang 中也有類型簽名的概念,而且核心思路都一樣,這里就不再贅述了。

通過了解這些編程語言的類型簽名,我們知道,簽名 (Signature) 其實與類型 (Type) 描述了同一個事物,類型 (Type) 所描述的事物是某些性質(zhì)的集合,具備相同性質(zhì)的事物,就可以認(rèn)為它們的類型 (Type) 相同;而簽名 (Signature) 可以看作由多個類型 (Type) 組合而成的復(fù)合類型。

舉例說明:

int32 a = 0; // a 的類型 (type) 是 int32

可以看到上述變量 a 的類型 (type) 是 int32,大家只要一聽到 int32,就會條件反射的想到 a 的一些性質(zhì),比如:32 位,整數(shù),范圍等等,int32 就是對這些性質(zhì)的總稱,下次再遇到一個變量 b,只要他的性質(zhì)符合 int32 的性質(zhì),我們就可以把它們歸為一類,即,它們都是類型 (type) 為 int32 的變量。

可是,編程語言的類型系統(tǒng)中,不僅僅有變量,還有一個很重要的東西 -- 方法。

int add(int a, int b) {
return a+b;
}

現(xiàn)在,就需要一個東西,描述上面這個方法的類型,即,需要有一個東西來區(qū)分什么樣子的方法與 add 方法屬于同一類。名稱?恐怕不行,因為下面這兩個同名方法用起來感覺完全不一樣。

// 兩個數(shù)相加
int add(int a, int b) {
return a+b;
}

// 兩個數(shù)組合并
int[] add(int a[], int b[]) {
return a.append(b);
}

所以,在大佬們設(shè)計語言的的時候決定,使用返回值和參數(shù)列表的類型 (type) 組合起來,來定義一個方法的類型,即:

// 兩個數(shù)相加
// 類型為 (int, int) -> int
int add(int a, int b) {
return a+b;
}

// 兩個數(shù)組合并
// 類型為 (int[], int[]) -> int[]
int[] add(int a[], int b[]) {
return a.append(b);
}

而簽名 (Signature) 就可以理解為將多個類型 (type) 組合起來形成的復(fù)合類型。這個簽名用來描述方法的類型,就可以叫做方法簽名 (Method/Function Signature)。那么,寫到現(xiàn)在,通過類比,也能猜出索引簽名大概是個什么東西了,前面提過索引可以看做是一個方法,輸入一個值,返回它指向的事物。

3. 索引簽名 (IndexSignature)

上面提到,索引我們可以看作一個指針或是一個方法,簽名 (Signature) 就可以理解為將多個類型 (type) 組合起來形成的復(fù)合類型,索引簽名 (IndexSignature) 描述的就是索引的類型,寫到這里我腦子里產(chǎn)生了點疑問,那索引簽名不就是索引的類型嗎,索引為什么要使用復(fù)合類型進(jìn)行描述,一個普通類型 (type) 描述不了索引的類型嗎?

  • a [0] 這個索引的類型不就是 Integer 嗎 ?
  • hash.get ("name") 這個索引的類型不就是 String 嗎 ?

這個問題,源自于對索引理解的偏差,

  • a[0]? 的索引不是 0,他的索引是0->a[0]``, 即輸入0,返回 [0]`.
  • hash.get("name")? 的索引也不是 “name”, 他的索引是“name”->"Jack", 輸入 “name” 返回 "Jack"。

寫到這里,其實使用各種編程語言的小伙伴們心里應(yīng)該都能感覺自己可能或多或少都接觸過索引簽名這個東西,只是當(dāng)時并不在意他叫什么,之所以這么說,是因為我自己在寫到這里的時候,想到了之前開發(fā) java 的時候使用的 hashmap:

public class RunoobTest {
public static void main(String[] args) {
HashMap Sites = new HashMap();

Sites.put("one", "Google");
Sites.put("two", "Runoob");
Sites.put("three", "Taobao");
Sites.put("four", "Zhihu");

System.out.println(Sites);
}
}

上述代碼第 7 行 HashMap Sites = new HashMap() 中, 就可以理解為一種索引簽名,它定義了這個 HashMap 結(jié)構(gòu)中的索引的類型,是輸入一個字符串,返回一個字符串。而數(shù)組的索引簽名也類似,只不過,數(shù)組的索引簽名編譯器幫我們自動省略了,即輸入類型一定是 int,不用我們手動書寫了。

// 顯式索引簽名:Array a = [0, 1, 2]
int[] a = [0, 1, 2];

// 顯式索引簽名:Array a = ["0", "1", "2"]
String[] a = ["0", "1"];

三、一些語言中的索引簽名

索引簽名的思想由來已久,最早甚至可以追溯到早些年間程序員們?yōu)榱顺绦虻目勺x性而定下的編程規(guī)約,當(dāng)我們規(guī)定一個整型變量的名稱必須以 i 開頭的時候,其實已經(jīng)是在定義指向一個整型的的索引的簽名了。

int i_user_id = 10; // 整型以i開頭,定義了  的索引簽名
float f_user_weight = 120.3; // 浮點以f開頭,定義了 的索引簽名

不過,規(guī)約可能并不是所有人都愿意遵守,當(dāng)索引的名稱成為編程元素的一部分,并且可以動態(tài)的操作的時候,將索引簽名作為變成規(guī)約,就不是太合適了。

// 當(dāng)出現(xiàn)可以動態(tài)添加索引的編程元素。
const a = {
"name": "Jack"
}

// 你和你的小伙伴約定好,年齡的索引就是“age”。
// 他在某個地方add("age", 10)。
a.add("age", 10);

// 你在某個地方,需要這個年齡。
a.get("age");

// 如果索引簽名是編程規(guī)約,而不帶有強(qiáng)制性。
// 你的小伙伴恰恰手一滑,眼一閉,寫錯了也沒看到 warning。
a.add("aeg", 10);

// 那你這邊就只能看到空指針異常了。
NullPointerException: "age" is not define.

因此,為了提升程序的穩(wěn)定性,避免這種不必要的風(fēng)險,一些通用編程語言 (如:TypeScript) 和領(lǐng)域語言 (如:KCL,CUE) 開始將索引簽名作為語言的特性暴露給開發(fā)者,旨在提供編程過程中的安全性和穩(wěn)定性,降低上述問題產(chǎn)生的影響。

1. TypeScript 索引簽名

在 TS 中,我們可以通過下面這種方式定義一個對象:

const salary1 = {
baseSalary: 100_000,
yearlyBonus: 20_000
};

根據(jù)上文我們對索引的描述,我們知道這個對象有兩個索引,并且它們的類型即索引簽名應(yīng)該是相同的,即它們是同一類索引。

const salary1 = {
baseSalary: 100_000, // 索引1 : 輸入“baseSalary”,返回100_000
yearlyBonus: 20_000 // 索引2 : 輸入”yearlyBonus“, 返回20_000
};

TS 提供了一種特性,使得開發(fā)者可以編寫這種索引簽名:

interface NumbersNames {
[key: string]: string // 索引的類型為輸入String,返回String
}

const names: NumbersNames = {
'1': 'one',
'2': 'two',
'3': 'three',
// etc...
'5': 'five' // Error: 這個索引的輸入類型為int,類型不匹配。
};

2. CUE 索引簽名

CUE 支持在索引簽名中寫正則表達(dá)式,支持對索引名稱的校驗。

a: {
foo: string // 索引foo 返回值是string類型。
[=~"^i"]: int // 以i開頭的索引,返回值都是int。
[=~"^b"]: bool // 以b開頭的索引,返回值都是bool。
...string // 其他的所有的索引返回值都是string。
}

b: a & {
i3: 3 // 索引i3以i開頭,返回值是3類型為int。
bar: true // 索引bar以b開頭,返回值true類型為bool。
other: "a string" // 其他索引的返回值類型都是字符串。
}

3. KCL 索引簽名

KCL 索引簽名的形式為 [: ]: ,語義上表示結(jié)構(gòu)中所有屬性的 key 只能為 類型,值只能為  類型:

  • 索引簽名的 ``` 處的類型只能為 str, int, float,不能為 union 類型
  •  可以為 KCL 任意合法的數(shù)據(jù)類型,包含 schema 類型和 union 類型等類型
  •  表示任意 KCL 合法的標(biāo)識符,并且可以省略不寫,一般用于和 check 結(jié)合使用

基礎(chǔ)用法

schema 定義方式:

schema Map:
[str]: str

注意使用了索引簽名的 schema 默認(rèn)為 relaxed。

一個索引簽名只能在 schema 當(dāng)中定義一次。

高級用法

類型簽名書寫默認(rèn)值:

schema Map:
[str]: str = {"default_key": "default_value"}

與 schema 定義混合使用,強(qiáng)制 schema 所有屬性 key, value 類型:

schema Person:
name: str
age: int # error, 與[str]: str語義沖突,
[str]: str # schema所有屬性的值只能為字符串類型

可以在 schema 中同時定義 schema 屬性和索引簽名,通常用于表示 schema 中額外屬性的類型約束,強(qiáng)制除 schema 定義所有屬性 key, value 類型。

schema Person:
name: str
age?: int
[...str]: str # 表示除name, age之外,其余schema屬性必須為字符串類型,屬性的值也必須為字符串類型

屬性名稱配合 check 使用:

schema Data:
[dataName: str]: str

check:
dataName in ["Alice", "Bob", "John"]

data = Data {
Alice: "10"
Bob: "12"
Jonn: "8" # error Jonn not in ["Alice", "Bob", "John"]
}
  • 注意:KCL 索引簽名暫不支持 union 類型以及字面量類型等類型。
  • 注意:索引簽名暫不支持對 value 的的值進(jìn)行校驗,僅支持類型檢查。
  • 注意:索引簽名暫不支持類似 CUE 的正則校驗 ["$b^"] ,因為屬于 runtime 檢查,不屬于類型系統(tǒng)的一部分,當(dāng)類型檢查從 runtime 階段前置后不容易結(jié)合,因此暫不支持。

四、總結(jié)

本文簡單介紹了索引簽名,通過梳理索引和簽名的概念,并對比了一些通用編程語言和領(lǐng)域語言中使用到的簽名的思想,泛泛的描述了一下索引簽名大概的樣子,希望能夠幫助大家能夠更加輕松的了解索引簽名這個概念,文章的內(nèi)容只是筆者個人對索引簽名的理解,如果有不對或者不合適的地方歡迎大家指正。


新聞名稱:編程語言中索引簽名是什么?
當(dāng)前路徑:http://m.5511xx.com/article/coiphpj.html