Clojure CLR 入门

简介:

  看过"黑客与画家"之后,你是不是对Lisp心动不已?然后翻了几页ACL(Ansi Common Lisp)又望而却步?叹息:如果有一天可以再.Net CLR 上写Lisp代码那就好了!这一天已经来了,这就是Clojure CLR.看语言转换矩阵, Clojure的寄生能力超强,这方面甚至超过javascript.在CLR上有一席之地不足为怪.

       
 
既然是入门,就必须回答下面几个问题:
  • 怎么安装?怎么运行REPL?
  • 使用什么IDE编写Clojure?
  • 如何编译clj文件?
  • Clojure CLR 与 Clojure JVM 有什么区别?
  • Clojure 如何调用 C#?
  • C# 如何调用Clojure?
  • Clojure如何调用.net WinForm ?
   
 

安装

 
    这第一步就不是太顺利,如果你从Github上(  https://github.com/clojure/clojure-clr ) 下载了代码编译的时候,你可能遇到特别多的问题,比如一开始你会发现lib文件夹中并没有项目依赖的Microsoft.Dynamic.dll和Microsoft.Scripting.dll.这个问题不大,只要到  http://dlr.codeplex.com/ 下载一份就可以了(下载解压拷贝等若干步骤省略),通过这个问题其实也可以知道Clojure CLR是构建在Microsoft's Dynamic Language Runtime (DLR)之上的.
   解决了引用的问题,紧接着就是编译项目,你可能会看到下面这个错误信息:
 
Error     16     The command "" D:\Code\clojure-clr-master\bin\4.0\Debug\Clojure.Compile.exe " clojure.core clojure.core.protocols clojure.main clojure.set clojure.zip  clojure.walk clojure.stacktrace clojure.template clojure.test clojure.test.tap clojure.test.junit clojure.pprint clojure.clr.io clojure.repl clojure.clr.shell clojure.string clojure.data clojure.reflect"  exited with code 1.     Clojure.Compile

 

  与其这样,我的选择是:直接用编译好的二进制包,不要在Clojure的门口逡巡太久.下载地址:  https://github.com/clojure/clojure-clr/wiki/Getting-binaries  http://sourceforge.net/projects/clojureclr/files/
 
 

运行REPL

 
   解压之后的目录里面只有一个带Clojure图标的Clojure.Main.exe,双击它,一个崭新的世界就来了:
 
复制代码
Clojure 1.4.1
user=> (+ 1 2)
3
user=> (println "hello world")
hello world
nil
user=>
复制代码

 

  

 
   如果你真的按照我上面一步一步来操作了,走到这里你可能会问:你是怎么把上面的文字拷贝出来的?Clojure.Main.exe是一个.net的Console Application,在界面鼠标上选中操作是不能直接使用的,我们可以先单击应用左上角的图标,出来编辑菜单,可以选择"select all",然后回车即可完成复制.还是截图来看看这个略显扯淡的操作方式:
 
 
 

Clojure IDE 

 
  不必专门找Clojure CLR的IDE,只要是Clojure的IDE都可以拿来用.备选方案有:Eclipse插件,Light Table,Vim插件,Emac 等等,按照自己的口味自己选吧,下面Stackoverflow上的讨论基本上包含了呼声比较高的几个Clojure IDE:
 
 
 

编译

 
  编写下面的文件hello.clj
(ns hello)
(println "hello world" 2013)
命令行完成编译:
 
C:\Clojure-CLR 1.4>Clojure.Compile.exe hello
Compiling hello to .hello world 2013
-- 415 milliseconds.
编译完成之后就会生成hello.clj.dll文件,拖入Reflector里面看看生成的代码是什么样子,注意下面的0x7ddL就是常量2013:
 
复制代码
public class __Init__
{
    // Fields
    protected internal static Var const__0;
    protected internal static AFn const__1;
    protected internal static Var const__2;
    protected internal static object const__3;

    // Methods
    static __Init__()
    {
        try
        {
            Compiler.PushNS();
            __static_ctor_helper_constants();
        }
        finally
        {
            Var.popThreadBindings();
        }
    }

    private static void __static_ctor_helper_constants()
    {
        const__0 = RT.var("clojure.core", "in-ns");
        const__1 = Symbol.intern(null, "hello");
        const__2 = RT.var("clojure.core", "println");
        const__3 = 0x7ddL;
    }

    public static void Initialize()
    {
        ((IFn) const__0.getRawRoot()).invoke(const__1);
        ((IFn) new hello$loading__16463__auto____5()).invoke();
        ((IFn) const__2.getRawRoot()).invoke("hello world", const__3);
    }
}
复制代码

 

  


Clojure CLR 与 Clojure JVM 有什么区别?

 
Clojure CLR项目的目标:

-- Implement a feature-complete Clojure on top of CLR/DLR.
-- Stay as close as possible to the JVM implementation.
-- Have some fun. 
 
 
 
 

Clojure 调用 C# 

 
  CLR interop is essentially the same as JVM interop. However, we have to make a number of extensions to allow for parts of the CLR object model that are not in the JVM.
 
 
 
复制代码
user=> (System.Console/WriteLine "Now we use Console Writeline")
Now we use Console Writeline
nil
 
 ;;读写文件
user=> (def file (System.IO.StreamWriter. "test.txt"))
#'user/file
user=> (.WriteLine file "===Hello Clojure ===")
nil
user=> (.Close file)
nil
user=> (println (slurp "test.txt"))
WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).
===Hello Clojure ===

