CoderClark
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    2
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # A0002 見山是山,見山不是山,見山只是山 ## 寫程式如禪學 **「見山是山,見山不是山,見山只是山」**[^1],這是禪學領域知名的人生哲理,描述著人生會經歷的三個階段。其意思是,在人生年輕歷練尚淺時,看到山就是山,不會有太多的想法;當進入中年,有一定人生歷練的時候,看到山總是會有些不一樣的體悟出來,或許覺得壯闊、或許覺得莊嚴、或許覺得寧靜,端看山所帶給自己的感覺,而不是山本身;最後到了經歷更多的老年,在看透了許多事情後,看到山反而沒有之前的包袱,認為山就是山,沒有必要過度解讀。 [^1]: 《指月錄》卷二十八。青原惟信禪師曾對門人說:『老僧三十年前未參禪時,見山是山,見水是水。及至後來,親見知識,有個入處,見山不是山,見水不是水。而今得個休歇處,依前見山只是山,見水只是水。』。 這樣的人生三境界,在寫程式的領域也是如此。 ### 境界一:見山是山 初次接觸寫程式的時候,通常都是從語法開始學起,所以看到語法就是語法,也就是**見山是山**。比方說,當學到了 if、for、class、function 等等的語法,心中所想的是,需要判斷式就加入 if、需要批次處理就加入 for、需要將資料包起來就加入 class、需要打包一段程式碼就加入 function。**見山是山**,語法就是語法,任何語法使用起來都是直觀的。 ### 境界二:見山不是山 隨著寫程式的時間越來越長,不論是自己經驗的心得、還是前人提供的指導、或者書本撰寫的知識,對於語法的使用概念會越來越不單純。可能會有以下情境: * 得知「使用switch 比 if 有效率」,就開始覺得要把任何的 if 都替換成 switch。 * 得知「用泛型做 for 會更有通用性」,就開始覺得 for 都要寫成泛型。 * 得知「相關的觀念就一定要封裝」,就開始覺得不寫 class 罪大惡極。 * 得知「不包 function 難以複用程式碼、可讀性低」,就開始覺得包 function 才是正確的寫法。 自此語法不再是語法,都無形地被延伸概念所取代,**見山不是山**。從上述情境可以發現,這境界的程式設計人員有很重的包袱,可能是擔心違背了哪個程式觀念、也可能是對自己沒信心,導致在看到不錯的程式寫法或觀念之後,就拼命套用、彷彿非要用上一堆方法才是寫程式的正道。當寫程式就是套方法、套公式的話,產出的程式碼通常不直觀。由於是套用公式,通常從某些來角度看,水準會還不錯,可惜寫起來稍嫌不夠精準[^2];運氣不好的話,可能用得不恰當,反而把程式碼變得難以維護。 [^2]: 精準的程式碼,指的是易讀、易懂、易 trace,不殺雞用牛刀,不囉嗦地完成簡單程式碼。 ### 境界三:見山只是山 在經歷過許多的程式觀念、方法、公式的轟炸後,漸漸地回歸語法與觀念的本質,也就是**定義**。任何寫法都是在清楚定義、明白優缺點的前提下完成。心中所想的是,需要判斷式就加入 if、需要批量處理就加入 for、需要將資料包起來就加入 class、需要打包一段程式碼就加入 function。文字描述看起來與**見山是山**的境界沒有差別,但實際上要如何判斷「需要」卻是非常不同的。以 class 與 function 的例子來說,**見山只是山**的境界會很清楚要完成目標去包裝 function 或 class 的利與弊,判斷的準則都是從定義做起,然後**必要就去做、非必要就不去做**,而不是**見山是山**的**單純想到就去做**。 **見山只是山**的程式設計人員,對於語法與觀念的掌握度很高,所以處理問題的方法與工具會有很多,也因此總能產生很靈活的應對解決方案;各種精妙的程式碼,通常也是在這個境界才能寫出來的。這應該是最能享受寫程式的境界,不但思考的過程愉悅,完成程式後也頗具成就感。 ## Pointer 只是 Pointer 如果還是覺得這三個境界很抽象,沒關係,下面透過 C/C++ 的重要觀念, **Pointer** 來做說明。相信透過這個經典例子,可以更清楚寫程式的三個境界是什麼概念。 ### 境界一:見 Pointer 是 Pointer 剛接觸 Pointer 的時候,於定義上會學到「Pointer 的用途是儲存位址」;因此當書本或課堂範例提到位址,就會與 Pointer 做連結。這樣的連結,通常像是在背課文一樣,看到 ```int* p = &a;``` 就翻譯成 ```p``` 是 ```a``` 的位址。沒有什麼雜念,沒有什麼額外的想法,卻不知道應該在什麼地方使用。唯一可能使用的情境,就是當有些地方程式碼行為不如預期,像是想改變什麼值卻無效、或改變值卻造成 memory corruption,才會想到要調整 Pointer 的寫法試試。一個星號不對就用兩個,兩個星號還是不對,就再改寫法以避開 Pointer。由於很清楚 Pointer 的定義是儲存位址,所以**見 Pointer 是 Pointer**,只是可能不清楚怎麼使用,所以能免則免。 ### 境界二:見 Pointer 不是 Pointer 可是在 C/C++ 的領域要完全避開 Pointer 是非常困難的,很多情境都會需要用到。在不知道什麼時候該用,什麼時候不該用的狀況下,最常見的使用方式就是**套公式**。就像學生寫數學題目,很多時候不求甚解,只要題型與對應公式背好,考試就套公式,反正能拿高分就可以了。 下面舉幾個常見的 Pointer 使用公式:_Swap 交換兩個數值_、_Array 傳遞_、_額外的返回值_。當然,會使用到 Pointer 的公式不止於此,這裡提出 Pointer 初學最常見的案例來做說明。 #### Swap 交換兩個數值 ``` c++ void swap(int* a, int* b) { const int tmp = *a; *a = *b; *b = tmp; } ``` #### Array 傳遞 ``` c++ int sum(const int* p, unsigned int size) { int sum = 0; for(unsigned int i=0; i<size; ++i) { sum += p[i]; } return sum; } ``` #### 額外的返回值 ``` c++ void complex_mul(int a_re, int a_im, int b_re, int b_im, int* c_re, int* c_im) { *c_re = a_re * b_re - a_im * b_im; *c_im = a_re * b_im + a_im * b_re; } ``` 如果有寫過與 Pointer 相關的程式碼,肯定對這些公式不陌生,或多或少會用過這些公式。在**見 Pointer 不是 Pointer** 的境界,其實對 Pointer 如何使用還是不清楚的,但在遇到這些公式的情境,就會很自然地將對應的程式碼寫出來讓程式行為符合預期。就因為該怎麼使用 Pointer 還不是很熟,所以在學習過的公式之外,依然是不碰 Pointer 的。 ### 境界三:見 Pointer 只是 Pointer 進入到這個境界,使用 Pointer 並不拘泥於公式,僅針對定義「Pointer 的用途是儲存位址」就能發揮 Pointer 的各種效用了。或是用於通用介面、或是用於抽換 function、或是用於實現多型(Polymorphism)、或是用於隱藏實作等等。效用之多,不是隨意舉幾個例子就能概括的;各種靈活運用已經無法用套公式來辦到,而是在清楚定義的前提下,去建立自己想要的實作方案。一旦拋棄了公式的成見,就能**見 Pointer 只是 Pointer**,當用則用,不當用則不用。 ## 終能見山只是山? 如前面所說,當到達**見山只是山**的境界,不但寫程式的思考過程愉悅,能寫出精妙的程式碼,而且完成後的成就感極高。那是不是未達此境界的人,只要程式繼續寫下去、繼續練習就能達成呢?**答案是否定的**。人生可惜的就是不一定能**見山只是山**,可能終其一生都還是**見山不是山**,見到山都還是有想法、有感慨、有包袱,看不見山的本質。寫程式也是如此,許多人寫程式陷在套公式的泥沼裡,實作方案永遠都在找相似題與公式,沒有脫離套公式的時候。 為什麼會停滯在**見山不是山**的境界呢?主要是套公式之餘,沒有去思考公式的組成原理、也沒有去理解各個原理的定義、更沒有在套公式之餘問自己是否有更好的做法。長久下來,再也不問程式觀念的定義是什麼,反正程式能動就好,自然無法**見山只是山**。 其實停留在**見山不是山**的境界也不見得是糟糕的,畢竟每個人的理想與目標不同,非得在寫程式的旅程上追求最高境界是不合理的。倘若工作不需要、或者目的不需要,即使寫程式停留在最初的**見山是山**又如何?應該要看自己的需要,再來追求應該要達到什麼境界。 ## 見山只是山 那要如何才能邁向**見山只是山**的境界呢?下面分享幾個具體訣竅: * **追本溯源**:當接觸到新的程式觀念,不要只是將範例當公式使用,而是要釐清根本定義;縱使定義可能不容易理解,也可以先記起來。將來有機會再接觸到的時候,嘗試用定義思考、解讀,就會有豁然開朗的一天。 * **他山之石**:當看到別人優秀的程式碼,如果認識作者,可以請教作者這樣設計的理由;如果不認識,可以嘗試解讀,或者思考是否有更好的寫法。只有弄清楚為什麼要這樣寫、為什麼有(或沒有)更好的寫法,才能將好的方法內化成自己的技術。 * **百尺竿頭**:當自己完成一份程式碼,不要只滿足於完成的當下,永遠都要思考有沒有更好的實作方案。如果自己知道有,盡可能抽空練習將程式碼改進;如果自己不確定有沒有,也可以請親朋好友幫忙做程式碼審查(Code Review),不論審查結果如何,都能透過討論、接收更多不同的觀點,以豐富自己的知識庫。 條條大路通羅馬,其實要讓自己往下一個境界邁進的方法有很多,並不限於上述的訣竅,這裡僅就經驗提供作參考。只要有心要讓自己進步,不要一直覺得自己已經很厲害了、不要拒絕接收更多知識、不要拒絕檢討自己、**不要成天只想著程式能動就好**,總會有達到**見山只是山**的時候!

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully