[{"content":"星期六下午帶著小孩理髮，理髮店電視播放著 T 台政論節目，節目中播放立法院的錄影畫面，畫面中沈伯洋叫國民黨的人不要拉他，而他正要去阻止韓國瑜進議場。與會來賓大抵就是要說沈干擾議事秩序或沒禮貌（？）根本不是暖男啊！這位來賓對著畫面滔滔不絕，時而得意大笑，似乎對於自己的表現相當滿意。\n不禮貌、爆粗口、破壞秩序的人，怎麼能做好市政呢？\n當然，在這個平行時空裡，體型壯碩的沈伯洋沒有在主席台附近被人搥打內臟和從空中拋落。\n拿立院裡的「物理」攻防來攻擊候選人這類把人貼上激進派標籤的策略，很老套卻很有效。百姓希望安定，誰都不希望選出一個激進份子。但看到選舉不能聚焦在政策討論上，還是覺得可惜。\n百無聊賴，改讀起手上的書。上個禮拜還在想，奇怪怎麼台北選戰打這麼久了國民黨還沒有拿抄襲、桃色新聞或是弊案來打泥巴戰，結果當晚就來了。\n中間的事大家都知道了，雖然認知可能完全相反。\n個人閱讀沈伯洋《柯震東震出我國毒品政策的爛瘡》一文後，認為有幾處遣詞用字確實可以再溫和一些，對大眾來說陌生的觀念也可以不厭其煩的為讀者下註解。但是要把這篇批評政策的文章講成沈「支持社區供毒」和「毒品合法化」（還很刻意的販毒和吸毒兩件事混為一談），就真的是充滿惡意了。\n我指的不只是對一線醫護人員的努力的抹煞，更是對社會和諧和進步，充滿惡意。\n這是一個多麼好的政策討論機會。蔣團隊乃至整個國民黨，可以挑戰、可以質疑、甚至可以罵其不切實際、窒礙難行，有眾多的面向可以帶動討論，但最終還是選擇去脈絡化的，把不是對方的主張硬戴到他頭上。\n引起反彈後，只要再戴一次帽子，幾十萬的留言在保守派的眼裡便又成為網軍和機器人的惡意攻擊，就算其中有許多專業的分析討論，上位者一旦定調，也只能牢牢的被鎖在各自的同溫牢籠裡。\n我不知道這算盤打得精不精：激起多數醫護的反感，但鞏固保守派的票源，催動保守派為維護社會安定而出來投票，一來一回，說不定還真的划算。如果接下來民調沒有出現交叉，到年底的選戰基調大概就是專打這題了。\n但不論誰當選，我們都永久喪失這次公共政策討論的機會了。我們還有多少社會議題須要好好討論？受刑人權利、安樂死、死刑\u0026hellip;這些複雜的議題不該永遠不被理解和深刻探討，更不該被拿來當作操弄輿情的工具。政治人物來來去去，都是一時的，如果追尋大位的過程中不促進台灣社會的融合和演進，台灣又怎麼能夠長治久安下去呢？\n","date":"2026-10-06T00:00:00Z","permalink":"/posts/taipei-election-thought/","title":"台北市選舉感想"},{"content":"野狼今早過世了。\n當初牠趁我等紅燈之際從路邊竄出來躲到機車踏板下，車身動彈不得的情況下只能把牠撿起來。從沒有看過這麼小的貓，稍後給醫生檢查後才知道牠出生還未滿一個月，看起來沒了爸媽，甚至不知道要躲避人類。覺得有緣，當下決定由幾個朋友出資共同撫養，安置在我的住處。從診所回家後牠住進臨時的紙箱，迅速的吃完罐頭，也很快就找到貓砂大便，適應得很好。\n可能是因為從小養起，也可能是沒有爸媽教，據養貓的朋友說，野狼超級溫馴。我只知道牠從來不咬人，最多就張口含著作勢要咬下，也不抓人或抓家具。牠也很好哄，下午曬曬太陽，或者搔搔下巴就會呼嚕呼嚕。\n畢業搬回家後，就如網路上的梗圖描繪的，本來爸媽不想要家裡有寵物，結果帶回去沒幾天，大家吸貓吸得比我還勤。其中又以我妹妹最為疼愛牠，房間也讓牠自由進出，有小孩後我找牠的頻率降低很多，還好照看牠的人變多，不致寂寞，雖然牠可能也不會感到寂寞就是了。\n中間經歷過因環境變動而到處撒尿的不安時期，胃裡積了太多貓毛而嘔吐，和最麻煩的貓癬，還好，走的時候至少看起來是無病無痛，只是不吃不喝並迅速的衰退，最後悄悄的離開。十八個年頭，換算成人的歲數也是人瑞了，我雖難過，卻也為牠健康的活了這麼久，並走得順遂而感到開心。\n謹以此文告知曾經撫養或認識野狼的朋友們。\n","date":"2025-10-22T00:00:00Z","image":"https://image.sharefun.dev/21%201.jpg","permalink":"/posts/bye-bye-wild-wolf/","title":"野狼掰掰"},{"content":"忙裡偷閒，趁著連假開始前，來浸沐在威廉透納的光裡。\n老婆個性隨和而且能自得其樂。被我硬拖過來，本來興趣缺缺的，逛了一陣子後竟也開始跟我分享心得，並驚喜的發現她最愛的那一幅也是公認最好的那幅。\n小時候畫畫只會工筆，一直到成年後看了畢沙羅的展，才知道景物入畫，是可以透過那迷人的光影來呈現的，從此便愛上印象派。\n最近也重新拾起筆來寫字，並嘗試各種可能性。就像繪畫從寫實邁向抽象，在手機電腦如此普及的現在，手寫字的主要目的已不再是傳遞訊息或感情，而應是傳達美感。\n","date":"2025-10-10T00:00:00Z","permalink":"/posts/turner-echoes-of-sublime-works-from-tates-collection/","title":"威廉透納特展"},{"content":"In OpenWRT, all config files under /etc/config are generated dynamically. There are scripts in /etc/uci-defaults to construct this configuration.\nThe scripts in /etc/uci-defaults are executed on first boot and then removed.\nAlthough the scripts are removed on first boot, we could still find them in the image. For example, if you\u0026rsquo;re using an imagebuilder to build the image, once you built, under imagebuilder root, build_dir/target-aarch64_cortex-a72_musl/root-bcm27xx/ are the rootfs of bcm27xx targets, and the sub-directory /etc/uci-defaults is what we are looking for.\n10_migrate-shadow 14_migrate-dhcp-release 50-dnsmasq-migrate-resolv-conf-auto.sh 12_network-generate-ula 15_odhcpd 90-resize-filesystem-to-partition-size 13_fix-group-user 20_migrate-feeds 99-override-network-proto-lan-to-dhcp The content of 12_network-generate-ula is\n[ \u0026#34;$(uci -q get network.globals.ula_prefix)\u0026#34; != \u0026#34;auto\u0026#34; ] \u0026amp;\u0026amp; exit 0 r1=$(dd if=/dev/urandom bs=1 count=1 |hexdump -e \u0026#39;1/1 \u0026#34;%02x\u0026#34;\u0026#39;) r2=$(dd if=/dev/urandom bs=2 count=1 |hexdump -e \u0026#39;2/1 \u0026#34;%02x\u0026#34;\u0026#39;) r3=$(dd if=/dev/urandom bs=2 count=1 |hexdump -e \u0026#39;2/1 \u0026#34;%02x\u0026#34;\u0026#39;) uci -q batch \u0026lt;\u0026lt;-EOF \u0026gt;/dev/null set network.globals.ula_prefix=fd$r1:$r2:$r3::/48 commit network EOF exit 0 If we want to change this default configuration, just add another uci-defaults script with larger number in the filename, i.e. 00_customize_network_setting.\nSometimes we want to use built-in scripts to save our time of writing the script using raw UCI commands. There are functions in build_dir/target-aarch64_cortex-a72_musl/root-bcm27xx/lib/functions/ to provide such functionality. For example, there is network.sh which defines some functions to make the scripting more easily.\n","date":"2024-02-22T00:00:00Z","permalink":"/posts/openwrt-config-generation/","title":"OpenWRT Config Generation"},{"content":"I\u0026rsquo;m using Ubuntu for my everyday work. Recently, I have some tasks relating SELinux. Unfortunately, SELinux is by default not enabled in Ubuntu, and the ecosystem is not as full as it in Fedora.\nIn this article, I wrote down the steps to setup an Fedora VM via Virtual Maching Manager, and using ssh to login Fedora.\nInstall Virtual Machine Manager sudo apt-get install virt-manager Download the Fedora Workstation ISO I\u0026rsquo;m using Fedora 38. Download from the official site or simple using the command below.\nwget https://download.fedoraproject.org/pub/fedora/linux/releases/38/Workstation/x86_64/iso/Fedora-Workstation-Live-x86_64-38-1.6.iso Create Fedora VM and Install Click \u0026ldquo;Create a new virtual machin\u0026rdquo;.\nClick \u0026ldquo;Forward\u0026rdquo;.\nFollow the steps below to select the Fedora ISO we just downloaded.\nSet proper memory and CPU and disk size.\nSet the name of the VM, click \u0026ldquo;Finish\u0026rdquo;.\nNow the boot process starts. We firstly boot from the ISO and then install to the disk.\nInstall Fedora. The installation destination is not set. Click \u0026ldquo;Installation Destination\u0026rdquo; to set.\nDouble click the only disk in \u0026ldquo;Local Standard Disks\u0026rdquo;, which is created for us in the VM creation steps, then click \u0026ldquo;Done\u0026rdquo;. Then click \u0026ldquo;Begin Installation\u0026rdquo;.\nAfter installation is done and reboot, we can boot from the disk.\nAfter reboot and login, open \u0026ldquo;Terminal\u0026rdquo; app. Then go to the next section.\nSetup ssh login Since openssh-server is already installed by default, we could simply enable it.\n# Guest terminal systemctl enable sshd systemctl start sshd Copy public key from host.\n# Host terminal cat ~/.ssh/id_rsa.pub Paste the output to the guest machine.\n# Guest terminal mkdir -p ~/.ssh # Paste the output to ~/.ssh/authorized_keys Obtain guest\u0026rsquo;s IP address\n# Guest terminal ifconfig | grep 192 \u0026gt; 192.168.123.25 Login guest from host.\nssh \u0026lt;username\u0026gt;@192.168.123.25 ","date":"2023-10-06T00:00:00Z","permalink":"/posts/setup-fedora-vm-using-virtual-machine-manager/","title":"Setup Fedora VM Using Virtual Machine Manager"},{"content":"讀者：葉學舫\n作者黃文局先生是身懷絕藝的江湖高手，在紐約經商四十年終成一方之雄，也是個飽讀中外文史，進而關懷國家興衰的世外異人，跨海資助近代的政治人物和活動，又從不露形跡於幕前。累積巨富後回台的他仿效猶太人，先後在美、台創辦全球台灣研究中心 (Global Taiwan Institute, GTI) 與台灣勵志協會 (Taiwan Inspiration Association, TIA)，向美國政界及學界發聲，並幫助本土政權茁壯。\n以史為基，以錢為盾，如今更以筆為刀，黃文局先生將其畢生江湖「撇步」撰於書中傳予年輕人，盼後者經過幾代的茁壯後，引領住在台灣這塊土地的人民邁向自決建國一途。\n展讀此書之際，作者在我心中的形象使我數次想起十多年前在柬埔寨與一位台商相遇的經歷。\n兩位 Peter 與金邊台商 十多年前，在研究所畢業後的幾個月空窗期，友人邀請我到東南亞旅行，並在柬埔寨的偏鄉做短期志工，我們先後在 The Cambodian Dormitory and Education Project (CDEP) 帶科學實驗，及在 Cambodia-Taiwan Education Program (CTEP) 從事電腦教學工作。\nCDEP 是美國人 Peter 創辦的 NGO 的計畫，目的是改善柬埔寨的急救和照護系統，我們在其轄下的西哈努克省偏鄉裡的 Graphis Health Center (GHC) 工作，帶鄰近區域的小學生做科學實驗。順道一提，GHC 是由 台灣寶島行善義工團 出資、出力、托運建材，花幾年的時間分批建成的。\nCTEP 的創辦人也叫 Peter，侯先生，台灣人。CTEP 的任務是在吳哥一帶提供無償的短期電腦補習班（修業期滿即可退全額學費），藉以提昇當地居民收入。我們在 CDEP 的期間侯先生曾來訪 GHC 一次，並向我們述及早我們幾年來到 GHC 拓荒的前輩志工的故事。\n原本的計畫是只有在 CDEP/GHC 一地服務的，但後來我們因為一些因素想盡早結束在 GHC 的工作。提早離開 GHC 既是意外之舉，舉目無親的兩人只得加緊思索剩餘的日子要如何度過。身上的現金不足以讓我們天天住飯店、吃外食，住在 GHC 外的鐵篷和每日供餐是出國前就繳清的，停留在 GHC 雖沒有額外開銷，我們仍不願逗留。無奈之下試著聯絡 CTEP 的侯先生討論收留我們的可行性，幾次信件往來洽談好轉移的日子，卻還有一個多禮拜。最後，受一位金邊台商的幫忙，暫住他家一週，才度過這個危機。\n我們為什麼會認識該台商並受其援助？因為他隔三差五就往 GHC 跑，看看有沒有台灣人進駐，是否有需要幫忙的地方，來的時候帶水、帶糧食（那時一罐維力炸醬就是人間極品），共襄義舉。\n要知道，從金邊到 GHC 有 125 km，連接兩地的四號公路路況可不像台灣的國道或省道，只有單線道，道路兩旁不是黃土、草原就是河塘。時值九月雨季，上午一貫是晴空萬里，整片天空找不到一朵雲可躲避豔陽，午飯過後，烏雲立時匯聚，轉眼大雨滂沱，雷鳴時而狂嘯時而低吼，直至傍晚才又嘎然放晴。在此氣候與路況下騎著摩托車往返怎麼看都是一件苦差事，他卻毫不在意。第一次來找我們的時候撲了空，隔週再訪才見到我們。\n金邊台商的人生軌跡曲折，又博古通今，與我這種過單調人生的無聊讀書人不同。他與我們暢談自己過去的商場經歷和台灣歷史，就如同李前總統與作者面談，幾乎都是他自顧自的說話，不時又話鋒一轉，引用起四書裡的章句，闡述待人處事之道。他口中的江湖，是我成長過程中從未涉入的世界，我自是聽得興味盎然。\n他總稱自己是「天公仔囝」，感恩每個際遇，我卻覺得那些所謂「好運」是源自於他未滿五十而樂天知命的智慧，使他總是以富足的眼光看待不論好的、壞的所有事件。他熱心的帶我們見他的台商朋友，有家藏書五千多本的，有開計程車發達後不棄糟糠之妻的，至於沒緣得見的，就用說的給我們聽。\n他幫助人有一套哲理：只幫心存善念之人，不助心術不正之輩。有次他買光一位花束小販的某款花束，只為感謝那小販在暴雨下混亂的交通中義務引導車流讓他得以提早回家。然而幾次光顧後，小販刻意增加該款花束的數量，後來他就不再購買了。這助人惟德的道理看似直覺，沒什麼高深之處，我卻覺得如果沒有精準的看人眼光，往往錯幫了人而不自知，反受其累。即便如作者慧眼獨具，仍然多次遭親信背叛，遑論凡人如我。遠的不說，看看乘著 318 學運之勢躋身政壇的幾個政治人物今日的樣貌，就足以使我對「曾經相信他們」這事感到羞愧不已。\n行善需以永續為目標 回到下榻金邊的那個傍晚。狼狽的兩人扛著行李抵達時已經身心俱疲，沒有對台商說明離早離開 GHC 的原因，但他雙眼似乎能直視人心，撫慰了我們受傷的心靈。\n在 GHC 一帶，乃至大部分的柬埔寨偏鄉都存在一個問題：教育無法持續。因為各級政府層層貪污，最下游的老師實際能領到的薪水極少，迫使他們必須出外打零工，十堂課就有三、四堂不在。學生有時需要照顧弟妹，或乾脆將其帶來學校，遇到農忙也就跟著下田而不進學校。我曾隨長庚義診團參訪學生們的家，茅草屋頂甚至不能遮雨，衛生條件極差。\n我們終於了解到，那偏鄉的住民現在需要的是 GHC 提供的醫療和衛教，和可以維持生存的基本收入，而不是我們帶來的自然科學實驗和英文教育，或是我朋友建置的圖書館管理系統。也許他們終有一天會用到，但不是那時候。意識到那個地方不會因為我們的造訪而有任何改變後，我們便亟欲離開。\n行善，也需要企業經營的思維，設立目標，訂定計畫，確實執行，在對的時間投入對的資源，並以永續經營為目標。如果我能提昇自身的力量，運營一個可以自足的機構，不靠捐贈和募款，能否將事情做得不一樣？即使如今我已右傾，終日汲汲營營，當年那些刻在靈魂裡的對話，仍不時在午夜裡呼喚著。\n韓國人的團結 除了猶太人，作者在書中數次提到韓國人，講述其 All or None 的烈性、對台灣人「窩囊」的觀點，但最令我印象深刻的，應該還是韓國人的堅韌團結。\nCTEP 的侯先生對我們說，做善事這件事，「韓國人高調，日本人低調，台灣人沒調。」私解為韓國人做善事，必定敲鑼打鼓，深怕其他國家不知道；日本人為善不欲人知，刻意不露鋒芒，但求實效；台灣人行善，卻不問成效，當耗費大量的金錢、人力而成效不如預期時，還會用「我們已經盡力了，改變本來就不容易」或者「比起受我們幫助的人，我們其實獲得的更多」來安慰自己。想好好宣傳卻不得要領，明明是可以提高國際形象、增進兩國民間友誼的善舉，做了半天卻沒人知曉。\n金邊台商也曾提及韓國人的團結一事。彼時金邊證券業正要起步，他也參與其中，似乎一開始是先行者，但後到的韓國人制肘其事業的手段使其頗為頭痛。\n中國汶川地震、日本 311 地震，台灣人的捐款額在國際上都是數一數二的高。台灣人很樂意幫助他人，同情心可以用氾濫成災來形容，但相比日、韓，不論在大局觀或是組織能力都略遜一籌，猶如散兵，難生綜效。\n台灣人沒有在做善事嗎？ 作者曾說台灣人沒有公益觀念，這可能略失公允。\n可惜的是，台灣人除了賺錢以外，很少人想過死後要替社會留下什麼？沒有公益觀念，國家意識薄弱，除了想到自己，還是自己。即使這十幾二十年來，名震天下的輝達 NVIDIA、超微 AMD、台灣國際航電 GARMIN 等高科技公司的創辦人或執行長，他們都已成巨富，也都是出生在台灣的「正港」台灣人，可曾聽過他們捐款支助台灣？或為台灣發聲？\n台灣人，自私的很多，但無私奉獻的也不少，不然不會有前段提到的賑災成績。\n往大的說，台積電創辦人張忠謀先生多次代表出席 APEC，奇美創辦人許文龍先生建立奇美博物館，聯電創辦人曹興誠先生近年捐款充實民間武裝，都是台灣人幫助台灣的實例。（以其財力和人脈是否可以做得更多是另一層面的事。）\n往小的看，台灣寶島行善義工團為受災戶蓋屋，侯先生在吳哥辦學，金邊台商協助台人克服在異地的種種困難，也都是善舉。\n我認為作者想表達的應該是：行善的人雖多，但有真正有力量、有意識、有組織的增進台灣國力，乃至推動自決建國的人物還是太少。這才是作者真正期許台灣人仿效猶太人的地方。一如《百年追求》序言「和其他民族相較，臺灣的民主運動並不特別壯烈，不特別曲折，也不特別艱難」，因此轉型正義始終未能落實；台灣人沒有經歷亡國的悲痛，所以沒有踏上建國道路的堅毅決心。\n我們是可以選擇的，不用等走到那一步才來懊悔。\n本書缺憾 也許是出版社為了增加目標客群而降低政治敏感度，也可能是為下一本書做準備，作者與台灣政治人物互動的文章皆未收錄。我說可惜，是因為如果只看《大局》而不讀如 憶李登輝和蔡英文 和給 李應元的悼文 等文，雖能領略作者一心只願國家強盛的心情，卻錯過其仗義疏財的實際作為，作者的生命厚度不免被削薄了幾分。所幸 上報 可讀到這些文章，期待作者可以將與台灣政壇的互動故事集結成冊，那將會是很珍貴的政壇紀實。\n","date":"2023-05-30T00:00:00Z","permalink":"/posts/big-picture/","title":"讀《大局》，兼憶金邊台商與我的緣份"},{"content":"\n十月和十一月，帶著小方舟體驗農事。誠然對真正的農夫來說那遠遠算不上農事，但對都市家長如我來說，已經可滿足帶小孩認識世界各種樣貌的目的。為什麼我這樣認定？因為每次結束，小方舟總是嚷著要再參加類似的活動。\n小方舟固然驚異於那些初次親見的、體驗的事物，陪伴過程也拓展了對世界認識甚少的我的視野。\n方知龜山平地竟有小葉種茶業，茶的滋味不差（我不懂茶，但我老婆是行家），以之製成茶凍，清涼甘甜。\n方知除了課本上常見的樹枝般竹節蟲只是竹節蟲家族的一種，家族中甚至有長度可及成人小臂的成員。\n方知不必遠赴南庄，距我家車程半小時內，就能看到（仍在使用中的）洗衫坑。\n選擇的農事活動取近和便宜為主，足跡僅止於桃園和苗栗，價格在 500 以內。\n苗栗的薑麻節，議員、鄉長在市集旁搭了棚子和講台，宣講政績的聲音透過大型音箱直接蓋過正在為我解說薑黃染布步驟的老師，老師指這是拿政府錢辦的活動。\n桃園的龜山青農力和卿卿百果園個別陪我們做半天的活動。「只收 350 根本連材料費都不夠吧？」主人輕描淡寫：「政府鼓勵青年從事農業，有補助。」活動期間沒有半個政府官員出現搶主人的風采。只有一次，七、八輛機車的里長競選車隊駛入百果園，跟園長拜票。噓寒問暖，其實更像是鄰居在問「食飽未」。\n","date":"2022-12-01T00:00:00Z","permalink":"/posts/agriculture/","title":"農事體驗"},{"content":"The CPython interpreter usese GIL (global interpreter lock), to prevent threads from executing Python bytecodes at once.\nSuppose I have two components who need to be run in parallel in a modern multi-core processor. Say, add and mul:\ndef add(n: int) -\u0026gt; int: result = 0 for i in range(n): result += (i + 1) return result def mul(n: int) -\u0026gt; None: # Run many times to get longer execution period for x in range(4000000): result = 1 for i in range(n): result *= (i + 1) return result Impose that these two tiny components have to be run sequentially, mul receives add\u0026rsquo;s output.\nsequenceDiagram participant main participant mul participant add main-\u003e\u003emul: For every stdin activate main mul-\u003e\u003eadd: result add-\u003e\u003emul: mul-\u003e\u003emain: deactivate mainRun it twice and fix the input of mul to be 11 for demonstration purpose. Note here I print the time log to the standard error on purpose. The code is listed below.\nSingle Thread Version for i in range(2): x = mul(11) y = add(x) Run it!\n\u0026gt; time python3 0_single_thread.py Time cost for mul 2.4840409755706787 Time cost for add 2.594242811203003 Time cost for mul 2.5620434284210205 Time cost for add 2.4484610557556152 python3 0_single_thread.py 9.81s user 0.01s system 97% cpu 10.111 total Both of the two components cost about 2.5 s. (Since I choose the parameter 11 and the magic number 4000000.) The time needed for each iteration becomes long. Besides, while computing one of the components, the other cannot do any computation. The total time for finishing the loop on my machine should be around (2.5 + 2.5) * 2 = 10 s, and I got 11.111 s.\nMult-thread Version To assure the above sequence, I use Queue for messaging from main thread to t1 (the mul_with_time thread) and t2 (the add_with_time thread).\nThe main thread put 11 into q1, the mul_with_time pop the q1 and do computation and put its result to q2, the add_with_time pop q2 and do computation.\ndef mul_with_time(q1: Queue, q2: Queue) -\u0026gt; int: round = 0 while True and round \u0026lt; 2: n = q1.get() q2.put(mul(n)) round += 1 def add_with_time(q: Queue) -\u0026gt; int: round = 0 while True and round \u0026lt; 2: n = q.get() add(n) round += 1 if __name__ == \u0026#39;__main__\u0026#39;: q1 = Queue() q2 = Queue() t1 = Thread(target=mul_with_time, args=(q1, q2), daemon=True) t2 = Thread(target=add_with_time, args=(q2,), daemon=True) t1.start() t2.start() for i in range(2): q1.put(11) t1.join() t2.join() time python3 1_multi_thread.py Time cost for mul 2.5354559421539307 Time cost for mul 6.187425374984741 Time cost for mul 6.396909475326538 Time cost for mul 2.273833990097046 python3 1_multi_thread.py 11.17s user 0.02s system 99% cpu 11.228 total The total time got even longer! The second round mul_with_time and the first round add_with_time are 2.5x because these two threads runs simultaneously. Since there is a GIL, only one of them is actually executed at any given moment. And since there is a context switch when transit from one thread to the other, the time for both threads should be more than 2.5 + 2.5 = 5 s.\nThis multi-thread version is a good practice since I have isolated the two components, this architecture makes it possible to execute them concurrently (not parallel).\nMulti-process Version Spawning sub-processes for both components can readily avoid them from blocking each other. Simply replace multithreading.Thread by multiprocessing.Process and queue.Queue by multiprocessing.Queue will turn this script from multi-thread version to multi-process version.\ntime python3 2_multi_process.py Time cost for mul 2.4805655479431152 Time cost for mul 2.2870962619781494 Time cost for mul 2.4712436199188232 Time cost for mul 2.320164918899536 python3 2_multi_process.py 9.58s user 0.02s system 131% cpu 7.313 total This time no heavy context switches are present. Each sub-process holds its own GIL and blocks no one. First round add_with_time and second round mul_with_time are executed in parallel, i.e. both of them are actually running at a given moment. The total time should be 2.5 + 2.5 + 2.5 = 7.5 s.\nMulti-process with shell The work is done. But when I staring at the 2_multi_process.py script, I found that although mul_with_time and add_with_time are well separated, there are many fancy stuff in my main function. For example, Process and Queue are objects that may make other programmers confused at first glance, they are not what I really concern and are not necessary actually.\nProcess can be replaced by shell, and Queue can be replaced by pipeline |. Pipe first component\u0026rsquo;s standard output to second component\u0026rsquo;s standard input will make it.\n3_mp_mul.py\nfor i in range(2): print(mul(11), flush=True) 3_mp_add.py\nwhile True and round \u0026lt; 2: stdin = sys.stdin.readline().rstrip() if (stdin == \u0026#39;\u0026#39;): continue else: result = add(int(stdin)) round += 1 Now the two components are even more isolated. In this version, each script is just a main function which listen to the standard input, do single component and then print something to its standard output. (Yes, you can change the first script so that it can listen to standard input too.)\nAnd I get the same performance as the previous version.\ntime (python3 3_mp_mul.py | python3 3_mp_add.py) Time cost for mul 2.516085386276245 Time cost for add 2.300935745239258 Time cost for mul 2.5419352054595947 Time cost for add 2.2685813903808594 ( python3 3_mp_mul.py | python3 3_mp_add.py; ) 9.64s user 0.02s system 131% cpu 7.349 total The parenthesis that enclosing two Python processes is to create a shell sub-process so that the total time of this sub-process (which creates two processes) can be recorded.\nImagining that you and your teammates are developing a series of algorithm like sum and add which have to be run sequentially and the output of the former is the input of the latter, this architecture frees you from interference each other. You can develop, test your own component, you can also combine it with other components by a pipeline. Neat, right?\nYou can downlaod these scripts and run it yourself.\n","date":"2022-04-22T00:00:00Z","permalink":"/posts/a-minimal-example-of-concurrent-python/","title":"A Minimal Example of Concurrent Python"},{"content":"這是一篇學習 UML class diagram 的簡記。為保持文意清晰，用到術語時盡可能使用原文表示。\nDependency（依賴） 定義：影響為單向。如 A 的變化不影響 B，B 的變化會影響 A，則 A 依賴 B。 圖例：虛線連結，單向箭頭，由依賴方指向被依賴方。 classDiagram ClassA ..\u003e ClassB UML syntax classDiagram ClassA ..\u0026gt; ClassB 依賴關係是比較廣泛的描述，如下面的 Inheritance 和 Asscociation 也可以視為一種 Dependency，只是將這些比較常見且重要的依賴形式獨立出來便於使用。 Association 定義：廣義來說，Association 是包含 Aggregation 和 Composition 的，後二者是一種特化。若 A 與 B 之間可獨立存在，若 A 對 B 有存取權，則 A asscociates with B。Association 可以是雙向的。 圖例：實線連結，箭頭從擁有者指向被擁有者。雙向連結時省略箭頭。 classDiagram ClassA \"1\" --\u003e \"*\" ClassB ClassC \"*\" --\u003e \"1\" ClassD ClassE -- ClassF UML syntax classDiagram ClassA \u0026#34;1\u0026#34; --\u0026gt; \u0026#34;*\u0026#34; ClassB ClassC \u0026#34;*\u0026#34; --\u0026gt; \u0026#34;1\u0026#34; ClassD ClassE -- ClassF 與 Aggregation, Composition 的相異處在於，Association 的類之間可以是對等的，也可以是從屬關係。習慣上我會直接將具有從屬關係的類用 Aggregation 或 Composition 表示，將對等關係的類保留給 Association。 實例：一部汽車可以有一至多個 USB 風扇。電腦也可以有一至多個 USB 風扇。USB 風扇本身也可以單獨存在，甚至插到其他提供 USB 的插座上。 classDiagram 汽車 \"1\" --\u003e \"*\" USB 風扇 電腦 \"1\" --\u003e \"*\" USB 風扇Aggregation 定義：表示 A 與 B 有從屬（主體與附屬）關係。若 A 包含 B，但 B 可以被共享，則 A aggreates B。 圖例：實線連結，空心菱形頭指向整體。 classDiagram ClassA \"1\" o-- \"N\" ClassB UML syntax classDiagram ClassA \u0026#34;1\u0026#34; o-- \u0026#34;N\u0026#34; ClassB 與 Composition 的相異處，在於 Aggrestion 的附屬類可以被共享，生命週期也不須與主體類相同。 實例：一部汽車可以一至多個兒童安全座椅。每個兒童安全座椅只能附屬於汽車。一台座椅可以登記在幾台常用的車上，隨時可以拆換到其他車上使用。 classDiagram 汽車 \"1\" o-- \"N\" 兒童安全座椅Composition 定義：表示 A 與 B 有從屬（主體與附屬）關係。若 A 包含 B，且 A 的完整性需要 B 才能完成，則 A is composed of B。 圖例：實線連結，實心菱形頭指向整體。 classDiagram ClassA \"1\" *-- \"N\" ClassB UML syntax classDiagram ClassA \u0026#34;1\u0026#34; *-- \u0026#34;N\u0026#34; ClassB 與 Composition 的相異處，在於 Composition 的主體與附屬無法單獨存在，生命週期相同。 實例：一部汽車有四顆輪胎，但若沒有輪胎，車子就不完整。車子報銷後，輪胎也會跟著被回收或丟棄。（假設沒有被黑心廠商拿去裝到別的車上） classDiagram 汽車 \"1\" *-- \"4\" 輪胎Inheritance (Generalization)（繼承） 定義：B is a kind of A。A 為實體類，而 B 是 A 的一種特化。 圖例：實線連結，空心箭頭指向被特化的類。 classDiagram ClassA \u003c|-- ClassB UML syntax classDiagram ClassA \u0026lt;|-- ClassB 使用 PlantUML 可以畫出空心箭頭，但使用 Mermaid 只能畫出如下的實心箭頭，不論是 Refactoring: Improving the Design of Existing Code 一書中使用空心箭頭，在白板上作圖，都是空心箭頭比較方便。不知 Mermaid 為何只能畫出實心箭頭。 Realization 定義：B realizes A。A 為通用的介面，而 B 實作該介面。 圖例：虛線連結，空心箭頭指向介面。 classDiagram ClassA \u003c|.. ClassB UML syntax classDiagram ClassA \u0026lt;|.. ClassB 與 inheritance 相同，一樣存在 Mermaid 無法畫出空心箭頭的問題。 ","date":"2022-03-30T00:00:00Z","permalink":"/posts/uml-class-diagram/","title":"A Note on UML Class Diagram"},{"content":"初看 楊斯棓 醫師發文說要贈送書盒，我心裡想：『書盒是什麼東西？』該文章附圖是一個個的紙箱，不知裡面是什麼，也沒再探究。幾天後，陸續看到其他收到「書盒」的人開箱分享，才驚覺原來送的是書啊！\n看著分享文中那些楊醫師精心挑選，主題圍繞在台灣、自由的書，著實心動，沒有履行再次參加有獎徵讀書心得承諾的我只好把羞恥心埋起來，伸手索書。\n於是，我在上週收到今年最具價值的有形禮物了。謝謝你，楊醫師。\n開心之餘緊接而來的是為難。我雖情感冷漠，不愛交際，禮尚往來的道理還是認同的。上回受禮後，隔年我贈出十幾本楊醫師的著作《人生路引》；這次比較難，一來與楊醫師並不相熟，無法投其所好，二來已經看到有人送禮被他「加倍奉還」，我豈敢妄動。\n當晚，我帶孩子念完書盒中唯一一本繪本後，在旁聆聽的老婆說：「我們買一箱這繪本送人吧！」，我心領神會，立表贊同。\n推廣閱讀、節能、促進消費（特別是實體書）、深化對這塊土地的認識，都是讓台灣更強韌、讓下一代環境美好的善舉，我的右還無法支撐我的左，但我能借花獻佛，將楊醫師的善念傳遞給更多人。\n","date":"2021-12-31T00:00:00Z","permalink":"/posts/books-from-sbyang/","title":"聖誕書盒"},{"content":"今天與同事討論 C 語言中，對一個浮點數取 floor 的問題。剛好最近有看到 IEEE 754 標準如何規範浮點數格式 1，就趁此機會仔細驗證一下。仍建議看第一手資料，以下純為記錄和分享用途而已。\n先從一個問題開始，我用 GCC 編譯以下的程式碼並執行：\nfloor(f1), 20 digital points: 2.00000000000000000000 floor(f2), 20 digital points: 3.00000000000000000000 為什麼 2.999999 取 floor 得到 2.0，而 2.9999999 取 floor 會得到 3.0 呢？我們的都知道，是因為浮點數有精度問題，單精度浮點數的精準度在絕大多數的機器上有效位數只到小數後第六位。這篇的目標就是從標準的角度去親自確認這件事情。\n首先，單精度浮點數是 32 bits，任何的小數都會轉換成二進制的科學符號後被存在這 32 個位元裡。\n借用 Wikipedia 的圖 \b\b這 32 個 bit，被分成三大部分，Sign、Exponent、Fraction（或稱 Significand/Mantissa）。\nSign：0 表示為正數，1 表示為負數。 Exponent：共 8 bits，值為 0~255，代表 2 的指數次方。由於指數也需要有正負號，如採用 Two\u0026rsquo;s Complement 來代表正負，則 0 到 127 代表 0 到 127，128 到 255 代表 -128 到 -1。 Significand：共 23 bits，但由於規定第一有效位一定要是 1，故有 24 有效位數 2。 使用 這個轉換器 可以知道，當想要對 f1 這個長度 8 bits 的記憶體位置存入 2.999999 時，其實際存起來的的值是 2.99999904632568359375。有效位為小數後六位（最低位 2^-23 = 0.000000119209\u0026hellip; 為可存的離散數間的最小間隔）。對這個值取 float，自然就是得到 2.0。而對 f2 這個長度 8 bits 的記憶體位置存入 2.9999999 時，實際存起來的值是 3.0，對 3.0 取 floor 會得到 3.0。\n可以實際執行下列程式確認這點。\nf1, 6 digital points: 2.999999 f2, 6 digital points: 3.000000 f1, 20 digital points: 2.99999904632568359375 f2, 20 digital points: 3.00000000000000000000 floor(f1), 20 digital points: 2.00000000000000000000 floor(f2), 20 digital points: 3.00000000000000000000 同時也可以發現，printf 是會對其參數做過一些處理才顯示出來的（15:16） ，這是為什麼有時候我們不能盡信 printf 給出的資訊的原因。用 GDB 或 Compiler 提供的 Debugger 直接對記憶體求值，才會得到未經處理的真實值。\n參考資料：https://www.bottomupcs.com/types.xhtml\n舉例來說，可以參考 IEEE 754 對 單精度浮點數 的定義。\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n先假設我們只有 4 bits Significand 可用，Exponent 為 0 的情況下，0.5 會是這樣存 0100，其十進位換算方式是 (0*2^0 + 1*2^-1 + 0*2^-2 + 0*2^-3)*2^0 = 0.5，但這樣存的缺點是能存的離散數的差只有到 2^-3 = 0.125。假如我們規定首位一定要是 1（就像十進位的科學記號，個位數一定會大於零），以此例來說，我們需要向左推兩位，Siginicant bits 就會變成 (1)0000，同時因為對 Significand 左推，Exponent 必須減二變為 -2，計算結果就變成 (1*2^0 + 0*2^-1 + 0*2^-2 + 0*2^-3 + 0*2^-4)*2^-1 = 0.5，會得到一樣的結果，但是能存的離散數的差變小為 2^-4 = 0.0625。\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"2019-07-02T00:00:00Z","permalink":"/posts/ieee754-float-check/","title":"C 語言中的浮點數與 IEEE 754"},{"content":"讀者：葉學舫\n這是一本白色恐怖受難者的記憶歷史。作者顏世鴻先生因為加入共產黨被逮捕至保密局北所、青島東路的軍法處，後囚禁於綠島和小琉球共十三餘年。顏君強記獄中事件，於獲釋後用兩天的時間抄寫出來，完成《霜降》一書，以此為獄友立傳。此書即是《霜降》第三次改寫而成。\n國民黨敗於共產黨後播遷來台。為了鞏固時局、剷除異己，國民黨發佈戒嚴令。國民黨政府接收台灣以降，包含外省人在內的社會各階層人士因不滿其種種惡行，或發議論、或辦報、或參加共黨活動，在明處或暗處反抗政府。國民黨視這些人為眼中釘肉中刺，遂依《戡亂時期檢肅匪諜條例》大肆逮捕。這些政治犯，部份雖確實預謀武裝反抗，多數人往往只是辦報、結社或是共黨組織成員，更有許多人是被構陷入罪。他們被補之後經過簡陋的審判，其刑期卻大多是動輒十年以上的有期徒刑乃至死刑。在可以自由結社、議論的今天，這些刑責重得難以承受，多少正值人生精華的壯年，就這樣早夭，或在獄中磋跎殆盡。面對與罪行極不符比例的重罪，能倖存已屬不易，換作是我，大概也只能哀嘆生不逢時，若能倖免於這場浩劫，怕還要像張大春先生描述自己家族平安度過白色恐怖時的心情，拍拍胸口安慰自己一聲：「好險！」\n無人記得的事件，再壯烈也終歸虛無；無人憑弔的紀念碑，再雄偉都將成斷壁殘垣。顏君任重而道遠，深入地獄，把所見所聞一一記在腦海，五千個日子中反覆記誦，把這段黑暗歷史最細微的質地化為文字供後人流傳，並且親赴綠島和馬場町悼念故人。我幾乎可以體會到，在轉移安坑時，確定可免於一死時，其不安和罪惡感，和對生存的強烈盼望交雜在一起的那種複雜的心情。不能生，是因為戰友為共同目標的犧牲，不能死，則是要為烈士立傳於史冊，生死之間的猶豫，使顏君自嘲不是文天祥、譚嗣同那塊料子，但在筆者眼中，警醒當世與流傳後人同樣令人肅然起敬。\n如今的綠島，已從關滿政治犯的監獄轉變為一處度假勝地，遊客在此從事各種水上活動、溫泉、夜遊，也會走人權園區、尋訪監獄，但政治犯的那段苦悶的記憶、面對漫漫刑期的絕望，大多已很難體會了。讀此書前，白色恐怖對我而言，與其說是一段歷史，不如說是一個符號。符號作為一個對談間的識別標記，或是作為一個概念的集合是很方便的，不過其概括的特性，背後的盤根錯節很容易就被忽視。讀此書後，白色恐怖這個符號於我才算真正有了意義，雖然那些大事小事，放到今天來看都已經微不足道，知道或不知道所有的枝微末節，也對未來無甚幫助，但賦予符號意義後，我的生命才能真正跟故事中的地點產生連結，跟歷史裡的事件與現在關聯起來。賦與意義這種工作之於我大概是一種徒勞，卻又是必須做的事情吧。\n筆者寫作此文時，正好在台東度假。來台東搭的是普悠瑪號，慚愧的是，一直到乘車當下，我才知道普悠瑪的意思，而且也僅止於名詞解釋。這符號所背負的，那些原住民受到的種種政經文化的侵略，都是我還不曾涉足的。歷史的層次和文化的肌理，從來不是像表面看來的那樣簡單和平易近人，那些或醒目的、或簡化的故事，只要稍一探索，就會發現其中充滿許許多多光怪陸離，它們使人悲傷，或令人無奈，它們一點也不有趣，但它們是我們的過去，是我與時間和空間產生連結的方式。\n","date":"2017-04-05T00:00:00Z","permalink":"/posts/chingtao-east-road/","title":"《青島東路三號：我的百年之憶及台灣的荒謬年代》：白色恐怖受難者的記憶歷史"},{"content":"讀者：葉學舫\n這本書講的是運動的學習方法。而且標題與內容不符，這不是一本網球運動基本動作指南，而是一個網球教練（W. Timothy Gallwey）總結出的，對於頂尖的運動選手都適用的身體訓練指南。\n放鬆的專注便是心法 統攝全書的關鍵字彙就在開篇的序中：\nThe player of the inner game comes to value the art of relaxed concentration above all other skills; he discovers a true basis for self-confidence; and he learns that the secret to winning any game lies in not trying too hard.\n放鬆的專注（relaxed concentration），指的是高度專注於觀察，而放棄想去干涉身體的衝動。為了更正確了解這件事，作者提出兩個自我的解釋。每個人都有兩個自我，各自負責不同的工作，我一（self 1）是 teller, thinker, criticizer，它負責觀察和評價自我，並控制身體達成我們下意識的動作；我二（self 2）是 doer，是真正負責執行動作的自我。掌握放鬆的專注的頂尖運動員們，會讓我一完全專注在觀察，觀察周遭、觀察對自己運動軌跡的期待、以及觀察我二的執行結果，然後讓我二在不受我一干涉的情形下去執行動作。\n白話來講，就是讓我一閉嘴，專心看就好。控制身體不是我一擅長的事情，它擅長整理複雜的資訊，給出評價，但是說到身體的整體運動，就是我二的場域，而且在不被干涉的情況下做得最好。\n自我經驗 作為一個業餘運動者，我自己也常有這樣的經驗，打桌球時，某球打偏了，就想著下一球要注意手腕的角度，並告訴自己不要太用力，結果下一球卻矯枉過正，接著再想著另一個修正方法，然後再一次打壞。就是這個注意手腕的念頭，讓身體局部緊繃，使得我二無法有效的運用身體各個部位，才會造成反效果。\n練習太極拳的過程也有類似的經驗。當我操作一個動作時，可能指法有誤，被指正後，第二次為了修正指法，反而在手的局部更為緊繃，結果就是進退維谷，不注意就達不到新的要求，注意就會喪失全局流暢性。\n配合心法的四種方法 作者認為最高的境界是我一和我二的融合，這會透過四個訓練漸漸達成（以我的話來改寫）：\n對於想得到的結果要有清晰的圖像，我二會從這個圖像自我學習。 信任我二能夠做出最佳表現，在失敗或成功中都能學習到東西，不去干涉。 不讓我一去評價，讚美或批評都不要，單純去看發生的事實就好。 不斷訓練專注力，不只是因為在專注的時候我一無法去評價或控制我二，更高的專注會因為會達成一種「靜」的狀態，那是身體運動最佳的狀態。 這四點並不簡約，也很容易就忘了，但是在運動前提醒自己，幾次下來就變成一種平常的習慣了。不過說到底，我本身就是個運動神經很差的人，就算這些技巧正確，我也真的用上了，想要在運動方面有什麼突破還是有點難想像啊\u0026hellip;\u0026hellip;\n","date":"2017-03-19T00:00:00Z","permalink":"/posts/the-inner-game-of-tennis/","title":"《網球的內心遊戲》：運動場域的學習心法是放鬆的專注"},{"content":"轉職為 Rails 工程師滿一年了。\n這一年，坦白說薪資並不多，福利也普通，但是個人思想面和技術面的成長，完全是過去的我無法想像的。而且在這個圈子裡，我找到竹科公司無法給的，那心目中理想的工作環境。至今我仍可以很肯定的說，當初離開相對高薪工作的決定是對的。\n離職前我曾說過，轉職，並不在我人生規劃中。只是每當思及自己三年後會在什麼位置、做著什麼事、達到什麼成就，我就不能再待在那個安逸的地方。安逸倒也不是壞事，只是個人趣舍不同而已，一份你所滿意的工作，放到他人身上結果未必相同。我想從工作獲得的東西有二，一是成就感，二是富足，成就感又先於富足，我在兩者相權之下，也只能暫時拋開喜愛的物理，選擇離去。唯獨有些可惜的是，前一份工作我的專業程度達不到我老闆十一，這點我於心有愧。\n為什麽選擇網路業？三年前的三一八學運，從立院傳出的直播讓民眾直接接觸現場而不是加工後的報導，新聞稿和場內外消息被即時翻成多國語言對外媒發送直接與國際接軌，國外義務提供網路資源支援 g0v，臉書上連日的討論洗版等，我在場親眼見證了資訊人對社會事件的投入和資訊科技如何改變了台灣未來的走向。當時的我發現自己對這些東西一竅不通，身為還懂一點 C++ 和 Matlab 的光學工程師，怎麽能容忍自己與科技脫節？於是我就一頭栽進去了，就這樣而已。（也許，在這個後真相時代，人們永遠得不到真相，但是換個角度想，真相是以一種更為多元的方式存在，而無法被有權力的人掩蓋。）\n我從一個業餘的 coder，變成專職的 web developer，能過渡來用的知識不多。從不懂 stack 和 queue，lexical 和 context，看一份 doc 一整天還看不懂，碰到 bug 只會 StackOverflow，我硬著頭嗑下每一個擋在路前的知識，到現在已經逐漸形成自己的方法論，看 document 或解 issue 都有一定的能力。這段過程蠻不容易的，也犧牲掉大量的休閒時間，但是我獲得成就感，也為公司完成大大小小的任務，有比這更棒的事嗎？\n我很感謝老闆給我自我成長的空間，以及新創環境帶給我的新視野。成就感已經具備，再來便是追求富足了。三年，腳步不會停歇。\n記於三一八學運三年後\n","date":"2017-03-19T00:00:00Z","image":"https://image.sharefun.dev/m1TNik4.png","permalink":"/posts/being-a-rails-developer-after-one-year/","title":"轉職 Rails 工程師的一年後"},{"content":"讀者：葉學舫\n撇除義務教育時期被動接受的資訊，我真正了解二戰前後台灣這塊土地上的人事物，是始於王鼎鈞的《關山奪路》，其後是《百年追求卷一自治的夢想》，再來就是《此心不沉：陳纂地與二戰末期台灣人醫生》。《關山奪路》講述鼎鈞先生從流亡學生，到被國民黨徵召（或說矇騙）進入憲兵隊，在中國繞了大半圈後隨著國民政府來台的故事。《百年追求》訴說日治中期開始，台灣本土菁英和學生追求民主化的過程，一直到二二八事件後數年。《此心不沉》從被日人徵召入伍的台灣醫生為視角，描述本土菁英關懷台灣前途，二二八之際武裝起來，採取激烈手段力拒國民黨統治，事敗後藏身山中四年多，最後在特務監視下終老的故事。\n權力使真相沉沒，思辨史傳才能讓我們更逼近真實。被國民黨誘騙的文人憲兵、採溫和路線的台灣學生和本土菁英、採激進路線的斗六隊和二七部隊，這三本書圍繞著二二八事件前後，從這三個視角我架構起過去的歷史基底，和在這些基底上行走過的人物的圖像。這些人物甚多，有台灣本土菁英、留日台人、國民黨軍人、掌權者、中台兩地的日人和本書主角：受日人徵召的軍人。\n國共內戰末期，國民黨軍隊在中國華北華中各地已是聲名狼籍，所到之處極盡搶拐誘騙之能事，幾場重大會戰的挫敗，國民黨許多高官更是亟思中飽私囊，或潛逃、或投共，底層官兵無以為濟，已以劫收平民資產為慣。這時多數台灣人滿心期待的國民政府前來光復，希望他們會為其帶來日本無法給的民主，這是長期受到日人差別待遇和六三法集權統治，再經蔣渭水等人的文化運動啟蒙後很正常的想像。\n在資訊不發達的年代，台灣本島只有少數知悉中國情勢的士紳階級看得出國民黨的接收是禍非福。在海外，則有遭到蔣中正算計過，後來帶領越盟爭取越南獨立的胡志明，深深了解國民黨是怎樣一群人，越盟中的陳纂地希望戰後的台灣也能循越南模式成為一獨立自主的國家，也擔心被接收後台灣人會面臨的災難，所以毅然結束在越盟的建立的良好關係地位，回轉台灣。從歷史的後見之明看來，戰後的民心和意見領導者就決定了越南和台灣註定走向不同的命運。胡志明積極反對蔣代為受降甚至出兵、向國際抗議，台灣人則是歡天喜地慶賀光復，明眼的士紳階級但求明哲保身，維繫祖業，遂迎來不速之客。\n陳纂地先生，本書主角，彰化二八水（今二水）醫生，在二戰末期受日人強徵，搭上貨輪神靖號前往西貢支援。神靖號在行經 San Jacque 被美軍炸沉，陳纂地大難不死，結交越盟，並思考台灣出路。回台後組織自衛隊，並與本書作者相識，兩人在二二八後分組斗六隊和二七部隊，攻下中台灣要地，在國軍二一師登陸後才兵敗，作者鍾逸人被捕入獄，陳纂地遁入家鄉山中。四年後受昔日同窗勸降，以演出「共軍來降」的粉飾橋段為條件換取家人生命和被扣押的財產，其後被命在台北行醫，受特務監視直至終老。\n幸得鍾逸人先生還原，以往成王敗寇的簡單法則被打破，時間沒有洗掉過去而是沖刷出真實，陳纂地也不用作為共軍被世人記憶。《百年追求》中大略提到的全島起義，在鍾先生筆下又帶出這一段曲折的故事。這群人並非我早前想像的，是一群單純不滿國民黨統治，所以在二二八後乘著民怨隨機挺身反抗的勇士，而是少數有遠見、肯實幹，計畫籌備良久，廣積實力，在台灣自由將消失殆盡之際，為民奪取自由而身先士卒的在地菁英，是有血有肉有情緒有弱點的人。\n陳纂地先生過世之年，恰好是我出生之年。在我這個年紀附近的人，對日本統治、神靖丸、二二八、白色恐怖等未曾親歷的事件，若非特意追尋，就只是一些畫面模糊的名詞，或者只能人云亦云而已。但這又是離我這麽近的事件，又是台灣之所以成為現在的台灣的幾個關鍵事件，我可能永遠無法體會那代人的恐懼悲傷和無奈，但也無法只看片面的事實就喊出「二二八已經過去應該放下原諒面對未來」或是「KMT 就是應該黨產歸零立刻解散」等簡化的口號。時空環境、資訊不足、民意歸向、當權者心態共同造就了悲哀的過去，如果當初台灣像越南一樣力拒蔣中正接收，又或者負責接收的不是陳儀這等貨色，又或者軍伍和官僚有紀律而贏得台人尊重，又或者蔣氏不那麽嫉才多疑、視民如草芥，也許就不會發生後來種種。但歷史不講假設，在二二八這天，我希望所有的真相都能一一還原，如此傷痛才能真正走進歷史，歷史才能真正成為我們的一部份與我們長久共存。而我能做的，只有在積累的閱讀中塑造自己的歷史觀，有機會的話，再告訴更多的人，這樣而已。\n後記 雖然鍾先生以驚人的毅力寫下這本中文書，我閱讀的過程還是比較吃力的。主要原因是對人物的不熟悉，在書序已經提到，鍾先生記憶非凡，認識或聽聞過的當代人士為數眾多，許多神來一筆插入的角色，在我還建立不起這人的印象就結束了。其二是行文方式用許多引號，即使非關鍵字詞仍用引號，會使人誤以為是否另有喻意或音喻，導致閱讀斷點甚多。另外，雖然在 Wiki 上查得的主角名字是「陳篡地」，與書名中的「陳纂地」不同，但筆者不詳加細究，僅以書名上的版本來書寫。\n","date":"2017-02-28T00:00:00Z","permalink":"/posts/chen-and-taiwan-doctors-in-world-war-two/","title":"《此心不沉：陳纂地與二戰末期台灣人醫生》：二二八事件中台灣武裝起義的人物"},{"content":"百里寒冬風割面，遊心一夜到雲巔。\n枋山鐵道尋陳跡，旭海長亭度陌阡。\n華舍錦衾高索費，紅霞碧海不需錢。\n驚瀾散去復歸海，談笑盡時情自延。\n第三十六屆鳳凰樹文學獎　古典詩外系組　正獎\n","date":"2008-01-01T00:00:00Z","permalink":"/posts/syuhai-with-friend/","title":"偕友觀潮於旭海"}]