.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 == 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

 

 

 

 

 

 

 

 

 

 

 

 

 

信奥赛csp初赛高频考点【二分查找】(详细解析) 阅读详情

相关推荐

使用 IronScheme 进入 Scheme 编程语言的世界

Scheme 程序说声:hello world。先打开你的编辑器,创建一个称为 hello.ss 的文件,然后将下面的文本内容保存进去:;hello.ss (import (rnrs)) (begin ;显示 hello 文字 (display "hello world.") (newline) ) 第1行是注释。Scheme 会把分号(;)及在这行它...

dieya9669的博客 299

java中间语言汇编语言_中间语言(IL) | 学步园

一、IL与汇编语言IL是微软.NET平台上衍生出的一门中间语言.NET平台上的各种高级语言(如C#,VB,F#)的编译器会将各自的代码转化为IL。,其中包含了.NET平台上的各种元素,如“范型”,“类”、、“接口”、“模块”、“属性”等等。值得注意的是,各种高级语言本身可能根本没有这些“概念”在里头,如IronScheme是一个在.NET平台上的Scheme语言实现,其中根本没有前面提到的这些I...

weixin_35150962的博客 1013

IronScheme:跨.NET平台的R6RS符合规范的Scheme实现

IronScheme:跨.NET平台的R6RS符合规范的Scheme实现 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 IronScheme 是一个专为所有.NET实现和平台设计的Scheme方言实现,遵循R6RS规范。它旨在提供超过99%的R6RS标准特性,并具备完整的宏系统,与Icarus、Vicare和Chez等其他实现方式类似。 项目技术分析 R6RS兼容性...

gitblog_00014的博客 506

C#与IronScheme交互

IronScheme为C#版本的Scheme编译器,通过它可以实现scheme与C#之间的相互调用,scheme编写为库,C#直接调用scheme库函数,这样就可以动态加载scheme代码,完成调用。Scheme也可以调用C#中的库函数或自定义类,具体方法可见官方文档。下面讨论的是C#调用scheme函数。 1.      编写scheme库函数 ;Define a function wr

u014291956的专栏 937

.NET语言三剑客:IronScheme, IronLisp和Xacc

自从.NET DLR发布之后,社区里大名鼎鼎的Leppie,也就是Llewellyn Pritchard,积极致力于将Scheme与Lisp集成到.NET DLR中。最终的产品就是包含了集成开发环境的IronScheme与IronLisp,它们极大地丰富了开发者的开发体验。最近,InfoQ编辑有幸联 系到了Leppie,请他谈谈关于IronScheme与IronLisp的开发近况。Jame

phphot 1873

老赵书托(1)-SCIP

 也不知道博客园老赵先生是否同意转载,秉着与大家一起分享好书的原则,我还是先摘录如下,与大家共享。全文出处请大家访问老赵的博客:http://www.cnblogs.com/JeffreyZhao/archive/2009/07/15/recommended-reading-2-sicp.html 我要推荐的第一本书便是大名鼎鼎的《Structure and Interpretatio

华章IT官方博客 5042

.NET语言三剑客:IronScheme, IronLisp和Xacc[译]

文章链接:http://www.infoq.com/cn/news/2008/01/leppie-ironscheme

weixin_34220179的博客 145

rust_hdc:用纯 Rust 重写鸿蒙设备连接器(HDC),一颗 3MB 二进制替代整个 C++ 工具链

协议层是性能敏感 + 安全敏感的:HDC 走 TCP/USB 批量传输,分包、握手、并发会话,Tokio 异步运行时天然匹配;跨平台一致性:macOS(IOKit)、Linux(libusb)、Windows、OHOS,同一套代码一个 flag 切换目标;产出即库:Rust 生态的 crate 分发让"工具"和"库"天然合一,crates.io 发布后即用。HDC 协议不大——核心 500 行 Rust 就能说清楚——但它连接的是整个鸿蒙开发者生态的日常。

夏天的博客 128

C++】 定时器进阶:多层时间轮原理与任务迁移

单层时间轮虽然能够以较低的开销管理大量定时任务,但当任务延迟时间跨度很大时,要么需要大量槽位,要么需要额外维护轮数。多层时间轮通过将不同时间范围的任务放到不同层级中,实现类似“秒针、分针、时针”的分级管理。本文主要介绍多层时间轮为什么出现、各层如何划分、定时任务如何选择层级,以及高层任务如何逐步迁移到低层并最终执行。

qq_64148519的博客 107

【AI大模型接入SDK】Ollama API 流式增量响应

🎬 艾莉丝的简介: 1.2.2 curl 参数释义 :静默模式,屏蔽进度条、连接日志,仅输出响应内容 :指定 HTTP 请求方法为 POST :请求头,告知服务端请求体为 JSON 格式 :携带 POST 请求体 payload;bash 环境使用单引号包裹 JSON,避免 shell 解析 JSON 内部双引号 1.2.3 不同 stream 参数终端表现 :终端逐行吐出分片 JSON,模型边生成边返回数据 :阻塞等待模型全部推理完成,一次性输出完整 JSON 报文 1.3 Ollama 流式响

艾莉丝努力练剑的博客,感谢大家一直以来的对艾莉丝的支持和鼓励,uu们如果对C/C++方向感兴趣的话,可以通过艾莉丝主页的微信名片加艾莉丝的好友,和努力练剑的艾莉丝一起加油! 476

Linux的开发工具

包管理器就类似手机上的应用商店。

2401_88240248的博客 151

Person p2=Person(p) 的构造过程 和 RVO

C++17 的 guaranteed copy elision 使得 Person p2 = Person(p); 仅触发一次拷贝构造函数调用,且直接在 p2 的内存位置上完成构造,无需临时对象。Person(p) 不再代表独立的临时对象,而是“构造配方”,与 p2 的初始化为同一事件。p2 的地址始终不变,无搬运、无额外析构。此行为是标准保证,非优化结果,区别于旧版中可能发生的两次构造与移动。

jimy1的博客 135

嵌入式学习第38天——(汇编的基本使用(加减,函数声明;异常处理))

逻辑指令:and:与逻辑 orr: 或逻辑 eor:异或逻辑 bic:按位清0。算术指令:add:加法;rsc:反向带进位减法。比较逻辑:cmp:相当于C语言里的if。数据搬移:mov:相当于C语言里的赋值。

2503_90965834的博客 168

c语言保留标识符

不管是。

mingtiauigena的博客 281

C++进阶系列 (四)】关于线程堆栈的那些事——new、delete、delete[]

文章主要讲C++中new/delete的原理,包括构造析构、异常安全、delete[]的cookie机制、placement new等。本文从“包工头”比喻切入,剖析C++中new/delete的底层原理:new包含内存分配与构造,且具备异常安全回滚;delete先析构再释放。重点讲解delete[]通过头部Cookie记录元素个数、逆序析构,误用delete会导致UB。并延伸至内存池重载、placement new及底层malloc/free调用,帮助读者掌握内存管理核心。

2501_93095927的博客 430

实现pytorch resnet18功能(二,c++ cudnn)

/输出32*32*32-----------------------显然输入也是32*32*32。, _ci(ci), _co(co), _h(h), _w(w), _jjh(juanjihe), _pad(pading) {//int stride=2,juanjihe=1时,pading=0;原因是残差块中最后一步只实现了相加,并没有实现relu,所以这个架构中,所有残差块类都跟有relu!

ganggangwawa的博客 163
上一篇: 封装的一个用来下载图片的类
下一篇: 有关于认证和加密
weixin_33847182
博客等级 码龄11年 6143粉丝 803原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值