琴子 LilyPond Guile 入門

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

寫在前面

LilyPond Guile 很難學,而且用途很窄,脫離了 LilyPond 就沒什麼用。在開始之前,請先給自己打個預防針:

  • 語言門檻高:Guile / Scheme 屬於 Lisp 家族,其函數式語法與常見的 Python 或 C 語言截然不同,本來就比較難上手。
  • 文件不完整:LilyPond 官方並未完全公開內部的 Guile API,查不到資料、像在盲操黑盒子都是正常的。
  • 非必學功能:平常排版完全不需要懂 Guile。它屬於進階擴充功能,不會寫絲毫不影響你製作精美的樂譜。

站在巨人的肩膀上

其實很少人會從頭編寫 Guile 程式碼。建議直接去開源社群尋找現成範例修改:

寫不出來是正常的,千萬不要灰心。

Hello World

\version "2.24.3"

#(display "Hello World\n")

透過終端機執行:

$ lilypond -s program.ly
Hello World

範例說明

  • -s 參數的作用:此參數能隱藏 LilyPond 預設的編譯進度與雜訊,讓自訂的 Scheme 輸出結果在終端機中清晰呈現。
  • 現階段只要確認環境能成功印出這行字串即可,不需要急著往深處鑽研。

如何學習 Guile?

如果想深入,可以到 Guile 的官方網站了解。但老話一句:看不懂非常正常。

這門語言本身極為小眾,多數軟體工程師都不曾接觸。更核心的問題是,Guile 官方並沒有提供正式的 Windows 原生版本,主要活躍於 GNU/Linux 環境。

此外,LilyPond 內嵌的 Guile 其實是閹割版。為了幫程式瘦身、提高執行效率,官方拿掉了許多不必要的函數。畢竟它在 LilyPond 裡的核心任務只有排版樂譜,本來就沒打算當成通用型程式語言來使用,自然不需要那些多餘的功能。

如何看官方 API?

既然官方文件查不到,最直接的方法就是直接看 LilyPond 的底層原始碼。

  1. 尋找目錄:前往你的 LilyPond 安裝目錄。
  2. 尋找檔案:尋找特定目錄底下的 .scm 檔案。
    • share/guile/version/scm/ 是 Guile 的 API
    • share/lilypond/version/scm/ 是 LilyPond 的 API
  3. 閱讀工具:強烈建議使用 VS Code 等程式編輯器開啟整個資料夾,利用全域搜尋(Ctrl+F)功能來追蹤與閱讀 API 邏輯。

在 VS Code 的搜尋中,找 (define-public ,就可以找到公開 API。define-public 是 Guile 的語法,用在定義變數、函式等項目後將其公開在模組中。

範例

開啟 REPL 模式

在終端機輸入以下指令:

$ lilypond -e "(begin (use-modules (system repl repl)) (start-repl))"

經實測,這不是一個可用的 REPL,連 (exit) 指令都沒有。這是因為內嵌的 Guile 不是完整版,拿掉了許多功能。

顥示目前系統時間

\version "2.24.3"

#(display
   (strftime "%Y-%m-%d %I:%M:%S %p"
     (localtime (current-time))))
#(newline)

印出系統支援的 MIDI 樂器

\version "2.24.3"

#(map
   (lambda (pair)
     (begin
       (display (car pair))
       (newline)))
   instrument-names-alist)

後記

琴子後來並沒有堅持在 LilyPond Guile 的路上死磕。畢竟改用主流程式語言的繪圖函式庫,只要多花點心思慢慢微調、對齊距離,一樣能畫出理想的圖表。回頭想想,把大把青春耗在解開這個排版黑盒子上面,投資報酬率實在不怎麼高。

關於作者

琴子為資訊碩士與音樂愛好者,音樂學習始於大學國樂社,曾彈奏古箏、中阮,偶爾參與中國打擊樂演出。出社會後持續接觸多種樂器,包含中阮、吉他、烏克麗麗與鋼琴。

除了對音樂的持續探索,琴子喜歡黑咖啡與日本料理,會簡單的日文,興趣包含閱讀與自助旅行。