成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

手寫編程語言-實現運算符重載

人工智能 機器學習
運算符重載其實并不是一個常用的功能;因為會改變運算符的語義,比如明明是加法卻在重載函數中寫為減法。這會使得代碼閱讀起來困難,但在某些情況下我們又非常希望語言本身能支持運算符重載。

前言

先帶來日常的 GScript 更新:新增了可變參數的特性,語法如下:

int add(string s, int ...num){
println(s);
int sum = 0;
for(int i=0;i<len(num);i++){
int v = num[i];
sum = sum+v;
}
return sum;
}
int x = add("abc", 1,2,3,4);
println(x);
assertEqual(x, 10);

得益于可變參數,所以新增了格式化字符串的內置函數:

//formats according to a format specifier and writes to standard output.
printf(string format, any ...a){}

//formats according to a format specifier and returns the resulting string.
string sprintf(string format, any ...a){}

下面重點看看 GScript 所支持的運算符重載是如何實現的。

使用

運算符重載其實也是多態的一種表現形式,我們可以重寫運算符的重載函數,從而改變他們的計算規則。

println(100+2*2);

以這段代碼的運算符為例,輸出的結果自然是:104.

但如果我們是對兩個對象進行計算呢,舉個例子:

class Person{
int age;
Person(int a){
age = a;
}
}
Person p1 = Person(10);
Person p2 = Person(20);
Person p3 = p1+p2;

這樣的寫法在 Java/Go 中都會報編譯錯誤,這是因為他們兩者都不支持運算符重載;

但 Python/C# 是支持的,相比之下我覺得 C# 的實現方式更符合 GScript 語法,所以參考 C# 實現了以下的語法規則。

Person operator + (Person p1, Person p2){
Person pp = Person(p1.age+p2.age);
return pp;
}
Person p3 = p1+p2;
println("p3.age="+p3.age);
assertEqual(p3.age, 30);

有幾個硬性條件:

  • 函數名必須是operator
  • 名稱后跟上運算符即可。

目前支持的運算符有:+-*/   == != < <= > >=

實現

以前在使用 Python 運算符重載時就有想過它是如何實現的?但沒有深究,這次借著自己實現相關功能從而需要深入理解。

其中重點就為兩步:

  • 編譯期間:記錄所有的重載函數和運算符的關系。
  • 運行期:根據當前的運算找到聲明的函數,直接運行即可。

第一步的重點是掃描所有的重載函數,將重載函數與運算符存放起來,需要關注的是函數的返回值與運算符類型。

// OpOverload 重載符
type OpOverload struct {
function *Func
tokenType int
}

// 運算符重載自定義函數
opOverloads []*symbol.OpOverload

在編譯器中使用一個切片存放。

而在運行期中當兩個入參類型相同時,則需要查找重載函數。

圖片

// GetOpFunction 獲取運算符重載函數
// 通過返回值以及運算符號(+-*/) 匹配重載函數
func (a *AnnotatedTree) GetOpFunction(returnType symbol.Type, tokenType int) *symbol.Func {
for _, overload := range a.opOverloads {
isType := overload.GetFunc().GetReturnType().IsType(returnType)
if isType && overload.GetTokenType() == tokenType {
return overload.GetFunc()
}
}
return nil
}

查找方式就是通過編譯期存放的數據進行匹配,拿到重載函數后自動調用便實現了重載。

感興趣的朋友可以查看相關代碼:

  • 編譯期:https://github.com/crossoverJie/gscript/blob/ae729ce7d4cf39fe115121993fcd2222716755e5/resolver/type_scope_resolver.go#L127
  • 運行期:https://github.com/crossoverJie/gscript/blob/499236af549be47ff827c6d55de1fc8e5600b9b3/visitor.go#L387

總結

運算符重載其實并不是一個常用的功能;因為會改變運算符的語義,比如明明是加法卻在重載函數中寫為減法。

這會使得代碼閱讀起來困難,但在某些情況下我們又非常希望語言本身能支持運算符重載。

比如在 Go 中常用的一個第三方精度庫decimal.Decimal,進行運算時只能使用 d1.Add(d2) 這樣的函數,當運算復雜時:

a5 = (a1.Add(a2).Add(a3)).Mul(a4);
a5 = (a1+a2+a3)*a4;

就不如下面這種直觀,所以有利有弊吧,多一個選項總不是壞事。

責任編輯:武曉燕 來源: crossoverJie
相關推薦

2009-08-12 10:47:03

C#運算符重載

2021-12-15 10:25:57

C++運算符重載

2021-12-16 10:40:11

C++運算符重載

2025-02-24 11:16:20

2009-09-04 13:18:10

C#允許運算符重載

2009-08-12 10:27:12

C#運算符重載運算符重載實例

2009-08-14 10:16:57

C#運算符重載

2009-08-12 10:56:47

C#運算符重載C#運算符重載實例

2009-08-12 12:46:11

C#運算符重載

2011-07-15 01:34:36

C++重載運算符

2020-09-30 14:04:25

C++運算符重載

2009-08-12 10:37:13

C#運算符重載

2009-08-11 15:51:08

C#運算符算術運算符

2024-01-26 16:37:47

C++運算符開發

2010-01-22 17:48:46

VB.NET運算符重載

2009-08-12 11:20:51

C#運算符重載

2009-08-12 15:20:18

C#賦值運算符復合賦值運算符

2009-08-12 15:02:49

C#賦值運算符簡單賦值運算符

2020-08-10 10:20:15

流插入運算符語言

2021-04-14 10:00:44

Python運算符重載
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久av网站 | 久综合| 欧美精品在欧美一区二区 | 亚洲一区二区在线 | 中文字幕一区二区三区在线观看 | 激情久久久久 | 又黑又粗又长的欧美一区 | 国产精品九九九 | 青草福利 | 精品久久影院 | 久久精品亚洲精品国产欧美 | 成人国产精品久久久 | 无码国模国产在线观看 | 九九热这里 | 欧美福利视频一区 | 视频在线一区二区 | 国产成人精品999在线观看 | 99日韩| 日韩高清黄色 | 国产一区二区三区精品久久久 | 四虎在线观看 | 在线一区二区三区 | 国产午夜精品一区二区三区嫩草 | 一区二区三区小视频 | 99re热精品视频 | 中文字幕亚洲欧美日韩在线不卡 | 久久久久久亚洲 | xxxxx黄色片 欧美一区免费 | av在线亚洲天堂 | 国产精品99久久久久久宅男 | 欧美精品一区二区蜜桃 | 欧美亚洲网站 | 另类 综合 日韩 欧美 亚洲 | 久久爆操 | 欧美一级毛片久久99精品蜜桃 | 羞羞的视频在线看 | 性高湖久久久久久久久 | 欧美一区二区三区免费电影 | 91在线导航 | 精品国模一区二区三区欧美 | 伊人免费视频二 |