.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研究的第一站。
1,下载IronScheme源码
IronScheme在Codeplex上有开源项目, https://ironscheme.codeplex.com/ ,可以下载它的源码和编译好的程序,在 https://ironscheme.codeplex.com/SourceControl/latest 可以下载源码,我下载时候的文件名是 ironscheme-103684,下载的源码可以用VS2008打开。如果没有开发环境,直接用 debugbuild.bat 也就可以直接编译。另外还可以直接运行测试 r6rstest.bat
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.exe
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 == ); c = FinalLineText[];
}
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
.NET DLR 上的IronScheme 语言互操作&&IronScheme控制台输入中文的问题的更多相关文章
- JVM 平台上的各种语言的开发指南
JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...
- 我用爬虫一天时间“偷了”知乎一百万用户,只为证明PHP是世界上最好的语言
我用爬虫一天时间“偷了”知乎一百万用户,只为证明PHP是世界上最好的语言 2015-08-06 猿圈 我用爬虫一天时间“偷了”知乎一百万用户 只为证明PHP是世界上最好的语言 看了不少朋友圈里推荐的P ...
- 用Visual Studio Code Debug世界上最好的语言
前言 这阵子因缘巧合接手了一个辣鸡项目,是用世界上最好的拍黄片写的,项目基本是另一个小伙伴在撸码,我就兼职打杂和发布做点运维的工作. 然后昨天项目上了测试版之后,一用起来Error满天飞了.让小伙伴查 ...
- 世界上最好的语言搭建短链接及统计功能(附API代码)
前言 在这个营销的时代,短链接和二维码是企业进行营销中非常重要的工具,不仅仅是缩短了链接,而且还可以通过扩展获得更多的数据,诸如点击数.下载量.来源以及时间等等. 网上搜寻了一下比较有名有U.NU和0 ...
- 用Visual Studio Code Debug世界上最好的语言(Mac篇)
用Visual Studio Code Debug世界上最好的语言(Mac篇) 首先,你要有台Macbook Pro,接着才继续看这个教程. PS:Windows用户看这里用Visual Studio ...
- Ubuntu 12.04上安装R语言
Ubuntu 12.04上安装R语言 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ R的安装 sudo gedit /etc/apt/sources. ...
- 在windows上搭建C语言开发环境——借助eclipse和MinGW
0. 前言 [本文目的] 近期在电脑上又一次安装了MinGW,发现MinGW的安装方法和之前的方法稍有差别,全部再写了一篇博文记录一下具体的安装方法. [本文主要内容] ...
- php果然是世界上最好的语言
这两天参加Hackathon,作为一个什么都半吊子的家伙,两人小队伍被逼上岗,于是我不得不着手写代码.由此,我体验到了php的魔力-- 首先,我深刻地意识到了更新版本的重要性. 偷懒不想搭Apache ...
- 龙芯GO!龙芯平台上构建Go语言环境指南
龙芯软件生态系列——龙芯GO!龙芯平台上构建Go语言环境指南2016-07-05 龙芯中科1初识Go语言Go语言是Google公司于2009年正式推出的一款开源的编程语言,是由Robert Gries ...
随机推荐
- linux下配置mysql默认编码utf8
linux下配置mysql默认编码utf8 下面是需要在对应地方加入的配置 [client] default-character-set=utf8 [mysqld] character-set-ser ...
- Struts2学习笔记 - Action篇<配置文件中使用通配符>
有三种方法可以使一个Action处理多个请求 动态方法调用DMI 定义逻辑Acton 在配置文件中使用通配符 这里就说一下在配置文件中使用通配符,这里的关键就是struts.xml配置文件,在最简单的 ...
- KnockoutJS 3.X API 第四章 数据绑定(5) 控制流component绑定
本节目录: 一个例子 API 备注1:仅模板式的component 备注2:component虚拟绑定 备注3:传递标记到component绑定 内存管理 一个例子 First instance, w ...
- CCNA网络工程师学习进程(6)vlan相关协议的配置与路由器简单配置介绍
前面已经介绍了大部分与vlan技术相关的交换机的协议的配置,更深层次的还有STP协议和以太网端口聚合技术,接着还会简单介绍一下路由器的基本应用. (1)STP(Spanning-tre ...
- JSON学习之一
1.JSON:JavaScript Object Notation(javaScript对象表示法),JSON是存储和交换文本信息的语法,类似XML:JSON比XML更小,更快,更易解析: { &qu ...
- js高程读书笔记(1-3章)
一.js简介 js是一种专为与网页交互而设计的脚本语言,由以下三个不同的部分组成: 1.ECMAScript,由ECMA-262(它规定了语言的这些组成部分:语法,类型,语句,关键字,保留字,操作符, ...
- 信息加密之非对称加密算法RSA
前面为大家已经总结了,基于密钥交换的DH算法,现在就为大家再介绍一种基于因子分解的RSA算法,这种加密算法有两种实现形式:1.公钥加密,私钥解密:2.私钥加密,公钥解密.下面就为大家分析一下实现代码, ...
- SQL*Loader之CASE6
CASE6 1. SQL脚本 [oracle@node3 ulcase]$ cat ulcase6.sql set termout off rem host write sys$output &quo ...
- [转载]基于TFS实践敏捷-项目管理
最近,一直想让团队加入敏捷开发,但TFS2010用下来,并不是令人满意,还好,TFS2012横空出世了.相比TFS2010,TFS2012改进太多了,主要体现在以下方面: Team Web Acces ...
- javaccript学习1
1.javascript中的三种消息框 (1)警告框 警告框经常用于确保用户可以得到某些信息. 当警告框出现后,用户需要点击确定按钮才能继续进行操作. 语法: alert("文本" ...