[{"data":1,"prerenderedAt":107},["ShallowReactive",2],{"\u002F2011-10-31-ocaml-study-note":3},{"id":4,"title":5,"body":6,"date":85,"description":12,"extension":86,"meta":87,"navigation":90,"path":102,"seo":103,"stem":104,"tags":105,"__hash__":106},"blogs\u002F_legacy\u002F2011\u002F2011-10-31-ocaml-study-note.md","OCaml学习札记",{"type":7,"value":8,"toc":81},"minimark",[9,13,16,19,22,25,28,31,34,45,56,59,65,68,71],[10,11,12],"p",{},"时间过得真快，一转眼2011就要结束了。",[10,14,15],{},"~~而我却还是一事无成呢，在心里认为自己很伟大以及在现实面前很平庸这样的矛盾真是让人痛苦啊（笑）。~~最近也是，不知道为什么就是什么也没干的过来了。最后发现只有正在学习的这门课程能够拿出来证明我真的活过了这几个月……",[10,17,18],{},"好吧，上面的都是闲话，这里直接切入正题。接触到ocaml是因为正在学函数式程序设计，英文好像叫 function programing 来着，记不清了。这里主要写一些自己学到的东西吧，当然不敢说是教程了。",[10,20,21],{},"ocaml是object caml的简称，而caml是ml的一种方言。它最主要的特点就是是一种函数式语言，据说这种语言可以减少代码量。而且设计上也更加适用于并行运算，因为它在设计上没有变量。没有变量就没有内存共享，这样就可以方便的进行并行运算了。",[10,23,24],{},"当然这都是被宣称的，真实情况就不是很清楚了。个人感觉，至少现在还不怎么流行就是了。主要这种语言要用的话原来的编程思路似乎得转变一下，然后它只提高了编程效率，对于运行效率却不太可能有什么提升。而且并行运算似乎也不是非它不可。现在编程的都是实用主义的，自然用的人就少了。在我看，这门语言目前比较适合对编程有些兴趣，想要挑战自己智商的人，因为它在具体的算法的设计和实现上确实比较精妙。不过F#是以ocaml为基础的，由于ocaml内部没有对应的图形库，所以F#必须搭配.net的其他语言才可以编出可视化的程序。",[10,26,27],{},"我想,学习一门新的语言对于程序员而言基本上是家常便饭了，所以基本上没有什么难的。",[10,29,30],{},"基本类型没有什么变化int、float、char、string、list都有,不过使用的时候不用事先声明习惯了c风格的童鞋可能会有点不习惯。",[10,32,33],{},"ocaml里最大的特点就是所谓的函数式程序的特性，也就说可以将函数定义好作为算子来使用。要说明的话太过于麻烦，而且要学语言最快的还是看代码。于是来看这段代码吧：",[35,36,41],"pre",{"className":37,"code":39,"language":40},[38],"language-text","let nextx a x = (a\u002F.x +. x) \u002F. 2.0;;\nlet rec findroot a x acc =\n  if abs_float (x -. nextx a x) \u003C acc *. x then\n    nextx a x\n  else\n    findroot a (nextx a x) acc  ;;\nlet sqroot a = findroot a 1.0 0.000001\n","text",[42,43,39],"code",{"__ignoreMap":44},"",[10,46,47,48,55],{},"这段代码是对牛顿逼近算法求平方根的一个实现，算法方面就不做解释了。可以看到nextx是用来求下一个逼近值的函数，而findroot则是主函数。在定义时需要递归的函数前必须加rec来声明，否则无法编译。这就是一段简单的ocaml程序，其实ocaml最主要的就是将函数编写成为通式来使用。这点和面向对象的一些思路很像，不过函数式语言最终的目的是将函数作为单体(",[49,50,54],"a",{"href":51,"rel":52},"http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMonad_%28functional_programming%29",[53],"nofollow","monad",")的运算子,以实现良好的有序操作或者控制流。",[10,57,58],{},"下面再给一段较为复杂的代码：",[35,60,63],{"className":61,"code":62,"language":40},[38],"type ´a tree = Leaf ¦ Node of ´a * ´a tree * ´a tree;;\n\nlet rec fold_tree f e t =\n   match t with\n    Leaf -> e ¦\n    Node (a,b,c) -> f (a, fold_tree f e b , fold_tree f e c) ;;\nlet height t = fold_tree (fun (a,b,c) -> (max b c) + 1 ) 0 t;;\nlet t1 =\n  Node ( \"a\" ,\n    Node (  \"b\" ,\n      Node ( \"c\" ,\n        Node ( \"d\" , Leaf , Leaf) , Leaf ) ,Leaf) ,Node ( \"e\" ,Leaf,Leaf));;\nlet balance t = ( fold_tree (fun (a,b,c) -> if (b = -1 ¦¦ c == -1 ) then (-1)\n    else\n      let ab =  abs (b-c) in\n      if ab \u003C= 1 then (max b c)+1\n      else (-1)\n    ) 0 t ) \u003C> (-1);;\n\nbalance (Node ( \"a\" , Leaf ,Leaf));;\nbalance t1;;\n",[42,64,62],{"__ignoreMap":44},[10,66,67],{},"这是一段用于检验二叉树是否平衡的代码。上面的代码首先定义了一个类型tree用来表示二叉树，使用的定义方式类似于离散数学中的归纳定义。也就是Leaf是二叉树，而一个节点下有两个子树也是二叉树。而fold_tree则是ocaml中比较常见的一种通式的写法，通过match匹配，对整棵树进行遍历。而fold_tree的参数f则是一个可以自定义的函数。下面的函数balance就是对fold_tree的一种应用。",[10,69,70],{},"据说很好的利用通式可以简化编程的代码量和降低算法的设计复杂度，在实际写过一段时间之后发现确实如此，函数式语言还是有些优点的。不过我还没有系统的对ocaml进行过学习当然也没有继续深入研究的打算，如果要深入研究的话我推荐一下语言参考，解释的还是非常详细的。同时也把我这段作为习作写的代码也上传了吧，里面有关单体的运用的那块不是我一个人写的，总之希望对正在学习的人有所帮助吧。",[72,73,74],"blockquote",{},[10,75,76,77],{}," 下载地址：",[49,78,79],{"href":79,"rel":80},"http:\u002F\u002F3721up.com\u002F4cve",[53],{"title":44,"searchDepth":82,"depth":83,"links":84},2,3,[],"2011-10-31","md",{"layout":88,"status":89,"published":90,"author":91,"author_login":92,"author_email":93,"author_url":94,"wordpress_id":95,"wordpress_url":96,"date_gmt":97,"excerpt":98},"post","publish",true,{"display_name":92,"login":92,"email":93,"url":94},"chaoshikari","chaoshikari@gmail.com","\u002F",94,"http:\u002F\u002Fwww.ch-wind.com\u002F?p=94","2011-10-31 14:29:19 +0000",{"type":7,"value":99},[100],[10,101,12],{},"\u002F2011-10-31-ocaml-study-note",{"title":5,"description":12},"_legacy\u002F2011\u002F2011-10-31-ocaml-study-note",[],"K_Xf-JfvgivqqbrUk3FZFNCRukwoIz6UbTybX7w3Yy4",1788763177945]