当决定再次继续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'); |