.NET DLR 上的IronScheme 語言互操做&&IronScheme控制檯輸入中文的問題

前言

一直以來對Lisp語言懷有很崇敬的內心,《黑客與畫家》對Lisp更是推崇備至,雖然看了很多有關Lisp的介紹但都沒有機會去寫段程序試試,就像我對C++同樣,多少有點敬畏。這個週末花了很多時間來研究Lisp。
Lisp是古老的函數式語言,跟C,C++等命令式語言徹底不同的編程風格,但Lisp的方言不少,最後Lisp標準委員制定了Common Lisp,但內容很長,有1000多頁,所以功能比較強大;而Lisp的另一個主要分支就是Scheme,它的標準內容只有不到100頁,因此很是簡單,適合學術研究和大學計算機語言教學以及通常的工程應用。目前Lisp有在JVM上的實現,在.NET上的實現就是 IronScheme,因而我便開始選擇了IronScheme做爲Lisp研究的第一站。html

1,下載IronScheme源碼

IronScheme在Codeplex上有開源項目, https://ironscheme.codeplex.com/ ,能夠下載它的源碼和編譯好的程序,在 https://ironscheme.codeplex.com/SourceControl/latest 能夠下載源碼,我下載時候的文件名是 ironscheme-103684,下載的源碼能夠用VS2008打開。若是沒有開發環境,直接用 debugbuild.bat 也就能夠直接編譯。另外還能夠直接運行測試 r6rstest.batlinux

2,IronScheme控制檯

在網站上下載IronScheme的應用程序後,能夠直接看到它已經提供了不一樣環境下的控制檯程序,分別有64位與32位,.NET 2.0與4.0的程序: IronScheme.Console32-v2.exe IronScheme.Console32-v4.exe IronScheme.Console-v2.exe IronScheme.Console-v4.exesql

2.1,執行Scheme程序

找一個合適的控制檯運行下,輸入幾個Lisp表達式看看: 編程

Lisp程序有一個自然的執行多個參數運算的特色,因此咱們能夠執行多個數字相加。也可使用 display 函數顯示一個字符串。架構

2.2,中文亂碼問題

寫一個簡單的Hello 程序文件來加載 試試:框架

 執行這個程序,成功 ,可是亂碼,不論是存儲成 ANSI格式仍是UTF8格式均亂碼:函數

2.3,解決亂碼

無奈,只有打開IronScheme源碼進行分析,分析了好久好久....學習

最後乾脆直接搜索編碼格式 Encoding...,好歹涉及這個關鍵詞的地方只有3個:測試

在 IronScheme.Console 項目下的 Program 文件中,找到下面的代碼:字體

 Encoding oo = Console.OutputEncoding;

      EnableMulticoreJIT();

      try
      {
          //Console.OutputEncoding = Encoding.UTF8;
        return IronSchemeConsoleHost.Execute(args);
      }
      finally
      {
        Console.OutputEncoding = oo;
      }

將原來的 Console.OutputEncoding = Encoding.UTF8 註釋便可,因爲個人電腦是中文環境,這樣程序便以GBK的編碼運行了,此時便可正常顯示Scheme 程序中的 漢字。可是,若是要加載的文件名有漢字,則悲劇了,控制檯沒法輸入漢字...

再次檢查程序中全部跟控制檯有關的編碼的地方,發現除了前面檢查過的編碼問題,再也沒有其它地方,最後跟蹤調試代碼,發現程序使用

Console.ReadKey()

方法來獲取屏幕輸入的,而這個方法,是沒法得到中文輸入的...%&*....

 既然是截獲了鍵盤敲擊,那麼我就頂一個特殊的鍵,按下它在彈窗出來一個窗口,在裏面輸入中文就能夠了吧,因而找到文件 SuperConsole.cs ,找到 Insert(ConsoleKeyInfo key) 方法,修改爲下面的代碼:

 private void Insert(ConsoleKeyInfo key) {
            char c;
            if (key.Key == ConsoleKey.F6)
            {
              Debug.Assert(FinalLineText.Length == 1);
              
              c = FinalLineText[0];
            }
            else if (key.Modifiers == ConsoleModifiers.Alt && (key.Key >= ConsoleKey.NumPad0 && key.Key <= ConsoleKey.NumPad9))
            {
              c = '?';
            }
            else
            {
              c = key.KeyChar;
            }
            //Ctrl+Z 輸入漢字
            if (key.Key == ConsoleKey.Z && key.Modifiers == ConsoleModifiers.Control)
            {
                frmInputString frm = new frmInputString();
                frm.Activate();
                frm.ShowDialog();
                //Console.Write(frm.Text);
                string s = frm.Text;
                
                _input.Append(s);
                Output.Write(s);
                _rendered += s.Length;
                _current += s.Length;
            }
            else
            {
                Insert(c);
            }
        }

這樣就能夠在Scheme控制檯彈窗輸入中文了,順便加入文件選擇功能,方便加載程序文件,如圖:

控制檯默認的字體是 「點陣字體」,這種字體在輸入中文後,Scheme 定位字符位置會有問題,應該使用非點陣字體,例如以下圖的設置(控制檯窗口標題--屬性--字體):

3,Scheme 調用 .NET

按照 做者官方的說法,IronScheme是能夠簽入在.NET應用程序裏面的,可是單獨執行Scheme程序的時候,是否能夠調用 .net已有的程序呢?這個IronScheme也提供了,下面是 https://ironscheme.codeplex.com/wikipage?title=clr-syntax&referringTitle=Documentation 頁面的內容:

