筆記, Cirru Table Redo 失敗, 經驗教訓

緣起

前面兩週花了一些精力斷斷續續去想這個項目:git

Cirru Table Redo: https://github.com/Cirru/cirru-table-redo程序員

原本的目標是作一個實時預覽每一個值的解釋器的 Demo
從前作過兩個版本, 也是在微博記錄當中回憶才萌生念頭的:github

Cirru Live Editing: http://www.tudou.com/programs/view/SWKnhfmduos/
Cirru Table: http://www.tudou.com/programs/view/mHypUOnZSOI/編程

在 Live Editing 的例子裏, 我試驗了有一個全局 Mutable Scope,
而後代碼一遍渲染一遍會修改 Scope, 因而代碼同時會顯示每一個值.
當時的 commit 沒去找是哪個, 因此只能看不清晰的視頻了編程語言

Cirru Table 當中呢, 則是把解釋過程整個記錄而後用樹展現出來
效果對我本身來是是挺棒的, 只不過具體到程序, 不可能作到記錄所有執行過程
Chrome Profiler 當中 Flame Graph 有相似, 但恐怕也不會記錄所有數據
不過我以爲等硬件性能上去了卻是值得考慮下, 並且引入函數式編程的手法優化下
做爲概念演示, 已經足夠了, 我無論了, 只是想嘗試點別的函數式編程

失敗的目標

那麼我有新的想法了, 試試用新的辦法來演示, 好比說有這樣一段腳本:函數

cirrudefine (add x y) (+ x y)
define (main)
  print (add 1 2)

就像 Chris Granger 指出的, 抽象的變量是程序難以理解的緣由
由於你根本不知道變量裏邊是什麼, 只能一邊腦補一邊寫代碼, 錯了也不知道
那個人方案首先是程序執行的過程中應該把具體的數值顯示出來
就算寫 test case 也只是給某些特定數據吧, 不如直接在程序當中給:性能

cirrudefine:Builtin (add:Symbol x:1 y:2)
  +:Builtin x:1 y:2

爲了整套東西能運行, 我須要引入 suppose 函數, 寫上初始的變量
suppose 的做用, 是在開發時提供圖形化的數據, 而在實際運行時消失
那麼整個程序通過註釋, 文字版就是這樣的:學習

cirrusuppose:Built (add:Symbol 1:1 2:2)

define:Builtin (add:Symbol x:1 y:2)
  +:Builtin x:1 y:2

define:Builtin (main:Symbol)
  print:Builtin (add:Func 1:1 2:2)

基於這樣的思路, 拆分出來子問題能夠有這樣一些:優化

  • 須要有基本的解釋器, 好比 add 調用時直接能運行 (搞定 Demo)
  • 須要在渲染 DOM 時也能解釋, 寫另外一份解釋器 (思路理清, 沒搞定特例)
  • 須要搞定讀寫文件接口的數據模擬 (思路理清, 沒實現)
  • 須要考慮匿名函數的使用, 內部的數據怎樣模擬 (思路沒有理出來)

如今感受這個坑已經太大了, 目前能力遠遠不夠, 打算快點跳出來
固然我依然對此保持強烈的興趣, 也是我爲何失敗了還留筆記
若是有同窗對此感興趣繼續探索就有意思了.. 固然極可能失敗
前些天看到這句話, 能夠共勉一下:
http://weibo.com/1651843872/Cl1Cl2hKI

If you don't fail at least 90 percent of the time, you're not aiming high enough.
-- Alan Kay

Live Coding

關於怎樣讓編程更加簡單, 更加可靠, 社區已經投入了不少研究
特別是前面的 Chris Granger 的做品, 都是很發人深省的
他設計的 LightTable 當中就在多, 不過具體對應這裏的是:

Inline Evaluation: http://docs.lighttable.com/tutorials/full/#inline-evaluation

實際上我但願能有對更大的項目使用的方案, 單行的有點不夠
無論怎麼說 LightTable 跟 Swift 出如今我面前時仍是很正震驚的
大概由於我徹底不知道怎樣去實現吧.. Anyway, 之後會有更強大的