nil
user=>
复制代码

 

  

 
我们把抓取Web页面的代码翻译成Clojure:
 
C#:
 
System.Net.WebClient webClient= new System.Net.WebClient();
byte[] bResponse = webClient.DownloadData("http://www.baidu.com");
Console.WriteLine(Encoding.UTF8.GetString(bResponse));

  

Clojure:
 
(import (System.Net WebClient))
(import (System.Text Encoding))

  (.GetString Encoding/UTF8 
       (.DownloadData (WebClient.) "http://www.baidu.com"))

 

 

 
我们继续在这个代码上做点文章,我们把它修改成一下放在hello.clj文件里面编译出来:

 

复制代码
(ns hello)
 
(import (System.Net WebClient))
(import (System.Text Encoding))

(defn getbaidu []
  (.GetString Encoding/UTF8 
       (.DownloadData (WebClient.) "http://www.baidu.com"))
)
复制代码

 

 
再一次把hello.clj.dll拖入Reflector,看生成的代码:
 
复制代码
[Serializable]
public class hello$getbaidu__11 : AFunction
{
    // Methods
    public override bool HasArity(int num1)
    {
        if (num1 != 0)
        {
            return false;
        }
        return true;
    }
 
    public override object invoke()
    {
        return Encoding.UTF8.GetString(new WebClient().DownloadData("http://www.baidu.com"));
    }
}
复制代码

   

 是不是上面有一个问题已经在不知不觉之间解决了?(如何在C#中调用Clj代码) 
  
 
 
Clojure 调用.net Winform 当然也不是问题 
  
  只要加载System.Windows.Forms程序集导入对应的类即可,示例代码如下:
 
复制代码
user=> (System.Reflection.Assembly/Load "System.Windows.Forms,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
#<RuntimeAssembly System.Windows.Forms, Version=4.0.0.0, Culture=neutral, Public
KeyToken=b77a5c561934e089>
user=> (import (System.Windows.Forms MessageBox))
System.Windows.Forms.MessageBox
user=> (MessageBox/Show "Hello world from clojure-clr!" "Clojure-CLR DialogBox")

OK
user=>
复制代码

 

 
 
Clojure CLR 旅行愉快 !
 
     
 
 最后小图一张:
 
目录
相关文章
|
Kubernetes 搜索推荐 前端开发
containerd 镜像构建工具 -- nerdctl 和 buildkit
containerd 镜像构建工具 -- nerdctl 和 buildkit
9101 0
|
5月前
|
域名解析 缓存 网络协议
阿里企业邮箱如何设置域名DNS解析?
阿里企业邮箱如何设置域名DNS解析?
718 2
阿里企业邮箱如何设置域名DNS解析?
|
6月前
|
人工智能 Java API
Java 正式进入 Agentic AI 时代:Spring AI Alibaba 1.1 发布背后的技术演进
Spring AI Alibaba 1.1 正式发布,提供极简方式构建企业级AI智能体。基于ReactAgent核心,支持多智能体协作、上下文工程与生产级管控,助力开发者快速打造可靠、可扩展的智能应用。
4707 43
|
12月前
|
网络协议 NoSQL Redis
Docker Compose--模板文件
Docker Compose--模板文件
1236 29
|
10月前
|
JSON API PHP
天气预报免费API接口【地址查询版】使用教程
本文介绍了如何使用中国气象局官方数据提供的免费天气预报API接口,通过省份和地点查询指定地区当日天气信息。该接口由接口盒子支持,提供JSON格式数据、GET/POST请求方式,并需注册获取用户ID和KEY进行身份验证。
5062 2
|
安全 Ubuntu Linux
在Linux中,如何进行系统升级?
在Linux中,如何进行系统升级?
|
监控 安全 测试技术
现在公司都在用的CI/CD框架到底是什么?
现在公司都在用的CI/CD框架到底是什么?
7042 1
|
测试技术 开发者 Ruby
Ruby领域特定语言(DSL)的神秘力量:如何让你的代码飞起来?
【8月更文挑战第31天】在软件开发领域,Ruby以简洁的语法和强大的表达能力著称,但面对复杂业务逻辑时,代码可能变得冗长难维护。此时,领域特定语言(DSL)成为解决问题的有效途径。DSL专为特定领域设计,使代码更贴近业务逻辑,提高可读性和可维护性。本文通过示例展示了如何在Ruby中开发DSL,包括使用解析器和宏功能创建一个简单的Web应用结构描述语言,并提出了定义清晰语法、避免滥用DSL等最佳实践,强调了测试与文档的重要性。
317 0
|
开发框架 .NET API
分享一个 ASP.NET Web Api 上传和读取 Excel的方案
分享一个 ASP.NET Web Api 上传和读取 Excel的方案
532 0