• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            loop_in_codes

            低調(diào)做技術(shù)__歡迎移步我的獨(dú)立博客 codemaro.com 微博 kevinlynx

            用lisp開(kāi)發(fā)博客客戶端

            用lisp開(kāi)發(fā)博客客戶端

            Author: Kevin Lynx
            Date: 3.13.2011

            最近一直在學(xué)習(xí)Lisp這門語(yǔ)言?;仡^一看,基本上接近1個(gè)月了。剛開(kāi)始接觸Lisp是因?yàn)榭? 了<Lisp本質(zhì)>,然后我發(fā)現(xiàn)有很多人宗教般地忠誠(chéng)這門語(yǔ)言,于是就來(lái)了興趣。

            imgs/lisp_believer.png

            當(dāng)然并不是每次因?yàn)槟称獙懙煤躦eek技術(shù)文章就去學(xué)習(xí)某個(gè)新的技術(shù)點(diǎn)。一個(gè)月時(shí)間對(duì)我來(lái) 說(shuō)還是很珍貴了。但是Lisp絕對(duì)是大部分程序員都值得一學(xué)的語(yǔ)言(就像Haskell一樣)。 我能給出的簡(jiǎn)單理由包括:

            • 大部分程序員只會(huì)命令式語(yǔ)言(C/C++/C Like etc),缺乏函數(shù)式語(yǔ)言解決編程問(wèn)題的思 想(當(dāng)然Lisp不是純函數(shù)式)
            • Lisp是僅次于Fortran的古老語(yǔ)言,很多優(yōu)秀的語(yǔ)言設(shè)計(jì)思想在現(xiàn)代的一些語(yǔ)言里都找得 到
            • 裝B黨必備

            另一方面,結(jié)合我一個(gè)月以來(lái)的讀書和兩個(gè)練習(xí)工程的實(shí)踐經(jīng)歷,我覺(jué)得也有些理由值得你 不去學(xué)習(xí)Lisp:

            • 你會(huì)Haskell或者其他函數(shù)式語(yǔ)言
            • 我目前還是覺(jué)得Lisp學(xué)習(xí)曲線高(大概是因?yàn)槲易x到的書都在應(yīng)用語(yǔ)法層兜圈子,事實(shí)上 Lisp的語(yǔ)法之統(tǒng)一,全特么的是s-expression),你不愿意花費(fèi)這些成本
            • you are too old bo to be a B

            關(guān)于這篇文檔

            這篇博客我使用reStructuredText格式編寫,然后用docutls導(dǎo)出為html,再然后使用這回 用lisp開(kāi)發(fā)的基于metaweblog API的博客客戶端,自動(dòng)發(fā)布到CPPBLOG。

            他們?cè)趺凑f(shuō)Lisp

            我就摘錄些書上的觀點(diǎn)(歷史):

            • 1958年,John McCarthy和他的學(xué)生搞出了Lisp,包括其第一個(gè)實(shí)現(xiàn),最初貌似也是以一 篇論文起頭
            • Lisp可以讓你做其他語(yǔ)言里無(wú)法做的事情(<ANSI common Lisp>)
            • 大部分編程語(yǔ)言只會(huì)告訴你不能怎樣做,這限制了你解決問(wèn)題的思路,Lisp not (<ANSI Common Lisp>)
            • Lisp讓你以Lisp的思維思考問(wèn)題,換到其他語(yǔ)言你會(huì)說(shuō):為什么X語(yǔ)言就不支持這個(gè)特性 呢(Once you've leanred Lisp, you'll even dream in Lisp) (<Land Of Lisp>)
            • Lisp代碼更清晰地體現(xiàn)你的想法(<Practical Common Lisp>)

            And my opinion

            我可還沒(méi)到把Lisp捧上天的地步。如果Lisp如此之好,為什么用的人不多?<Land Of Lisp> 里作者恰好對(duì)這個(gè)問(wèn)題做了回答(bla bla bla,懶得細(xì)讀)。

            • Lisp也是一門雜和型風(fēng)格的語(yǔ)言,函數(shù)式、命令式、面向?qū)ο?,以及最被人吹捧的宏編? --程序自己寫自己
            • Lisp的語(yǔ)句全部以(xxx xxx)的形式出現(xiàn),被稱為s-expression,我看稱為括號(hào)表達(dá)式還 差不多
            • Lisp每條語(yǔ)句都有返回值,沒(méi)基礎(chǔ)過(guò)函數(shù)式編程的同學(xué),if語(yǔ)句也是有返回值的
            • 函數(shù)式編程語(yǔ)言的一個(gè)重要特性就是閉包(closure),這個(gè)東西用來(lái)避免全局變量實(shí)在太 geek了

            開(kāi)始學(xué)習(xí)Lisp

            Lisp不像有些語(yǔ)言,有個(gè)直接的機(jī)構(gòu)來(lái)維護(hù)。感覺(jué)它更像C/C++一樣,只有個(gè)標(biāo)準(zhǔn),然后有 若干編譯器(解釋器)實(shí)現(xiàn)。Lisp在幾十年的發(fā)展中,產(chǎn)生了很多種方言。方言也就是形變 神不變的語(yǔ)言變種,本文說(shuō)的Lisp均指Lisp的方言Common Lisp。另一個(gè)比較有名的方言是 Scheme,關(guān)于各個(gè)方言的特點(diǎn),<Land Of Lisp>里也給了一個(gè)圖片:

            imgs/dialect.png

            其中,最左邊那只wolf就是Common Lisp,右邊那只sheep就是Scheme。

            要學(xué)習(xí)Lisp,首先就是選擇方言。然后最重要的就是選擇一個(gè)編譯器實(shí)現(xiàn)。世界上知名的有 十幾種實(shí)現(xiàn)(也許更多)。一些商業(yè)版本非常強(qiáng)大,甚至能編譯出很小的本地代碼執(zhí)行文件 ,不過(guò)價(jià)格也不菲。當(dāng)然也有很多開(kāi)源免費(fèi)的實(shí)現(xiàn),例如CLISP、SBCL。我選用的是SBCL。

            SBCL交互式命令行不支持括號(hào)匹配,甚至沒(méi)有輸入歷史。要實(shí)現(xiàn)這兩個(gè)功能,可以裝一個(gè) lisp工具:linedit。在lisp的世界中,要獲得一個(gè)lisp的庫(kù)實(shí)在不是件方便的事。尤其是 這些免費(fèi)的編譯器實(shí)現(xiàn),并不像有些語(yǔ)言一樣,直接隨編譯器帶個(gè)幾十M的庫(kù)。

            然后就有了quicklisp這個(gè)工具。該工具就像Ubuntu系統(tǒng)里的軟件管理器一樣,你可以在 lisp里直接獲取某個(gè)庫(kù)。quicklisp檢查該庫(kù)是否存在,不存在直接從它的服務(wù)器上下載人 然后自動(dòng)安裝。

            此外,在lisp的世界里,寫出來(lái)的程序不再是跨OS。OS的差異由編譯器實(shí)現(xiàn)來(lái)解決。但是, 寫lisp程序卻需要考慮跨編譯器實(shí)現(xiàn)(egg hurt)。這也是個(gè)無(wú)比傷神的事,比跨OS更傷 神。因?yàn)镺S就那么幾個(gè),但lisp的編譯器實(shí)現(xiàn),流行的也有好幾個(gè)。

            lisp的世界里,工程組織也有特殊的一套,就像makefile一樣,這就是asdf。

            博客客戶端如何實(shí)現(xiàn)

            像我們這種基本沒(méi)接觸過(guò)Web開(kāi)發(fā)的人,可能完全沒(méi)有思路去實(shí)現(xiàn)一個(gè)博客客戶端。事實(shí)上 實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單。

            使用過(guò)其他博客客戶端(例如Windows Live writer)的人肯定知道m(xù)etaweblog API,在配 置客戶端的時(shí)候需要填入。例如CPPBLOG的這個(gè)地址就是 http://www.shnenglu.com/kevinlynx/services/metaweblog.aspx。這個(gè)頁(yè)面展示了一些API 說(shuō)明。這些API就是博客客戶端和服務(wù)器進(jìn)行操作通信的接口。意思是說(shuō),服務(wù)器端提供這 這些接口,我們的客戶端調(diào)用這些接口即可。例如:

            blogger.deletePost,調(diào)用該接口即可刪除一篇博客文章
            

            但是客戶端如何調(diào)用到這個(gè)接口呢?這需要通過(guò)一種新的技術(shù)(或者說(shuō)標(biāo)準(zhǔn)),即 xml rpc 。rpc大家應(yīng)該清楚,xml rpc其實(shí)說(shuō)白了, 就是把接口調(diào)用的細(xì)則塞進(jìn) http 請(qǐng)求發(fā)給web服務(wù)器,服務(wù)器接收請(qǐng)求完成操作后再把結(jié)果以http回應(yīng)的形式丟給客戶端, 即完成了一次接口調(diào)用

            至于http請(qǐng)求回應(yīng)的細(xì)則就不提了,無(wú)非就是一些特殊格式的數(shù)據(jù),通過(guò)tcp連接與服務(wù)器 交互這些數(shù)據(jù)。

            所以,基本上,整個(gè)過(guò)程還是非常簡(jiǎn)單。如何來(lái)將調(diào)用細(xì)節(jié)塞進(jìn)http請(qǐng)求,則是以xml rpc 標(biāo)準(zhǔn)來(lái)做,其格式正好是xml格式。舉個(gè)例子吧:

            <?xml version='1.0'?>
            <methodCall>
                <methodName>title_or_id</methodName>
                    <params>
                    </params>
            </methodCall
            

            當(dāng)然這部分?jǐn)?shù)據(jù)之前就是若干http請(qǐng)求的數(shù)據(jù)。服務(wù)器回應(yīng)也是以xml格式組織:

            <?xml version='1.0'?>
            <methodResponse>
                <params>
                    <param>
                        <value><string>Welcome to Zope.org</string></value>
                    </param>
                </params>
            </methodResponse>
            

            我們的博客客戶端所要做的,就是把這些博客發(fā)布相關(guān)的操作封裝起來(lái)提供給使用者。底層 實(shí)現(xiàn)主要包括http請(qǐng)求、xml-rpc的組織等。何況,這兩部分在各個(gè)語(yǔ)言里都有大量的庫(kù)存 在,lisp自然也有。

            我這里直接選取了lisp的一個(gè)xml-rpc庫(kù):s-xml-rpc,基本上百來(lái)行代碼就可以把各個(gè)功 能跑一遍。例如以下lisp代碼就實(shí)現(xiàn)了通過(guò)s-xml-rpc刪除CPPBLOG的一篇文章:

            (defun delete-post (postid)
              (rpc-call
                "blogger.deletePost"
                postid
                "kevinlynx"
                "password"
                t))
            

            發(fā)布博客也很簡(jiǎn)單,根據(jù)metaweblog API接口的說(shuō)明,發(fā)布博客時(shí)需要填充一個(gè)結(jié)構(gòu)體。但 主要涉及到的數(shù)據(jù)僅包括:文章內(nèi)容、文章標(biāo)題、文章分類(可選):

            (defun new-post (title context &optional (cates))
              (rpc-call
                "metaWeblog.newPost"
                ""
                "kevinlynx"
                "password"
                (new-post-struct title context cates)
                t))
            

            值得注意的是,如果文章中有貼圖,則需要事先將圖片文件上傳到服務(wù)器。CPPBLOG的 metaweblog API里恰有API提供:

            (defun new-media-object (filename)
              (rpc-call
                "metaWeblog.newMediaObject"
                ""
                "kevinlynx"
                "password"
                (new-media-object-struct filename)))
            

            該函數(shù)讀入圖片文件,然后調(diào)用metaWeblog.newMediaObject接口,即可完成上傳。上傳成 功后,服務(wù)器會(huì)返回該圖片的URL。然后在我們的文章中就可以使用該圖片了。

            完整實(shí)現(xiàn)方案

            僅僅將metaweblog的一些接口做封裝,對(duì)于一個(gè)可以使用的博客客戶端來(lái)說(shuō)還遠(yuǎn)遠(yuǎn)不夠。大 部分同類工具都有一個(gè)友好的GUI編輯界面。我并不打算弄一個(gè)編輯界面出來(lái),吃力不討好 的事情。

            我的打算是先用其他工具對(duì)文章做排版處理,最后導(dǎo)出為html格式。因?yàn)镃PPBLOG支持直接 發(fā)布一個(gè)html文件。然后在用這個(gè)lisp工具將整個(gè)文件作為博客文章內(nèi)容發(fā)布。

            恰好公司最近打算用reStructureText(rst)格式來(lái)編輯文檔,作為熟悉手段,我決定拿這個(gè) 來(lái)練手。rst格式非常簡(jiǎn)單,同wiki命令很相似。在vim里編輯該文件非常合適,因?yàn)槟J(rèn)支 持。見(jiàn)圖:

            imgs/rst.png

            由圖即可看出,rst是一種半所見(jiàn)即所得的格式。即:它遵循你在編輯器里的排版,同時(shí)也 通過(guò)一些tag(例如image)來(lái)控制更豐富的輸出。

            rst有很多前端工具,可以將rst文件輸出,例如rst2html.py就可以輸出為html。好吧,最 最終我們得到了html格式的博客文章。

            但是如果文章中出現(xiàn)了圖片,而圖片基本上在本地,轉(zhuǎn)成html后也是相對(duì)路徑。我需要我的 lisp writer(cl-writer)能自動(dòng)掃描文章,發(fā)現(xiàn)有圖片的地方,就自動(dòng)將圖片上傳。最惡心 的是上傳后還得替換圖片引用路徑。這個(gè)工作可以在rst格式上做,也可以在結(jié)果格式html 上做。通過(guò)xml解析庫(kù)解析html比直接解析rst格式更簡(jiǎn)單,并且在擴(kuò)展性上更好。

            最終這個(gè)html中圖片路徑替換工作只消耗了不到100行l(wèi)isp代碼。這在很大程度上也依賴于 s-xml庫(kù)的接口設(shè)計(jì)。

            最終封裝好的發(fā)布接口如下,從這里也可以看出,函數(shù)式語(yǔ)言鍛煉我們寫出功能單一代碼度 短小的接口:

            (defun writer-post-new (post-file &key (u (get-default-user))(cates))
              (read-post-file u post-file context title
                              (new-post u title context cates)))
            

            END

            別指望我發(fā)布的代碼能夠讓你一鍵在你的博客上留下"this is a test",你甚至別指望它能 能夠工作。但如果你本來(lái)就是一個(gè)資深的lisper,或者雖然不是lisper但卻執(zhí)意想看看結(jié)果 。這里我就簡(jiǎn)要說(shuō)說(shuō)如何讓這些代碼歡樂(lè)起來(lái):

            1. OS Ubuntu10.04,下載安裝SBCL,不會(huì)有問(wèn)題;

            2. 下載安裝quicklisp,官方文檔hand by hand,簡(jiǎn)單不會(huì)有問(wèn)題;

            3. SBCL交互環(huán)境中使用quicklisp安裝s-xml-rpc:

              (ql:quickload "s-xml-rpc")
              
            4. 裝載我的代碼:

              (asdf:load-system :cl-writer)
              
            5. 在home下添加配置文件.cl-writer.lisp,配置你博客信息,例如:

              (in-package cl-writer)
              (setf *default-user* (make-cppblog-user "賬戶名" "密碼"))
              

              如果你的博客不在CPPBLOG,雖然也許也是metaweblog,但我不能保證成功,配置文件則 要復(fù)雜點(diǎn):

              (setf *default-user* (make-user-info :name "帳戶名"
                                    :password "密碼" :host "www.shnenglu.com"
                                    :url "/kevinlynx/services/metaweblog.aspx"))
              
            6. SBCL交互環(huán)境下測(cè)試:

              (in-package cl-writer)
              (new-post (get-default-user) "this is a test" "title")
              

            下載代碼

            最后,終于敲完這篇文章,我需要通過(guò)以下步驟來(lái)發(fā)表它:

            in shell:
            rst2html.py lisp_xml_rpc.rst lisp_xml_rpc.html
            in SBCL:
            (writer-post-new "lisp_xml_rpc.html")
            

            ;;EOF;;

            posted on 2011-03-13 13:19 Kevin Lynx 閱讀(16876) 評(píng)論(8)  編輯 收藏 引用 所屬分類: lisp

            評(píng)論

            # re: 用lisp開(kāi)發(fā)博客客戶端 2011-03-13 20:04 ccsdu2009

            寫的不錯(cuò) 很好的寫手!  回復(fù)  更多評(píng)論   

            # re: 用lisp開(kāi)發(fā)博客客戶端[未登錄](méi) 2011-03-14 10:30 Louis

            CLISP 我也折騰過(guò)不短的時(shí)間,當(dāng)然沒(méi)有用到真正的工作上。最主要的是這個(gè)括號(hào)匹配,實(shí)在是太蛋疼。  回復(fù)  更多評(píng)論   

            # re: 用lisp開(kāi)發(fā)博客客戶端 2011-03-14 13:18 Kevin Lynx

            @Louis
            閱讀Lisp代碼主要是通過(guò)代碼縮進(jìn)來(lái)識(shí)別語(yǔ)句關(guān)系,如果是通過(guò)括號(hào)那根本沒(méi)法閱讀。在RECL下(也就是交互模式下)輸入語(yǔ)句我喜歡一行輸下去,所以那個(gè)輸入環(huán)境能有括號(hào)匹配(例如CLISP輸入")"時(shí)就會(huì)做點(diǎn)提示)就是個(gè)不錯(cuò)的功能。SBCL默認(rèn)沒(méi)有。  回復(fù)  更多評(píng)論   

            # re: 用lisp開(kāi)發(fā)博客客戶端 2011-03-14 21:51 Albert Lee

            sbcl 可以配合 rlwrap 來(lái)實(shí)現(xiàn) readline 功能。 現(xiàn)在很流行一個(gè)安裝lisp庫(kù)的工具: quicklisp , 非常方便。 另外,在實(shí)際開(kāi)發(fā)Lisp的時(shí)候, Emacs + Slime 是一個(gè)非常強(qiáng)大的工具,邊開(kāi)發(fā)邊執(zhí)行邊改進(jìn),最能體現(xiàn)Lisp的快速迭代演進(jìn)的開(kāi)發(fā)風(fēng)格。  回復(fù)  更多評(píng)論   

            # re: 用lisp開(kāi)發(fā)博客客戶端 2011-04-25 22:34 hex108

            太帥了!
            image:: imgs/lisp_believer.png 也是我想要的功能  回復(fù)  更多評(píng)論   

            # re: 用lisp開(kāi)發(fā)博客客戶端 2011-09-01 12:58 xiaohanyu

            太帥了?。?!  回復(fù)  更多評(píng)論   

            # re: 用lisp開(kāi)發(fā)博客客戶端[未登錄](méi) 2012-02-23 17:52 li

            @Albert Lee
            但是在開(kāi)發(fā)一個(gè)項(xiàng)目的時(shí)候感覺(jué)就不是很方便
            目前在學(xué)習(xí)lisp中 希望多交流交流 嘻嘻  回復(fù)  更多評(píng)論   

            # re: 用lisp開(kāi)發(fā)博客客戶端 2014-09-04 00:45 leptune@live.cn

            鼓搗了一晚上,終于用樓主的代碼成功的將博客發(fā)送的新浪博客了?。≈x謝樓主!
            幫樓主步驟補(bǔ)充詳細(xì)些,以幫助那些跟我一樣的小白:
            如果提示asdf沒(méi)發(fā)現(xiàn),那么是你少了(require 'asdf)
            如果提示cl-writer沒(méi)發(fā)現(xiàn),那么就:sudo cp cl-writer.asd /usr/local/lib/sbcl/contrib/
            最后發(fā)表的總步驟為:
            (ql:quickload "s-xml-rpc")
            (asdf:load-system :cl-writer)
            (in-package cl-writer)
            (writer-post-new "lisp_xml_rpc.html")
            新浪博客的配置文件為:
            (setf *default-user* (make-user-info
            :name "281754179@qq.com"
            :password "密碼"
            :host "upload.move.blog.sina.com.cn"
            :url "/blog_rebuild/blog/xmlrpc.php"))  回復(fù)  更多評(píng)論   

            狠狠色噜噜色狠狠狠综合久久| 久久精品www| 精品亚洲综合久久中文字幕| 久久精品国产一区二区三区 | 欧美午夜A∨大片久久| 狠狠色丁香久久婷婷综合蜜芽五月| 久久精品无码一区二区WWW| 久久精品www| 久久久久久久精品妇女99| 国产精品欧美久久久久无广告 | 久久久久亚洲精品日久生情 | 三级三级久久三级久久| 日韩精品久久久久久| 久久影院综合精品| 亚洲国产天堂久久久久久| 亚洲国产精久久久久久久| 无码伊人66久久大杳蕉网站谷歌 | 亚洲国产精品无码久久98| 久久丝袜精品中文字幕| 亚洲精品国产成人99久久| 久久青青草原精品国产| 久久成人国产精品免费软件| 久久精品国产99久久香蕉| 国产91久久精品一区二区| 无码精品久久久久久人妻中字| 中文字幕亚洲综合久久菠萝蜜| 99久久精品无码一区二区毛片 | 亚洲AV无码久久| 久久久久久久久久久久久久| 亚洲精品久久久www| 午夜精品久久久久9999高清| 青青久久精品国产免费看| 人妻精品久久久久中文字幕| 久久久久免费视频| 九九久久精品国产| 久久一区二区免费播放| 久久se精品一区二区影院| 欧美久久天天综合香蕉伊| 深夜久久AAAAA级毛片免费看| 欧美大战日韩91综合一区婷婷久久青草| 国产A级毛片久久久精品毛片|