打印

Hello Clojure

[复制链接]
123|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
张さん|  楼主 | 2018-10-4 09:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
hello, ge, fm, TI, AN
当决定再次继续FP学习后,在网上逛查了一下,发现还真不少:Erlang,Lisp,Haskell,OCaml,Scala等等。大解去了解了一下,感觉很多对于自己来说觉得要么不够实用,我的实用是能用它们来写出我能想像的大部分程序来,包括算法,视觉,网络等等。比如:Erlang据说它主要是用于写一些服务器方面的,用于平行处理的多;像其它的就没了解太多,最后还是主要关注于以前有所了解过的Lisp包括Scheme,用过emacs的都大概懂点ELisp,这东西就是神奇和好玩,但是也是很难。

查了很多Lisp和Scheme的东东,能用的库很少,虽然也有opencv之类的库(CL-OPENCV:https://github.com/ryepup/cl-opencv,更多的库可以上cliki.net查查),而且我现在还没搞清楚LISP怎么与C、C++等语言或库进行交互,也发现说LISP标准中是没有定义这部分的,难怪很多LISP及其方言的标准库很少,因为很多都得再造轮子(有篇很有趣的**分析得很好,用LISP的都是GEEK,GEEK就是喜欢制造轮子【来自:http://qiujj.com/static/clojure-handbook.html#_Toc339573157】)。

可是我就是喜欢LISP,怎么办?还好,发现了Clojure,名字很难拼很难念是吧?可是它很实用,它是在JVM上的LISP,就像JYTHON是JVM上的PYTHON一样(JYTHON很多年前就已经听说了,可是一直没有去了解过,现在才大概明白是个什么样的怪物)

好吧,终于找到了我真正想要的:实用的LISP,下来就是学习了。

最近学了点小皮毛,很多还是依葫芦画瓢。学东西得有目标,不然容易走火入魔或举步难进,学习曲 线会更长。

我的第一个项目是用Clojure把前面的FM实现一遍,但是又不可能把C++写的内核给抛 弃,得像JNI一样把它们串起来用。虽然一开始我就把自己的难度提升不少,可是这也是为了验证使用其它第三方语言编写的库(如 opencv, PCL等),为后面提供一些经验。

有了度娘和谷哥,我还是实现了自己的想法。


查了不少**,不少人用emacs,可是这东西我断断续续用了很多年,最后还是比较喜欢用vim(emacs还是杰哥用得好)。还有人说用eclipse,试过,如网上说难配置;最后就选项了不错的:IntelliJ Idea。



Clojure代码:

;; test.clj

(ns test (:import fm))

;; 设置jni使用到的dll路径

(System/setProperty "java.library.path"

  (str "d:\\my\\clojure\\test\\src;" (System/getProperty

        "java.library.path")))

(def my-fm (new fm))

(defn init-fm [] (.initFM my-fm))

(defn free-fm [] (.freeFM my-fm))

(defn select-fm [index] (.selectFM my-fm index))

(defn get-fm-size [] (.getFMSize my-fm))

(defn get-fm-id [index] (.getFMId my-fm index))

(defn get-fm-name [index] (.getFMName my-fm index))

(defn get-fm-** [index] (.getFM** my-fm index))

(defn select-channel [index] (.selectChannel my-fm index))

(defn get-channel-size [] (.getChannelSize my-fm))

(defn get-channel-id [index] (.getChannelId my-fm index))

(defn get-channel-name [index] (.getChannelName my-fm index))

(defn get-channel-** [index] (.getChannel** my-fm index))

(defn get-next-song [] (.getNextSong my-fm))

(defn get-song-size [] (.getSongSize my-fm))

(defn get-song-id [index] (.getSongId my-fm index))

(defn get-song-name [index] (.getSongName my-fm index))

(defn get-song-url [index] (.getSongURL my-fm index))

(defn get-song-artist-name [index] (.getSongArtistName my-fm

        index))

(defn get-song-artist-picture [index] (.getSongAlbumPicture

        my-fm index))

(defn get-song-album-name [index] (.getSongAlbumName my-fm

        index))

(defn get-song-album-picture [index] (.getSongArtistPicture

        my-fm index))

(defn get-song-lyrics [index] (.getSongLyrics my-fm index))

(init-fm)

(println "FM Size:" (get-fm-size))

(doseq

  (println

    "Id:" (get-fm-id i)

    "Name:" (get-fm-name i)

    "**:" (get-fm-** i)))

(select-fm 0)

(println "Channel Size:" (get-channel-size))

(doseq

  (println

    "Id:" (get-channel-id i)

    "Name:" (get-channel-name i)

    "**:" (get-channel-** i)))

(get-next-song)

(println "Song Size:" (get-song-size))

(doseq

  (println

    "Id:" (get-song-id i)

    "Name:" (get-song-name i)

    "URL:" (get-song-url i)))

(free-fm)



这里我用java写的一个类fm.class,里面是封装的navite的东东:

public class fm {

    public fm() { /* compiled code */ }

    public native boolean initFM();

    public native boolean freeFM();

    public native int getFMSize();

    public native boolean selectFM(int i);

    public native java.lang.String getFMId();

    public native java.lang.String getFMName();

    public native java.lang.String getFM**();

    public native java.lang.String getFMId(int i);

    public native java.lang.String getFMName(int i);

    public native java.lang.String getFM**(int i);

    public native int getChannelSize();

    public native boolean selectChannel(int i);

    public native java.lang.String getChannelId();

    public native java.lang.String getChannelName();

    public native java.lang.String getChannel**();

    public native java.lang.String getChannelId(int i);

    public native java.lang.String getChannelName(int i);

    public native java.lang.String getChannel**(int i);

    public native int getSongSize();

    public native boolean getNextSong();

    public native java.lang.String getSongId();

    public native java.lang.String getSongName();

    public native java.lang.String getSongURL();

    public native java.lang.String getSongLyrics();

    public native java.lang.String getSongArtistName();

    public native java.lang.String getSongArtistPicture();

    public native java.lang.String getSongAlbumName();

    public native java.lang.String getSongAlbumPicture();

    public native java.lang.String getSongId(int i);

    public native java.lang.String getSongName(int i);

    public native java.lang.String getSongURL(int i);

    public native java.lang.String getSongLyrics(int i);

    public native java.lang.String getSongArtistName(int i);

    public native java.lang.String getSongArtistPicture(int i);

    public native java.lang.String getSongAlbumName(int i);

    public native java.lang.String getSongAlbumPicture(int i);

     // .... 还有 ....

}



其中DLL的路径问题让我花了不少时间,最后还是用System.setProperty来设置"java.library.path"解决了。

如果上面除去前再次重新定义函数部分,也就很短的一小部分主要代码。

当然也可以不用再重新定义的,只是为了方便和函数名的习惯。



其中,JNI的调用我这里是继续了JAVA那一套,这里还一另一套办法,是直接调用JNA来处理,下面就是高手用它来调用C库的例子,此网站里还有不少通过clojure处理vision(视觉处理)的东东:

http://nakkaya.com/2009/11/16/java-native-access-from-clojure/



通过宏来定义一个jna-call,这段我还没看明白,有待研究:

(defmacro jna-call [lib func ret & args]

  `(let [library#  (name ~lib)

         function# (com.sun.jna.Function/getFunction library# ~func)]

     (.invoke function# ~ret (to-array [~@args]))))



调用C库的printf的例子:

(jna-call :c "printf" Integer "hello, Clojure [JNA]")



运行结果:

FM Size: 8

Id: DOUBAN_FM Name: 豆瓣电台 **: nil

Id: BAIDU_FM Name: 百度电台 **: nil

Id: SOGOU_FM Name: 搜狗电台 **: nil

Id: KUGOU_FM Name: 酷狗电台 **: nil

Id: NINEKU_FM Name: 九酷电台 **: nil

Id: KUWO_FM Name: 酷我电台 **: nil

Id: XIAMI_FM Name: 虾米电台 **: nil

Id: RADIO_FM Name: 凤凰电台 **: nil

Channel Size: 34

Id: 1 Name: 华语 **: nil

Id: 2 Name: 欧美 **: nil

Id: 4 Name: 八零 **: nil

Id: 6 Name: 粤语 **: nil

Id: 32 Name: 咖啡 **: nil

Id: 9 Name: 轻音乐 **: nil

Id: 10 Name: 电影原声 **: nil

Id: 27 Name: 古典 **: nil

Id: 8 Name: 民谣 **: nil

Id: 16 Name: R&B **: nil

Id: 13 Name: 爵士 **: nil

Id: 5 Name: 九零 **: nil

Id: 17 Name: 日语 **: nil

Id: 76 Name: 小清新 **: nil

Id: 18 Name: 韩语 **: nil

Id: 94 Name: 中国好声音 **: nil

Id: 20 Name: 女声 **: nil

Id: 7 Name: 摇滚 **: nil

Id: 61 Name: 新歌 **: nil

Id: 111 Name: Polo信仰年轻 **: nil

Id: 105 Name: 扬天敢留白 **: nil

Id: 22 Name: 法语 **: nil

Id: 14 Name: 电子 **: nil

Id: 15 Name: 说唱 **: nil

Id: 3 Name: 七零 **: nil

Id: 77 Name: Easy **: nil

Id: 78 Name: 91.1 **: nil

Id: 28 Name: 动漫 **: nil

Id: 98 Name: 全新宝来 **: nil

Id: 107 Name: earthmusic **: nil

Id: 108 Name: 翼搏新生 **: nil

Id: 109 Name: 全新奥迪Q3 **: nil

Id: 112 Name: 奥迪见地未来行 **: nil

Id: 142 Name: 行乐嘉年华 **: nil

Song Size: 5

Id: 1907685 Name: 静静的 URL:$('mp3_Vh0').innerHTML=AC_FL_RunContent('FlashVars', 'soundFile=http%3A%2F%2Fmr3.douban.com%2F201307201748%2F9e22f3c6c6c7387741295fb5d1b48ec7%2Fview%2Fsong%2Fsmall%2Fp1907685.mp3', 'width', '290', 'height', '24', 'allowNetworking', 'internal', 'allowScriptAccess', 'never', 'src', 'static/image/common/player.swf', 'quality', 'high', 'bgcolor', '#FFFFFF', 'menu', 'false', 'wmode', 'transparent', 'allowNetworking', 'internal');

Id: 1224241 Name: 思念是一种病 URL:$('mp3_N4a').innerHTML=AC_FL_RunContent('FlashVars', 'soundFile=http%3A%2F%2Fmr5.douban.com%2F201307201748%2F3bb9f3f84694ed1ed8a8973da91b1027%2Fview%2Fsong%2Fsmall%2Fp1224241.mp3', 'width', '290', 'height', '24', 'allowNetworking', 'internal', 'allowScriptAccess', 'never', 'src', 'static/image/common/player.swf', 'quality', 'high', 'bgcolor', '#FFFFFF', 'menu', 'false', 'wmode', 'transparent', 'allowNetworking', 'internal');

Id: 1382539 Name: 突然好想你 URL:$('mp3_eY9').innerHTML=AC_FL_RunContent('FlashVars', 'soundFile=http%3A%2F%2Fmr3.douban.com%2F201307201748%2F2549df7ca52f594fad590adc17f9a638%2Fview%2Fsong%2Fsmall%2Fp1382539.mp3', 'width', '290', 'height', '24', 'allowNetworking', 'internal', 'allowScriptAccess', 'never', 'src', 'static/image/common/player.swf', 'quality', 'high', 'bgcolor', '#FFFFFF', 'menu', 'false', 'wmode', 'transparent', 'allowNetworking', 'internal');

Id: 512889 Name: 如果你也听说 URL:$('mp3_Vay').innerHTML=AC_FL_RunContent('FlashVars', 'soundFile=http%3A%2F%2Fmr3.douban.com%2F201307201748%2Fc0f0eb8345e470fb70992bb18449c2a3%2Fview%2Fsong%2Fsmall%2Fp512889.mp3', 'width', '290', 'height', '24', 'allowNetworking', 'internal', 'allowScriptAccess', 'never', 'src', 'static/image/common/player.swf', 'quality', 'high', 'bgcolor', '#FFFFFF', 'menu', 'false', 'wmode', 'transparent', 'allowNetworking', 'internal');

Id: 1526541 Name: 下雨天 URL:$('mp3_Cvq').innerHTML=AC_FL_RunContent('FlashVars', 'soundFile=http%3A%2F%2Fmr5.douban.com%2F201307201748%2F579ec64bdd01f8b0028c56f6222828f4%2Fview%2Fsong%2Fsmall%2Fp1526541.mp3', 'width', '290', 'height', '24', 'allowNetworking', 'internal', 'allowScriptAccess', 'never', 'src', 'static/image/common/player.swf', 'quality', 'high', 'bgcolor', '#FFFFFF', 'menu', 'false', 'wmode', 'transparent', 'allowNetworking', 'internal');

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

448

主题

464

帖子

1

粉丝