PTT推薦

Re: [討論] 請大家聊聊靜態語言的缺點

看板Soft_Job標題Re: [討論] 請大家聊聊靜態語言的缺點作者
electgpro
(Ray)
時間推噓 3 推:3 噓:0 →:6

借題發揮一下:static typed for the win

不過還是先切題回答「靜態語言的缺點」:

在大部分常用的靜態語言中,的確可能出現 valid program 不好標注 type 的情況

不過到底有多難標注就完全看是哪個語言跟哪個版本了

-----

個人有碰過的語言依據學習順序大概是這樣

C -> Java -> Python/Ruby/JS/ObjC -> Scala/Kotlin -> Haskell/Idris

(差不多時期學的用斜線表示)

我對這個問題的偏好也從「靜態」轉「動態」再轉回「靜態」

下面大概聊一下我在學習不同語言的時候的感想

-----

##「靜態」轉「動態」

- Java -> Python,覺得 Python 好方便,不用寫長長的 main,且不用宣告變數型態。

## 在各種常見動態語言中遊蕩(?

- 學了 Ruby 後覺得 map/filter 等等使用 block 的函數實在太方便了。而 Python
相對應的答案是 list comprehension。當時不明白明明可以用 Library 解決的問題, 為什麼要使用另外的語法,後來學了 Haskell 才完全了解這東西應該怎麼用,
不過這是另外一個話題。

- 學了 JS 後覺得 Ruby block 語法比較沒有一致性,在 JS 全部用 anonymous
function 就解決了。也大概在這個時間點了解所謂 first order function
是怎麼一回事。

因為差不多在這個時期同時有在接 Android/iOS 專案,所以 Java/ObjC 碰得不少。

ObjC 雖然有 lambda ,但語法異常複雜以至於有這個網站

http://fuckingblocksyntax.com/

而當時 Java 才剛開始有 lambda solution,必須要靠 compiler plugin 才能支援,

但還是 desugar 成 class Function<T, R>,所以在 Java-like lang 寫 lambda

要標註 function type 實在醜,所以在這個時期最喜歡的是支援動態型別、

first order functions 的語言 JS。


## 「動態」轉「靜態」

不過上述問題在 scala/kotlin 等新興語言都有改善。以下是不同語言的 map function

比較:

- Java 8: List<R> map(Function<T, R> f)
- Scala: def map[B](f: (A) => B): List[B]
- Kotlin: fun <R> map(f: (T) -> R): List<R>
- Haskell: map :: (a -> b) -> [a] -> [b]

基本上大部分的情境中 function type annotation 現在應該都不是什麼大問題

當然 OO Lang 還要考慮繼承,所以還有 variance 的問題(不過在這邊就先忽略不談


## Type Annotation 很花時間是指?

Type inference 現在應該都是基本了,所以宣告變數需要重複寫 type 應該已經不是

個問題了。其他常被提到的則跟 sum type/product type 有關。

Product type 基本上就是一個 class 有多個 value members。但 Sum type 大家可能就

比較不熟悉。

舉例來說,一個 function 他需要同時支援 type A 跟 type B 作為唯一的 argument

基本上我知道的語言中,大概有三種方式:

1. 讓 A, B 實作同一個 interface/super class
2. Union Type, typescript/flowtype: type AorB = A | B
3. Tagged Union Type, Haskell: data AorB = A A | B B

其中 scala/kotlin 屬於 1. 但不像 Java 一樣宣告起來麻煩:

sealed abstract class Base
case class A() extends Base
case class B() extends Base

當然還是比 Haskell 的一行多了一些。而 TypeScript 更可以 inline 宣告。

到這邊為止,大部分的語言應該在九成五的 case 都不需要太多成本就能 cover 了。


## Haskell/Idris

當然還是有某些狀況下,type 很難被正確 annotate,例如如果 input 小於某個數字,

就回傳 String 否則回傳 Int。雖然可以用上面提到的 sum type,但是如果我們確定

input 一定大於指定數字,所以不想要處理 String 作為 output 的話,那就要用到

dependent type 了。

而如果使用有 dependent type 的語言,絕大多數的 program 都可以被 annotate


不過問題是:

1. 學習門檻高,大部分的基礎程式課程連 generic 都不會講,更不用講 DT
2. 大部分的語言不支援 DT


## 結論

靜態語言跟動態語言只是一個非常粗略的分法,其中可以討論的面向從純技術層面

到團隊營運跟產品性質都有關係。如果可以在討論的時候舉一些例子會比較有趣 :D


不過一般來說我還是覺得靜態語言比較好一些。


--

※ PTT留言評論
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 82.25.26.57 (英國)
PTT 網址
※ 編輯: electgpro (82.25.26.57 英國), 11/24/2020 09:48:00

CoNsTaR11/24 10:05typecheck 對於成功 type checked 的程式碼的關係就相當

CoNsTaR11/24 10:05於 compile 對於成功編譯出來的執行檔的關係一樣

CoNsTaR11/24 10:05計算和類型本來就是等價的,不知道為什麼有很多人在討論

CoNsTaR11/24 10:06靜態型別的優缺點,但都沒看到有人在講編譯式語言的優缺

CoNsTaR11/24 10:06

CoNsTaR11/24 10:08強型別對程式碼的好處不就像是編譯式對程式的好處一樣嗎

CoNsTaR11/24 10:08

electgpro11/24 18:45理想上同意,但實務上可能會有一些詭異的狀況

zero1199512/01 11:12