These macro's are exported from the (ironscheme clr) library.

Common parameters

type is either:

  • a symbol. Eg: Int32 or System.IO.Stream
  • a list implying a generic type. Eg: (Action Int32)
  • #f (false) meaning the type should try to be inferred

Primary syntax

(clr-namespaces) Returns all the imported at the lexical scope
(clr-reference reference) reference can be a symbol for the assembly short name (ie System.Web) or a string containing the fully qualified assembly name.
(clr-using namespace) namespace is a symbol. Eg System.IO .
(clr-call type method instance arg ...) method is a symbol for a simple name, eg ToInt32 or a string to resolve specific methods, eg "ToInt32(Object)" . instance is a reference to the object of type . Can be null ('()) for static methods. arg ... is the arguments passed to the method.
(clr-cast type expr) expr is the instance to be cast.
(clr-is type expr) expr is the instance to be tested.
(clr-new type arg ...) arg ... is the arguments passed to the constructor.
(clr-new-array type size) size is the size of the array. Must be an integer.
(clr-event-add! type  event instance handler) event is a symbol for the name of the event. Eg Click . instance is a reference to the object of type . Can be null ('()) for static events. handler is a procedure taking the same number of arguments as the event's delegate.
(clr-event-remove! type  event instance handler) event is a symbol for the name of the event. Eg Click . instance is a reference to the object of type . Can be null ('()) for static events. handler is a procedure taking the same number of arguments as the event's delegate.
(clr-field-get type field instance) field is a symbol for the name of the field. Eg m_foo . instance is a reference to the object of type . Can be null ('()) for static fields.
(clr-field-set! type field instance expr) field is a symbol for the name of the field. Eg m_foo . instance is a reference to the object of type . Can be null ('()) for static fields. expr is the value to set the field.
(pinvoke-call library method arg ...) arg ... is the arguments passed to the method.

Derived syntax

(clr-indexer-get type instance arg ...) instance is a reference to the object of type . arg ... is the arguments passed to the indexer.
(clr-indexer-set! type instance arg ... expr) instance is a reference to the object of type . arg ... is the arguments passed to the indexer. expr is the value to set the indexer.
(clr-prop-get type property instance) property is the name of the property. Eg Height . instance is a reference to the object of type . Can be null ('()) for static properties.
(clr-prop-set! type property instance expr) property is the name of the property. Eg Height . instance is a reference to the object of type . Can be null ('()) for static properties. expr is the value to set the property.
(clr-static-call type method arg ...) method is a symbol for a simple name, eg ToInt32 or a string to resolve specific methods, eg "ToInt32(Object)" . arg ... is the arguments passed to the method.
(clr-static-event-add! type  event handler) event is a symbol for the name of the event. Eg Click . handler is a procedure taking the same number of arguments as the event's delegate.
(clr-static-event-remove! type  event handler) event is a symbol for the name of the event. Eg Click . handler is a procedure taking the same number of arguments as the event's delegate.
(clr-static-field-get type field) field is a symbol for the name of the field. Eg m_foo .
(clr-static-field-set! type field expr) field is a symbol for the name of the field. Eg m_foo . expr is the value to set the field.
(clr-static-prop-get type property) property is the name of the property. Eg Height .
(clr-static-prop-set! type property expr) property is the name of the property. Eg Height . expr is the value to set the property.

 

3.1,小試牛刀

看來支持得還挺全面,立刻寫個程序試試看:

(import
  (rnrs)
  (ironscheme clr))

;Define a function write-ln
(define (write-ln fmt . args)
  (clr-static-call System.Console WriteLine (clr-cast System.String fmt)
    (clr-cast System.Object[]
      (list->vector args))))

; And invoke it!
(write-ln "{0}" "Hello World!")
(write-ln "1:{0}" "aaa")
(write-ln "1:{0} 2:{1}" "張三" "李四")

這個程序是調用 .net的 Console.WriteLine 方法的,運行這個程序試試:

注意程序文件須要保存爲 UTF8格式的,IronScheme 才能夠正常顯示中文。

3.2,爲是麼要用 Scheme調用 .NET?

利用 Lisp的強大表達能力,調用.net強大的類庫

Scheme能夠看成腳本語言,能夠.net程序動態生成一個 Scheme程序,Scheme程序再調用.net。。。。 這個過程的用途,明白了吧?

好比工做流程序,調用一個Scheme 腳本..

 

參考資源

更多的 Lisp,Scheme學習資源,能夠參考下面的連接 :

Lisp 的永恆之道
http://www.oschina.net/question/28_57183


Scheme語言--簡介
http://blog.csdn.net/zzulp/article/details/5547729


學習Scheme
http://blog.csdn.net/ramacess/article/details/570769

 

Scheme 語言概要

http://www.ibm.com/developerworks/cn/linux/l-schm/index1.html

 

Read access to a .NET Assembly
https://ironscheme.codeplex.com/discussions/60977


Playing with IronScheme
http://www.codeproject.com/Articles/33050/Playing-with-IronScheme

尾遞歸

 http://blog.sina.com.cn/s/blog_3e5694650100tzqq.html

 

本文程序下載 「IronScheme中文版」

http://pwmis.codeplex.com/releases/view/117822

 

---------分界線 ----------------

 歡迎使用 PDF.NET SOD 開源框架,框架追求的目標是簡單與效率的平衡,體如今:代碼的精簡,開發、維護的簡單與追求極致的運行效率

做者簡介:

本人現任職架構師,求伯樂,聯繫方式:http://www.pwmis.com/sqlmap

相關文章
相關標籤/搜索