Bret Victor 在易學編程當中演示的就真的對圖形開發者很是有必要了
由於能清楚理解每一行程序發揮怎樣的做用的話, 對開發來講會清晰不少
具體看原文吧, 或者中文翻譯能夠的:

Learnable Programming: http://worrydream.com/LearnableProgramming/
(翻譯)易學編程: http://chengyichao.info/learnable-programming/

總之就是, 讓程序脫離抽象, 能讓開發者很是直觀地理解, 這很重要

腳本和靜態類型

中間有個思考, 就是: 程序越大, 越會有不少抽象機制, 也愈加難懂
首先數據的抽象, 過程的抽象, 在程序開發當中是相當重要的
其次纔是咱們要讓程序更好懂, 有不高的維護成本, 然而二者經常背道而馳
好比函數式編程 Monad 抽象程度很高, 理解起來極難

腳本語言計劃由於短小, 抽象不高, 但也所以常常出錯, 只能從 Log 調試
對於腳本語言我又這樣的一種理解, 就是腳本實際寫的是不出錯的狀況
就是說假設程序不會遇到奇怪的數據, 那麼先這樣, 再那麼, 應該就搞定了
而後寫着寫着發現有沒考慮到的, 加入判斷去處理一下. 強調下名字, 腳本.

在靜態類型的語句當中, 或者說須要顯示聲明類型的語言, 就不能這樣散漫
每個函數, 到須要考慮好類型, 怎樣處理各類數據的可能, 再鏈接到一塊兒
程序通過了類型檢查, 相比腳本語言來講出問題的狀況少得多
固然, 每一個函數都認真考慮, 提高質量的同時, 編寫的工做量也多了

這幾乎就是在便利和可靠二者之間作抉擇, 並且是徹底不一樣的目的
因此我想二者均可以看成是徹底不一樣的編程語言
有一天要設計程序的可視化的時候, 考慮下是否須要二者區分開來?

類型系統

這一段是後邊補上的, 我想起來還有一些關於類型系統的思緒

靜態類型系統語言, 我接觸的 Go, Haskell, 類型在開發當中都起到巨大的做用
在編程時, 類型是程序理解代碼的一步環節. 不須要執行就能發現錯誤
有些語言的 IDE 還能根據靜態類型給出方法和屬性提示,
這種提示, 有一點點像是 Live Coding 當中所指望的即時查看執行過程

固然, 將類型類比程序的執行, 類型是抽象的, 變量的值纔是具體的
不少具體場景, 只有弄明白具體的值, 以及運行過程, 才能理解程序
總體上我想說, 類型系統儘管抽象, 但也許也算一種將執行過程可視化的思路
又或者, 咱們想要的可視化, 也行並不老是經過以往常有的方式重現?

不可變數據的 name

中間試着玩的時候, 將來考慮渲染時狀態不被破破壞, 我嘗試考慮不可變數據
好比這樣一個解釋器, 會修改做用域當中兩個變量的數據,
若是渲染過程當中後邊的代碼修改了數據, 其餘用了變量的未位置是否收到影響?

cirrudefine (guess x y)
  set size 10
  set width 20
  + (* x size) (* y weight)

但是去掉修改做用域的函數 set, 問題來了, 而後如何定義變量呢?
後來想起了 Do Notation 當中手法, 經過函數做用域引入數據的 name,
具體就是個山寨(不全)的 bind 函數, 經過調用匿名函數來實現:

cirrudefine (guess x y)
  bind 10 $ \ (size)
    bind 20 $ \ (weight)
      + (* x size) (* y weight)

也是由於匿名函數的存在, 這個項目難度增長了, 匿名函數內部數據如何展現?
文本的代碼執行是很是抽象的, 雖然看起來只是傳入一個值, 實際卻不能那麼寫,
具體沒有考慮清楚. 不過 bind 的首發確實有意思, 之後還能用到

總結

可視化的編程方案對於開發者來講會很重要, 特別是界面愈來愈多的趨勢下
另外要吸引新人加入程序員的領域, 真的是要有足夠的誠意才行啊
我期待看國外牛人發佈新的方案去作執行過程的可視化, 本身作只是學習而已
至少理解了 bind 函數這一節, 幫我理解了 Haskell 當中有些地方

相關文章
相關標籤/搜索