﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet type="text/css" href="/style/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <title>FSherp RSS</title>
    <link>http://qianxun.net</link>
    <description>FSherp聚合资料</description>
    <generator>RainbowSoft Studio Z-Blog 1.6 Final Build 60816</generator>
    <language>zh-CN</language>
    <copyright>Copyright 2008 FSherp.cn Some Rights Reserved.</copyright>
    <pubDate>Fri, 20 Mar 2009 10:48:42 GMT</pubDate>
    <lastBuildDate>Fri, 20 Mar 2009 10:48:42 GMT</lastBuildDate>
    <item>
      <title>如何在Visual Studio 2008中编译F#程序</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2009/2/4637.shtml</link>
      <pubDate>20 Feb 2009 10:50:25</pubDate>
      <guid>http://qianxun.net/Post/2009/2/4637.shtml</guid>
      <description><![CDATA[<div>在Visual Studio 2008中,编译F#程序时,会出现警告(但不是错误),但是由于这个警告却使你的程序无法运行,不过大多数据这些警告都会有提示,提示你用.NET里的函数代替F#中的某些函数,但是这些.NET中的函数又不能像在C#中那样使用.</div><div>例如:</div><div>#light</div><div>let &quot;]<br />let two = &quot;two &quot; :: one<br />let three = &quot;three &quot; :: two<br />let rightWayRound = List.rev three<br />let printList l =<br />List.iter print_string l<br />print_newline()<br />let main() =<br />printList one<br />printList two<br />printList three<br />printList rightWayRound<br />main()</div><div>上面的程序在Visual Studio 2008编译时,会出现警告,提示List.iter print_string l一行中print_string要用Console.Write()代替,但是如果直接把print_string直接用Console.Write()或Console.Write也还是不行.</div><div>那么到底如果使用Console.Write()代替print_string在Viusal Studio 2008中通过编译呢,</div><div>注意Console.Wirite有多个重载版本,重载时要指明版本,这要用到匿名函数并对参数进行注解</div><div>所以上面的List.iter print_string l</div><div>可改写为List.iter (fun (x:string) -&gt; Console.Write(x)) l</div><div>这样就可以通过编译了.</div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>增强我们的Visual Studio（更新中）</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/12/4633.shtml</link>
      <pubDate>18 Dec 2008 16:06:44</pubDate>
      <guid>http://qianxun.net/Post/2008/12/4633.shtml</guid>
      <description><![CDATA[<div><p>这位同事是用Java的，最近的一个.NET项目中，他来帮我们做。所以他也开始使用VS2005了，我觉得他至少具有一条Java开发人员的典型特征&mdash;&mdash;对微软相当鄙夷，这个也就罢了，跟我没多大关系。其后在开发过程中，他经常抱怨VS2005不好用，又说Eclipse如何如何好用云云。说实话，本来我对微软及其产品也没有太多好感，但毕竟跟VS朝夕相处，日久生情，于是经常是他说VS哪个地方不好用，我就会为VS进行一番辩护。一段时间下来，至少也向他证明了，Eclipse的大部分功能VS2005也具备了；同时，不得不承认，VS2005的IDE有其不足。</p><p>于是我通过google找到一篇文章 <a href="http://msmvps.com/blogs/jon.skeet/archive/2005/12/22/79631.aspx" target="_blank"><font color="#000000">Visual Studio vs Eclipse</font></a>，想看看两者究竟对比如何。这篇文章里Jon Skeet更青睐于Eclipse，他提到了以下几点：</p><ul>    <li>定位类型/资源</li>    <li>重载智能感知</li>    <li>组织引入</li>    <li>JUnit集成</li>    <li>导航链接</li>    <li>SourceSafe集成</li>    <li>结构差异比较</li>    <li>保存时编译</li>    <li>组合的文件和类浏览器</li></ul><p>Jon Skeet认为，在上述方面Eclipse要强于VS2005，同时他也提到了VS2005的一些解决方案。</p><p><strong>1、<a href="http://www.usysware.com/DPack/Default.aspx" target="_blank"><font color="#000000">DPack</font></a></strong></p><p>DPack是一组用于VS 2003/2005的免费工具。其目标是极大地提高开发人员的生产力，自动化重复过程，对VS的一些特性进行扩展。它包含多个浏览器工具，帮助开发人员对类、方法和程序集类型快速定位。DPack也包括增强了的书签功能，各种代码导航工具以及改进了的Surround with功能。来看几幅截图：</p><p>1.1 代码浏览器</p><p>使用便利的对话框帮助开发人员快速定位到代码成员，如方法和属性。</p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/CodeBrowser_2.png"><img height="210" alt="CodeBrowser" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/CodeBrowser_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>它与VS2005中的&ldquo;Find Symbol&rdquo;不同。因为它是即时更新的搜索&mdash;&mdash;当你键入时，列表会即时更新。</p><p>1.2 文件浏览器</p><p>使用便利的对话框帮助开发人员快速定位到任意数量的文件。</p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/FileBrowser_2.png"><img height="144" alt="FileBrowser" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/FileBrowser_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>1.3 解决方案浏览器</p><p>解决方案浏览器是类浏览器和文件浏览器的结合。</p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SolutionBrowser_2.png"><img height="223" alt="SolutionBrowser" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SolutionBrowser_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>1.4 框架（Framework）浏览器</p><p>定位到一个类型，及其相应的命名空间和程序集。</p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/FCLBrowser_2.png"><img height="115" alt="FCLBrowser" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/FCLBrowser_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>1.5 计数书签（Numbered bookmark）</p><p>计数书签帮我们通过数字设置和定位书签。每个文件共有10个，从0到9。</p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/Bookmarks1_2.png"><img height="127" alt="Bookmarks1" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/Bookmarks1_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>1.6 Surround With</p><p>Surround With特性帮助我们用一些最常用的代码结构来包含选中代码。</p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SurroundWith_2.png"><img height="244" alt="SurroundWith" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SurroundWith_thumb.png" width="239" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>1.7 代码导航</p><p>代码导航功能帮助我们在代码元素间跳转。</p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/CodeNav_2.png"><img height="79" alt="CodeNav" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/CodeNav_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>1.8 解决方案统计数据</p><p>解决方案统计工具帮助我们评估整个解决方案的体积。包括文件数，代码行数等。</p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SolutionStats_2.png"><img height="84" alt="SolutionStats" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SolutionStats_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>1.9 解决方案备份工具</p><p>备份工具可用来备份整个解决方案或其中的单个项目。</p><p>&nbsp;<a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SolutionBackup1_2.png"><img height="124" alt="SolutionBackup1" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SolutionBackup1_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p><a href="http://www.cnblogs.com/images/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SolutionBackup2_2.png"><img height="122" alt="SolutionBackup2" src="http://images.cnblogs.com/cnblogs_com/anderslly/WindowsLiveWriter/VisualStudio_11EEE/SolutionBackup2_thumb.png" width="244" border="0" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" /></a></p><p>1.10 支持选项</p><p>1.11 键盘架构</p><p>该插件确实非常方便好用，<strong>强烈推荐</strong>！</p><p>2. <a href="http://www.testdriven.net/" target="_blank"><font color="#000000">TestDriven.NET</font></a></p><p>我们可以单独使用NUnit，但这需要经常在VS和NUnit间切换，TestDriven.NET与VS集成，可以免除此痛。</p><p>3. <a href="http://www.roland-weigelt.de/ghostdoc/" target="_blank"><font color="#000000">GhostDoc</font></a></p><p>GhostDoc是Visual Studio的一个免费插件，可以帮助开发人员编写XML格式的注释文档。我曾翻译过一篇<a href="http://www.cnblogs.com/anderslly/archive/2006/12/14/ghostdocintroduction.html" target="_blank"><font color="#000000">对其介绍的小文</font></a>，有兴趣看看。</p><p>4. <a href="http://www.gotdotnet.com/Community/UserSamples/Download.aspx?SampleGuid=91D1A529-0288-46D4-AE57-17446A6058F7" target="_blank"><font color="#000000">PInvoke.NET</font></a></p><p>PInvoke.NET是一个wiki，用于建立正确的P/Invoke签名。</p><p>先写这些，大家手头有什么好东东，也来一起推荐吧，把我们的VS打造为更好的IDE！</p><p>更新:2007-10-23</p><p>5.<span id="ctl00_ctl00_Content_TabContentPanel_Content_wikiSourceLabel"> <a href="http://www.codeplex.com/vssdkassist" target="_blank"><font color="#000000">VSSDK Assist</font></a></span></p><p>芭蕉兄提供,一个用于扩展VS的可视化工具集,目标是提供扩展VS的工具和指导.</p><p>6. Microsoft Visual Studio 2005 IDE Enhancements</p><p>主要功能:</p><ol>    <li>Index Find</li>    <li>代码结构查看器</li>    <li>文件比较</li></ol><p>下载请点击<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=CD7C6E48-E41B-48E3-881E-A0E6E97F9534&amp;displaylang=en" target="_blank"><font color="#000000">这里</font></a>.园子里的介绍页面<a href="http://www.cnblogs.com/yanrongpi/archive/2006/10/29/543835.html" target="_blank"><font color="#000000">链接</font></a>.</p><p>更新:2007-10-24</p><p>7. <a href="http://www.codeplex.com/modeling"><font color="#000000">PowerToys for the Class Designer and Distributed System Designer</font></a></p><p>这组Add-In增强了VS2005中已有的类设计器和分布式系统设计器的功能。</p><p>8. <a href="http://bordecal.mvps.org/Nicole/ImportsSorter/" target="_blank"><font color="#000000">Bordecal.ImportsSorter add-in for Visual Studio 2005</font></a></p><p>我们在文件的开头可能会引入多个命名空间，包括.NET Frameword的，第三方，我们自己的，如果手动写还好些，如果是采用快捷键Shift+Alt+F10导入的，就可能比较乱了，该Add-In就可以帮我们来整理排序。其排序规则一定程度上还可定制。</p><p>9. <a href="http://www.slickedit.com/content/view/441" target="_blank"><font color="#000000">SlickEdit Gadgets for Microsoft Visual Studio 2005</font></a></p><p>几个颇有意思的小玩意儿。</p><p>10. <a href="http://weblogs.asp.net/gmilano/archive/2005/11/10/430240.aspx" target="_blank"><font color="#000000">CoolCommands for Visual Studio 2005 RTM</font></a></p><p>在VS中添加多个有用的命令。</p><p>11. <a href="http://www.codeplex.com/ResourceRefactoring" target="_blank"><font color="#000000">Resource Refactoring Tool</font></a></p><p>为开发人员提供一种简单的方式,将代码中的字符串硬编码提取到资源文件中。</p><p>12. <a href="http://codebetter.com/blogs/scott.bellware/archive/2006/02/28/139446.aspx" target="_blank"><font color="#000000">NUnit Code Snippets for Visual Studio 2005</font></a></p><p>针对NUnit的一些Code Snippet。</p><p>13. <span class="h1"><a href="http://www.csharper.net/blog/mru_cleaner_v1_0_0_5___now_serving_your_file_cleaning_needs.aspx" target="_blank"><font color="#000000">MRU Cleaner v1.0.0.5</font></a></span></p><p>MRU即Most Recently Used, 指VS中的Recent Files和Recent Projects列表。在开发过程中，对于有些项目/文件，我们可能以后不再打开了；或者已经移除了；或者是通过添加已存在的项目命令打开的，我们都不希望在MRU列表中看到，该add-in可以帮助我们进行整理。</p><p>14. <a href="http://www.csharper.net/blog/clipboard_manager_upgraded_to_package.aspx#new_clipboard_manager_upgrade_1_0_0_4.aspx" target="_blank"><font color="#000000">Clipboard Manager</font></a></p><p>维护剪贴板的内容，而且可以将这些内容&ldquo;持久化&rdquo;到机器上，非常方便！</p><p>15. <a href="http://www.devexpress.com/go/CodeRushX.aspx" target="_blank"><font color="#000000">CodeRush Xpress for C#</font></a></p><p>它包含了Code Rush和Refactor! Pro中的一些特性，这些特性包括增强的导航、选择工具、代码创建功能以及强大的重构支持。</p><p>&nbsp;</p><p>最后，推荐两个链接，这里有大量有用的东东：</p><p><a href="http://www.hanselman.com/blog/CommentView.aspx?guid=cbb7f3df-b9dd-4a4a-8cc6-83d87c117d26" target="_blank"><font color="#000000">Scott Hanselman's 2005 Ultimate Developer and Power Users Tool List</font></a></p><p><a href="http://en.csharp-online.net/Category:Visual_Studio_2005_Add-ins" target="_blank"><font color="#000000">Visual Studio 2005 Add-ins List on en.csharp-online.net</font></a></p><p><strong>另</strong>：很感谢这位同事，他的偏执给我留下了很深的印象。我想作为一个程序员，是应该具备一定的偏执，它一定程度上反映了对程序的热爱，唯有热爱，才能有所成就。</p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>F#探险之旅（八）：使用F#开发Windows应用程序</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/12/4632.shtml</link>
      <pubDate>18 Dec 2008 16:06:01</pubDate>
      <guid>http://qianxun.net/Post/2008/12/4632.shtml</guid>
      <description><![CDATA[<div><p><b>我们身在何处？</b> <br /><br />前面<a href="http://www.cnblogs.com/anderslly/archive/2008/10/08/fs-posts-indices.html" target="_blank"><font color="#000000">写过的随笔</font></a>主要关注的是F#与FP的基本概念，对UI涉及很少。我们知道，没有UI就没法与用户进行交互，所以写两篇随笔来了解一下这方面的内容。本文主要关注的是如何使用F#开发WinForm应用程序，后面还会介绍如何使用F#开发ASP.NET应用程序。<br /><br />不过说真的，我对WinForm开发了解不多，所以如果有不妥之处，欢迎您的指正。<br /><br />WinForm中的基础类型是System.Windows.Forms.Form类，通过它我们可以创建一个窗体，在窗体上我们可以根据需要进行绘制。绘制的时候我们可以选择使用.NET提供的API手工&ldquo;画&rdquo;出一些图形，比如像素着色、直线、圆等等，也可以使用.NET里面的一些标准控件，比如文本框、按钮等等。接下来基于Windows应用的事件驱动的特性，通过事件（Event）和事件处理函数（Event Handler）使用户可与程序进行交互。另外，如果标准控件或窗体不能满足需要，我们还可以对其进行扩展，创建用户控件和自定义控件。<br /><br />下面就来看看如何实现这些过程。<br /><br /><b>分析 </b><br /><br />在使用C#开发的WinForm应用中可以看到，我们创建的新窗体类继承了System.Windows.Forms.Form类，在程序的入口函数Main中，有一行关键的代码：</p><div class="cnblogs_code"><img id="Code_Closed_Image_215848"  height="16" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" alt="" /><img id="Code_Open_Image_215848"  height="16" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" alt="" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_215848">C# Code</span><span id="Code_Open_Text_215848"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">Application.Run(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;MainForm());</span></span></div><p><br />也就是说创建Form类的一个实例，传给Application.Run方法，程序由此开始执行。使用C#开发的一大优势在于VS IDE提供的窗体设计器，这样就可以在设计时设置窗体和控件的属性，VS会为我们生成代码，从而大大提高了开发效率。<br /><br />遗憾的是，VS还没有为F#提供这样的设计时支持，也就是说我们必须手工编写所有的代码，那如果界面很复杂，不得累死啊？也不尽然。首先考虑下面的简化了的三层架构示意图：<br /><img src="http://pic002.cnblogs.com/img/anderslly/200812/2008121721593512.jpg" alt="" /> <br />这里并不是说程序一定要分为三层，或者说三个Project，而是说从逻辑上大体可以这样来看。大部分情况下，与设计器相关的只有UI层（不要忘了其它地方VS也可以生成代码），如果UI相当简单，完全手工编写这些代码也没什么大问题，如果UI相当复杂，就得考虑别的办法了。<br /><br />F#基于.NET平台，在这一点上，它与C#、VB.NET是平等的，这一次我们又可以获益于它的<b>互操作性（Interoperability）</b>了！既然C#类库可被F#调用，如果我们把窗体类放在一个类库内不就可以了吗？这样一方面我们可以利用VS的设计时支持，另一方面又可利用F#带来的好处，岂不妙哉？退一步讲，我们也没必要非得使用F#开发UI部分，完全可以使用C#开发UI，其余部分使用F#开发，这也是不错的方法。<br /><br />总结上面的分析，可以得到这样的结论：<b>在开发WinForm应用时使用F#，如果UI非常简单（比如画出一条数学曲线或者只有两三个控件的小工具等），我们完全可以手工编写所有代码；如果UI比较复杂，我们使用C#开发UI类库供F#调用，也可以只采用F#编写UI之外部分的代码</b>。<br /><br />下面我们来讨论下这三种方法的具体实现。<br /><br /><b>使用F#手工编写所有UI代码 </b><br /><br />前面写过的一篇<a href="http://www.cnblogs.com/anderslly/archive/2008/10/10/mandelbrot-set-by-fsharp.html" target="_blank"><font color="#000000">使用F#绘制Mandelbrot集合</font></a>就是这么做的，因为窗体上根本就没有任何控件，此时需要处理Paint事件完成窗体的绘制。这里再提供一个简单的例子，使用WebBrowser控件创建简单的浏览器：</p><div class="cnblogs_code"><img id="Code_Closed_Image_224107"  height="16" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" alt="" /><img id="Code_Open_Image_224107"  height="16" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" style="display: none" alt="" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_224107">F# Code - Simple Web Browser</span><span id="Code_Open_Text_224107" style="display: none"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /><br /></span><span style="color: #0000ff">open</span><span style="color: #000000">&nbsp;System<br /></span><span style="color: #0000ff">open</span><span style="color: #000000">&nbsp;System.Drawing<br /></span><span style="color: #0000ff">open</span><span style="color: #000000">&nbsp;System.Windows.Forms<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;Create&nbsp;the&nbsp;progressbar.</span><span style="color: #008000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000">&nbsp;statusProgress&nbsp;=<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ToolStripProgressBar(Size&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Size(</span><span style="color: #800080">200</span><span style="color: #000000">,&nbsp;</span><span style="color: #800080">16</span><span style="color: #000000">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Style&nbsp;=&nbsp;ProgressBarStyle.Marquee,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Visible&nbsp;=&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">)<br /></span><span style="color: #0000ff">let</span><span style="color: #000000">&nbsp;status&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;StatusStrip(Dock&nbsp;=&nbsp;DockStyle.Bottom)<br />status.Items.Add(statusProgress)&nbsp;</span><span style="color: #000000">|</span><span style="color: #000000">&gt;&nbsp;ignore<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;Create&nbsp;controls</span><span style="color: #008000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000">&nbsp;toolbar&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ToolStrip(Dock&nbsp;=&nbsp;DockStyle.Top)<br /></span><span style="color: #0000ff">let</span><span style="color: #000000">&nbsp;address&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ToolStripTextBox(Size&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Size(</span><span style="color: #800080">400</span><span style="color: #000000">,&nbsp;</span><span style="color: #800080">25</span><span style="color: #000000">))<br /></span><span style="color: #0000ff">let</span><span style="color: #000000">&nbsp;browser&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;WebBrowser(Dock&nbsp;=&nbsp;DockStyle.Fill)<br /></span><span style="color: #0000ff">let</span><span style="color: #000000">&nbsp;go&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ToolStripButton(DisplayStyle&nbsp;=&nbsp;ToolStripItemDisplayStyle.Text,&nbsp;Text&nbsp;=&nbsp;</span><span style="color: #800000">&quot;</span><span style="color: #800000">Go</span><span style="color: #800000">&quot;</span><span style="color: #000000">)<br />address.KeyPress.Add(</span><span style="color: #0000ff">fun</span><span style="color: #000000">&nbsp;e&nbsp;</span><span style="color: #000000">-&gt;</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(e.KeyChar&nbsp;=&nbsp;</span><span style="color: #800000">'</span><span style="color: #800000">\r</span><span style="color: #800000">'</span><span style="color: #000000">)&nbsp;</span><span style="color: #0000ff">then</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;browser.Url&nbsp;</span><span style="color: #000000">&lt;-</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Uri(address.Text))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />go.Click.Add(</span><span style="color: #0000ff">fun</span><span style="color: #000000">&nbsp;e&nbsp;</span><span style="color: #000000">-&gt;</span><span style="color: #000000">&nbsp;browser.Url&nbsp;</span><span style="color: #000000">&lt;-</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Uri(address.Text))<br />toolbar.Items.Add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ToolStripLabel(</span><span style="color: #800000">&quot;</span><span style="color: #800000">Address:</span><span style="color: #800000">&quot;</span><span style="color: #000000">))&nbsp;</span><span style="color: #000000">|</span><span style="color: #000000">&gt;&nbsp;ignore<br />toolbar.Items.Add(address)&nbsp;</span><span style="color: #000000">|</span><span style="color: #000000">&gt;&nbsp;ignore<br />toolbar.Items.Add(go)&nbsp;</span><span style="color: #000000">|</span><span style="color: #000000">&gt;&nbsp;ignore<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;Browser&nbsp;control&nbsp;event&nbsp;handlers.</span><span style="color: #008000"><br /></span><span style="color: #000000">browser.Navigating.Add(</span><span style="color: #0000ff">fun</span><span style="color: #000000">&nbsp;e&nbsp;</span><span style="color: #000000">-&gt;</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;statusProgress.Visible&nbsp;</span><span style="color: #000000">&lt;-</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">)<br />browser.DocumentCompleted.Add(</span><span style="color: #0000ff">fun</span><span style="color: #000000">&nbsp;e&nbsp;</span><span style="color: #000000">-&gt;</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;statusProgress.Visible&nbsp;</span><span style="color: #000000">&lt;-</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address.Text&nbsp;</span><span style="color: #000000">&lt;-</span><span style="color: #000000">&nbsp;browser.Url.AbsoluteUri)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #0000ff">let</span><span style="color: #000000">&nbsp;form&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Form(Text&nbsp;=&nbsp;</span><span style="color: #800000">&quot;</span><span style="color: #800000">Web&nbsp;Browser&nbsp;Sample</span><span style="color: #800000">&quot;</span><span style="color: #000000">,&nbsp;Size&nbsp;=&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Size(</span><span style="color: #800080">800</span><span style="color: #000000">,&nbsp;</span><span style="color: #800080">600</span><span style="color: #000000">))<br />form.Controls.Add(toolbar)<br />form.Controls.Add(status)<br />form.Controls.Add(browser)<br />form.PerformLayout()<br />form.Show()<br /><br />[&lt;STAThread</span><span style="color: #000000">&gt;]</span><span style="color: #000000"><br />Application.EnableVisualStyles()<br />Application.Run(form)</span></span></div><p><br />像这样的小工具，也没必要兴师动众，劳驾C#了。试试浏览一下博客园：<br /><img height="386" src="http://pic002.cnblogs.com/img/anderslly/200812/2008121722454034.jpg" width="593" alt="" /><br /><br /><b>注意</b>：看看上面例子的事件处理函数是怎么写的，比如go按钮的Click事件。我们知道C#中控件的事件处理函数一般有两个参数sender（:object）和e（:EventArgs），这里却只有一个，这是因为<b>对于标准的.NET事件，F#会忽略第一个参数</b>。<br /><br /><b>在F#中使用C#开发的UI类库</b> <br /><br />前段时间看到一个例子，是<a href="http://www.c-sharpcorner.com/UploadFile/scottlysle/FindListProcessesCS09102007024714AM/FindListProcessesCS.aspx" target="_blank"><font color="#000000">使用C#中获取本机的进程信息</font></a>，感觉它难易适中，就用它做例子吧。在原文中，只有两个主要的文件，一是工具类ProcessValidation.cs，一是窗体类Form1.cs，现在我们就是要把Form1分为两部分，UI设计器相关的部分放在C#类库中，后台的代码则采用F#编写，顺便把ProcessValidation类也改为F#代码。 <br /><img src="http://pic002.cnblogs.com/img/anderslly/200812/2008121722031041.jpg" alt="" /> <br />不过这里我按照自己的习惯给它们重新命名了，窗体是ProcessChecker，工具类是processHelper，然后在processFinder使用其中的窗体和控件，最后在Program类中定义了入口函数（FsSamples.UI中的其它文件可以略过）。<br /><br />这个过程比较简单，不过有个小问题。在C#中定义的窗体类中，各个控件在默认情况下是private的，如何在processFinder中使用呢？要想把它们暴露出来有几种方法，一是把private改为public，这样虽然简单，不过不是一个好的practice；二是把控件封装为public的属性，这样做如果控件少还比较好办，多了也很麻烦；我这里采用的是第三种方法（来自<a href="http://www.cnblogs.com/allenlooplee/" target="_blank"><font color="#000000">Allen Lee</font></a>的建议），即把控件的private修饰符改为protected，然后继承该窗体，这样仍有比较好的封装性，操作起来也比较简单，只要选中要修改的控件，把它们的Modifiers属性设置为Protected就可以了。（<a href="http://files.cnblogs.com/anderslly/FsWinSamples.zip" target="_blank"><font color="#000000">下载示例代码</font></a>）<br /><br />值得一提的是，在Application.Run方法之前，要添加一行代码：</p><p>&nbsp;</p><div class="cnblogs_code"><img id="Code_Closed_Image_220508"  height="16" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" alt="" /><img id="Code_Open_Image_220508"  height="16" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" alt="" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_220508">F# Code</span><span id="Code_Open_Text_220508"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">Application.EnableVisualStyles()</span></span></div><p><br />这样就可以使用XP/Vista的可视化样式了。程序的运行效果为：<br /><img src="http://pic002.cnblogs.com/img/anderslly/200812/2008121722134214.jpg" alt="" /><br /><br /><b>仅使用F#开发UI之外的代码</b> <br /><br />得益于F#与其它.NET语言良好的互操作性，我们可以在C#中开发UI部分，然后调用F#类库，这个过程跟调用C#开发的类库相比没有很大的区别，在此就不赘述了。<br /><br /><b>其它</b> <br /><br />关于WinForm开发的主题还有创建用户控件、自定义控件等，这方面已经有大量的资料了，相信使用本文的方法，开发起来也不会很难:)<br /><br /><b>小结</b> <br /><br />本文主要讨论了如何使用F#开发Windows应用程序。通过分析，确定了三种主要的方法，重点讨论了如何在F#中利用VS中的窗体设计器，这会使WinForm程序的开发简单不少。其中的一个例子是processFinder，它可以获取当前机器上的进程和应用程序信息。<br /><br />（<a href="http://files.cnblogs.com/anderslly/FsWinSamples.zip" target="_blank"><font color="#000000">下载示例代码</font></a>）<br />（要了解本人所写的其它F#随笔请查看 <a href="http://www.cnblogs.com/anderslly/archive/2008/10/archive/2008/10/08/fs-posts-indices.html" target="_blank"><font color="#000000">F#系列随笔索引</font></a>）<br /><br />参考 <br />《Foundations of F#》 by Robert Pickering<br />《Expert F#》 by Don Syme , Adam Granicz , Antonio Cisternino<br /><a href="http://www.c-sharpcorner.com/UploadFile/scottlysle/FindListProcessesCS09102007024714AM/FindListProcessesCS.aspx" target="_blank"><font color="#000000">Finding and Listing Processes in C# </font></a></p><p>&nbsp;</p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>Fashion Your Firefox</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/12/4631.shtml</link>
      <pubDate>18 Dec 2008 16:05:17</pubDate>
      <guid>http://qianxun.net/Post/2008/12/4631.shtml</guid>
      <description><![CDATA[<div><p>毫无疑问的，我们现在呆在网路上的时间要比走在路上的时间要多。在这里我们也怕堵车:-}，我们都希望能快点找到想要的东西。</p><p>还有，时间久了，也想把浏览器打扮地漂亮点儿。嗯，Mozilla推出了一个Add-on精选包&mdash;&mdash;<a href="https://addons.mozilla.org/en-US/firefox/fashionyourfirefox/" target="_blank"><font color="#000000">Fashion Your Firefox</font></a>，也许能满足一下这方面的需求吧。</p><p>1. Finder and Seeker</p><p>&nbsp;&nbsp;&nbsp; 就是更简单地找到更合适的信息，<a href="https://addons.mozilla.org/en-US/firefox/addon/138" target="_blank"><font color="#000000">StumbleUpon</font></a>很不错；</p><p>2. Social Butterfly</p><p>&nbsp;&nbsp;&nbsp; 给那些热衷于网络交际的人们准备的，通讯录、分享照片、发布公告等等；</p><p>3. ShutterBug</p><p>&nbsp;&nbsp;&nbsp; 在线浏览和分享图片和视频，<a href="https://addons.mozilla.org/en-US/firefox/addon/5579" target="_blank"><font color="#000000">Cooliris</font></a>确实很酷；</p><p>4. Digital Pack Rat</p><p>&nbsp;&nbsp;&nbsp; 方便地收藏站点、书签、博客。。。；</p><p>5. Rock Star</p><p>&nbsp;&nbsp;&nbsp; 哈，把摇滚歌手放在Firefox来吧；</p><p>6. Decorator</p><p>&nbsp;&nbsp;&nbsp; 来把Firefox打扮一下，<a href="https://addons.mozilla.org/en-US/firefox/addon/72" target="_blank"><font color="#000000">Noia</font></a>和<a href="https://addons.mozilla.org/en-US/firefox/addon/1368" target="_blank"><font color="#000000">ColorfulTabs</font></a>；</p><p>7. Shopaholic</p><p>&nbsp;&nbsp;&nbsp; 购物狂们的选择；</p><p>8. News Junkie</p><p>&nbsp;&nbsp;&nbsp; 发生在世界各地的最新闻和天气预报，每天早上喝点<a href="https://addons.mozilla.org/en-US/firefox/addon/2677" target="_blank"><font color="#000000">Morning Coffee</font></a>；</p><p>9. Executive Assistant</p><p>&nbsp;&nbsp;&nbsp; 我只是一个普通的程序员，现在也可以有小秘啦，<a href="https://addons.mozilla.org/en-US/firefox/addon/1191" target="_blank"><font color="#000000">ReminderFox</font></a>给一个TodoList，还有<a href="https://addons.mozilla.org/en-US/firefox/addon/3481" target="_blank"><font color="#000000">Glue</font></a>也很棒；</p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>F#探险之旅（七）：在F#中进行单元测试</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/12/4630.shtml</link>
      <pubDate>18 Dec 2008 16:04:36</pubDate>
      <guid>http://qianxun.net/Post/2008/12/4630.shtml</guid>
      <description><![CDATA[<div><p><strong>单元测试</strong>是开发者编写的一小段代码，用于检验被测代码的一个很小的、很明确的功能是否正确。通常情况下，一个单元测试（用例）用于判断某个特定条件（或场景）下特定函数的行为。如果想对单元测试的好处有更多的了解，可以看一下<a href="http://www.cnblogs.com/anderslly/archive/2008/03/21/unit-test-in-action-introduction.html" target="_blank"><font color="#000000">单元测试实战</font></a>。</p><p>在.NET社区内，<a href="http://www.nunit.org/" target="_blank"><font color="#000000">NUnit</font></a>无疑是最经典的单元测试工具，要了解它的用法，建议看一下园子里的一篇很棒的文章<a href="http://confach.cnblogs.com/archive/2005/06/20/177817.html" target="_blank"><font color="#000000">NUnit详细使用方法</font></a>。本文对此不再赘述。另外<a href="http://www.mbunit.com/Default.aspx" target="_blank"><font color="#000000">MbUnit</font></a>作为后起之秀，也很值得一试。</p><p>在F#中， <a href="http://blogs.msdn.com/chrsmith/archive/2008/05/30/language-oriented-programming-in-f.aspx" target="_blank"><font color="#000000">LOP</font></a>（<a href="http://en.wikipedia.org/wiki/Language-oriented_programming" target="_blank"><font color="#000000">Language-Oriented Programming</font></a>）是它的一个亮点，而FsUnit则是LOP的一个很好的实践。<a href="http://code.google.com/p/fsunit/" target="_blank"><font color="#000000">FsUnit</font></a>使用F#开发，用它编写的测试用例会接近于自然语言（英语），在其中我们也可以看到F#对函数进行组合的强大威力。</p><p>在本文中，我将通过简单的例子分别对NUnit和FsUnit的基本用法进行介绍。假定我们在开发一个类库MyFsLib，其中有一个模块mathHelper，里面有一些关于数学的函数，现在要做的就是测试这些函数。mathHelper的代码如下：</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_132859"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" /><img id="Code_Open_Image_132859"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_132859">F# Code - mathHelper的签名</span><span id="Code_Open_Text_132859"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">module</span><span style="color: #000000"> MyFsLib.MathHelper<br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 获取一个浮点数的平方值</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> square: </span><span style="color: #0000ff">float</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">float</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 获取一个浮点数的立方值</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> cube: </span><span style="color: #0000ff">float</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">float</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 判断一个整数是否为偶数</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> isEven: </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">bool</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 判断一个整数是否为奇数</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> isOdd: </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">bool</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 获取不大于指定正整数的质数数组</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> generatePrimes: </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">int</span><span style="color: #000000"> array</span></span></pre></div><p>&nbsp;</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_134946"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" /><img id="Code_Open_Image_134946"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" style="display: none" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_134946">F# Code - mathHelper的实现</span><span id="Code_Open_Text_134946" style="display: none"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">module</span><span style="color: #000000"> MyFsLib.MathHelper<br /><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> System<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> pow x y = Math.Pow(x, y)<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> square x = pow x </span><span style="color: #800080">2.0</span><span style="color: #000000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> cube x = pow x </span><span style="color: #800080">3.0</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> isEven x = x % </span><span style="color: #800080">2</span><span style="color: #000000"> = </span><span style="color: #800080">0</span><span style="color: #000000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> isOdd x = x % </span><span style="color: #800080">2</span><span style="color: #000000"> = </span><span style="color: #800080">1</span><span style="color: #000000"><br /><br /></span><span style="color: #008000">//</span><span style="color: #008000"> Eratosthenes筛法</span><span style="color: #008000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes n =<br />    </span><span style="color: #0000ff">match</span><span style="color: #000000"> n </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> _ </span><span style="color: #0000ff">when</span><span style="color: #000000"> n &lt; </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> [</span><span style="color: #000000">||</span><span style="color: #000000">]<br />    </span><span style="color: #000000">|</span><span style="color: #000000"> _ </span><span style="color: #000000">-&gt;</span><span style="color: #000000"><br />        </span><span style="color: #008000">//</span><span style="color: #008000"> Init sieve.</span><span style="color: #008000"><br /></span><span style="color: #000000">        </span><span style="color: #0000ff">let</span><span style="color: #000000"> sieve = [</span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000ff">for</span><span style="color: #000000"> i </span><span style="color: #0000ff">in</span><span style="color: #000000"> </span><span style="color: #800080">0</span><span style="color: #000000"> .. n </span><span style="color: #0000ff">do</span><span style="color: #000000"> yield </span><span style="color: #0000ff">true</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000">]<br />       <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> isPrime index = sieve.[index]<br />       <br />        </span><span style="color: #008000">//</span><span style="color: #008000"> Check it.</span><span style="color: #008000"><br /></span><span style="color: #000000">        </span><span style="color: #0000ff">let</span><span style="color: #000000"> upperBound = Convert.ToInt32(Math.Sqrt((</span><span style="color: #0000ff">float</span><span style="color: #000000">)n))<br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> upperBound </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />                </span><span style="color: #0000ff">for</span><span style="color: #000000"> j </span><span style="color: #0000ff">in</span><span style="color: #000000"> [i * </span><span style="color: #800080">2</span><span style="color: #000000"> .. i .. sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000">] </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />                    sieve.[j] </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> </span><span style="color: #0000ff">false</span><span style="color: #000000"><br />                   <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">mutable</span><span style="color: #000000"> count = </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000"> </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />                count </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> count + </span><span style="color: #800080">1</span><span style="color: #000000"><br />               <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primes = Array.create count </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">mutable</span><span style="color: #000000"> index = </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000"> </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />                primes.[index] </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> i<br />                index </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> index + </span><span style="color: #800080">1</span><span style="color: #000000"><br />               <br />        primes</span></span></pre></div><p><br /><strong>使用NUnit进行单元测试</strong></p><p>不要害怕，由于F#植根于.NET平台的本性，你会发现这些测试用例代码都是那么眼熟。</p><p>需要废话的是，先添加对&rdquo;nunit.framework.dll&rdquo;的引用，而且要为测试类添加一个无参构造函数。</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_133109"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" /><img id="Code_Open_Image_133109"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_133109">F# Code - NUnit tester</span><span id="Code_Open_Text_133109"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">namespace</span><span style="color: #000000"> NUnitTester<br /><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> NUnit.Framework<br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> MyFsLib<br /><br />[&lt;TestFixture</span><span style="color: #000000">&gt;]</span><span style="color: #000000"><br /></span><span style="color: #0000ff">type</span><span style="color: #000000"> TestCases = </span><span style="color: #0000ff">class</span><span style="color: #000000"><br />    </span><span style="color: #0000ff">new</span><span style="color: #000000">() = {}<br />   <br />    [&lt;Test</span><span style="color: #000000">&gt;]</span><span style="color: #000000"><br />    </span><span style="color: #0000ff">member</span><span style="color: #000000"> this.TestSquare() =<br />        Assert.AreEqual(</span><span style="color: #800080">0</span><span style="color: #000000">, MathHelper.square(</span><span style="color: #800080">0.0</span><span style="color: #000000">))<br />        Assert.AreEqual(</span><span style="color: #800080">4</span><span style="color: #000000">, MathHelper.square(</span><span style="color: #800080">2.0</span><span style="color: #000000">))<br />       <br />    [&lt;Test</span><span style="color: #000000">&gt;]</span><span style="color: #000000"><br />    </span><span style="color: #0000ff">member</span><span style="color: #000000"> this.TestGeneratePrimes() =<br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primesLessThan2 = MathHelper.generatePrimes(</span><span style="color: #800080">1</span><span style="color: #000000">)<br />        CollectionAssert.IsEmpty(primesLessThan2)<br />       <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primesNotGreaterThan2 = MathHelper.generatePrimes(</span><span style="color: #800080">2</span><span style="color: #000000">)<br />        CollectionAssert.IsNotEmpty(primesNotGreaterThan2)<br />        CollectionAssert.Contains(primesNotGreaterThan2, </span><span style="color: #800080">2</span><span style="color: #000000">)<br />        Assert.AreEqual(</span><span style="color: #800080">1</span><span style="color: #000000">, primesNotGreaterThan2.Length)<br />       <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primesNotGreaterThan10 = MathHelper.generatePrimes(</span><span style="color: #800080">10</span><span style="color: #000000">)<br />        CollectionAssert.IsNotEmpty(primesNotGreaterThan10)<br />        CollectionAssert.Contains(primesNotGreaterThan10, </span><span style="color: #800080">7</span><span style="color: #000000">)<br />        Assert.AreEqual(</span><span style="color: #800080">4</span><span style="color: #000000">, primesNotGreaterThan10.Length)<br />       <br />    </span><span style="color: #008000">//</span><span style="color: #008000"> Other testcases<img alt="" src="http://images.cnblogs.com/dot.gif" /></span><span style="color: #008000"><br /></span><span style="color: #0000ff">end</span></span></pre></div><p><br />这里只编写了对函数square和generatePrimes的测试。如果你在C#中用过NUnit，看这样的代码就没有任何问题了。测试结果为：<br /><img height="310" alt="" src="http://pic002.cnblogs.com/img/anderslly/200811/2008111813564068.jpg" width="463" /></p><p><strong>使用FsUnit进行单元测试</strong></p><p><a href="http://code.google.com/p/fsunit/" target="_blank"><font color="#000000">FsUnit</font></a>是一个Specification测试框架。它的目标是将单元测试和行为（函数）的规格尽量简化，并以函数式的风格代替命令式风格的测试代码。</p><p>Specification可以翻译为规格说明，就是说测试代码实际上是对待测代码的一条条规格说明。比如对函数square，它求一个数的平方，那么一条规格可以是：&rdquo;square(2) should equal 4&rdquo;。好了，惊喜就要来了：</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_133252"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" /><img id="Code_Open_Image_133252"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_133252">F# Code - FsUnit tester</span><span id="Code_Open_Text_133252"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> FsUnit<br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> MyFsLib<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> squareSpecs =<br />    specs </span><span style="color: #800000">&quot;</span><span style="color: #800000">Test square</span><span style="color: #800000">&quot;</span><span style="color: #000000"> [<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">square(0) should equal 0</span><span style="color: #800000">&quot;</span><span style="color: #000000"> <br />            (MathHelper.square(</span><span style="color: #800080">0.0</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">0.0</span><span style="color: #000000">) </span><span style="color: #008000">//</span><span style="color: #008000"> Pass</span><span style="color: #008000"><br /></span><span style="color: #000000">        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">square(2) should equal 2</span><span style="color: #800000">&quot;</span><span style="color: #000000"> <br />            (MathHelper.square(</span><span style="color: #800080">2.0</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">2.0</span><span style="color: #000000">) </span><span style="color: #008000">//</span><span style="color: #008000"> Fail</span><span style="color: #008000"><br /></span><span style="color: #000000">    ]<br />    <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes1Specs =<br />    specs </span><span style="color: #800000">&quot;</span><span style="color: #800000">Test generatePrimes</span><span style="color: #800000">&quot;</span><span style="color: #000000"> [<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(1).Length should equal 0</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">1</span><span style="color: #000000">).Length </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">0</span><span style="color: #000000">)<br />    ]<br />    <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes2Specs =<br />    specs </span><span style="color: #800000">&quot;</span><span style="color: #800000">Test generatePrimes</span><span style="color: #800000">&quot;</span><span style="color: #000000"> [<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(2).Length should equal 1</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">2</span><span style="color: #000000">).Length </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">1</span><span style="color: #000000">)<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(2) should contain 2</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">2</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should contain </span><span style="color: #800080">2</span><span style="color: #000000">)<br />    ]<br />    <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes10Specs =<br />    specs </span><span style="color: #800000">&quot;</span><span style="color: #800000">Test generatePrimes</span><span style="color: #800000">&quot;</span><span style="color: #000000"> [<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(10).Length should equal 4</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">10</span><span style="color: #000000">).Length </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">4</span><span style="color: #000000">)<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(10) should contain 7</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">10</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should contain </span><span style="color: #800080">7</span><span style="color: #000000">)<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(10) should not contain 9</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">10</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should not</span><span style="color: #800000">'</span><span style="color: #800000"> (contain 9))</span><span style="color: #800000"><br /></span><span style="color: #000000">    ]<br />    <br />printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">%s</span><span style="color: #800000">&quot;</span><span style="color: #000000"> (Results.summary())</span></span></pre></div><p><br />这里没有Assert，有的是should，这两个词给人的感觉可大不一样，而且通过函数的组合，我们可以写出should equal这样的&ldquo;句子&rdquo;。这里的测试代码已经比较接近自然语言了。</p><p>一条spec就是一条规格说明，它说明待测的函数具有什么样的规格，我们把这些都放在specs中，测试结束后，使用Results.summary函数来显示测试结果：<br /><img height="321" alt="" src="http://pic002.cnblogs.com/img/anderslly/200811/2008111817334624.jpg" width="522" /> <br />如果对FsUnit感兴趣，可以到<a href="http://code.google.com/p/fsunit/"><font color="#000000">http://code.google.com/p/fsunit/</font></a>这里来看看。感觉目前它还有些欠缺，比如没有像CollectionAssert这样的测试类，接下来看看能不能扩展一下。</p><p><strong>小结</strong></p><p>本文介绍了在F#中如何使用NUnit和FsUnit进行单元测试。可以看到两者都很简单，前者简单是因为能很好地延续在C#中的方式，迁移过来不要费多大力气；后者简单是因为它接近自然语言，看起来很亲切。FsUnit值得关注，除了单元测试本身，我们还可以通过它来了解Language-Oriented Programming的相关知识。</p><p>（要了解本人所写的其它F#随笔请查看 <a href="http://www.cnblogs.com/anderslly/archive/2008/10/archive/2008/10/08/fs-posts-indices.html" target="_blank"><font color="#000000">F#系列随笔索引</font></a>）</p><p><strong>参考</strong></p><p>《Foundations of F#》 by Robert Pickering<br /><a href="http://code.google.com/p/fsunit/"><font color="#000000">http://code.google.com/p/fsunit/</font></a></p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>推荐VS2008插件CodeRush Xpress for C#</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/12/4629.shtml</link>
      <pubDate>18 Dec 2008 16:04:00</pubDate>
      <guid>http://qianxun.net/Post/2008/12/4629.shtml</guid>
      <description><![CDATA[<div><p style="text-align: left">近期<a href="http://www.devexpress.com/" target="_blank"><font color="#000000">DevExpress</font></a>和微软共同发布了<a title="针对C#的CodeRush Xpress" href="http://www.devexpress.com/go/CodeRushX.aspx" target="_blank"><font color="#000000">CodeRush Xpress for C#</font></a><span style="font-family: 宋体">，它包含了</span>Code Rush<span style="font-family: 宋体">和</span>Refactor! Pro中<span style="font-family: 宋体">的一些特性。这些特性包括增强的导航、选择工具、代码创建功能以及强大的重构能力。另外CodeRush Xpress还对C#中既有的重构功能做了封装，这些功能用起来更为方便了。不过它不支持Express版的Visual Studio。 </span></p><p><span style="font-family: 宋体">CodeRush Xpress的强点包括</span><span style="font-family: 宋体">易于访问的重构和代码创建功能、强大的文件和代码导航功能、一组编辑器、选择、剪贴板工具等。</span></p><p>下面介绍一下我尝试过的几个功能。</p><p><strong>1. 使用中生成（Generate From Usage） </strong></p><p>本来C#中有一个生成方法的功能，如果来类中调用了一个未声明的方法，VS会提示是否生成该方法，不过CodeRushX的功能要强大得多。除了方法，它还支持构造函数、类、委托、枚举、事件处理器、字段、属性、接口、局部变量、结构等。</p><p>来看看生成类时的情况。在下面的代码引用了未声明的类TestClass，此时可选择声明类（或结构、枚举）</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR1.png" /></p><p>生成结果为：</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR2.png" /></p><p>TestClass类的框架生成好了，并按照调用者的代码添加了相应的构造函数。右下角的提示框是CodeRushX的一大特色，它根据当前使用的功能提供相应的提示。</p><p>等一下，有了这样的功能，我们写代码的顺序是不是可以跟以前不一样了？我们可以先编写使用一个类的代码，然后利用CodeRushX生成该类，这有些像TDD的方式，所以这个特性成为<strong>TDD风格的使用中生成</strong>。</p><p><strong>2. 文件导航功能 </strong></p><p>CodeRushX支持<strong>快速文件导航</strong>，使用快捷键Ctrl+Alt+F，可以打开快速文件导航窗口：</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR3.jpg" /></p><p>这个功能DPack也有，不过看看这个更奇妙的：</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR4.jpg" /></p><p>我们只要输入单词的首字母就可以进行过滤，当然这里需要大写字母。</p><p><strong>3. 代码导航功能 </strong></p><p>对于代码导航，CodeRushX提供了一个<strong>快速导航</strong>窗口，快捷键为Ctrl+Shift+Q：</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR5.jpg" /></p><p>默认地，它会列出所有的成员。CodeRushX为此也提供了文本过滤功能：</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR6.jpg" /></p><p>比如我们可以选择只显示当前文件，这里也支持类似于文件导航的缩略词过滤。</p><p><strong>4. 代码编辑 </strong></p><p>先看看<strong>复制行（Duplicate Line）</strong>功能。我们经常要在类的开头定义多个字段，或在方法开头定义多个变量，它们的类型可能是一样的，此时复制行就派上用场了。</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR7.jpg" /></p><p>这里要连续定义firstName和lastName，先写出firstName这一行，然后按<strong>Shift+Enter</strong>，就会生成新的行，并选中了字段名，可以直接进行编辑。</p><p>除了这里提到的字段，复制行还支持方法、事件、属性、using语句、赋值语句等。程序员最怕重复性的工作，CodeRushX可以帮我们的大忙。</p><p><strong>高亮所有引用 </strong></p><p>在NetBeans中见过这样的功能，即高亮标识符所有的引用。</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR8.png" /></p><p>现在CodeRushX提供了类似的功能，虽然没有这么酷，快捷键是Ctrl+Alt+U：</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR9.jpg" /></p><p><strong>5. 递增/递减选择文本（Increase Reduce Selection） </strong></p><p>这个功能很有用。代码中会有命名空间、类、方法、方法体，通过快捷键我们就可以递增地选择方法体、方法直到当前文件的所有代码，快捷键为Ctrl+Alt+=，也可以按Ctrl+Alt+-按原路返回。</p><p><strong>6. 重构 </strong></p><p>CodeRushX提供了多达25种重构特性，它们是：</p><ul>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">增加块分隔符</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">组合条件</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">压缩为</span><span style="font-family: Times New Roman">Lambda</span><span style="font-family: 宋体">表达式</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">压缩为</span><span style="font-family: Times New Roman">Ternary</span><span style="font-family: 宋体">表达式</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">转化为自动实现的属性</span><span style="font-family: Times New Roman">&nbsp; </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">转化为</span><span style="font-family: Times New Roman">Initializer&nbsp; </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">创建存储备份</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">分解</span><span style="font-family: Times New Roman">Initializer </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">分解参数</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">扩展</span><span style="font-family: Times New Roman">Lambda</span><span style="font-family: 宋体">表达式</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">扩展</span><span style="font-family: Times New Roman">Ternary</span><span style="font-family: 宋体">表达式</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">抽取方法</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">压缩条件</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">内联代理</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">内联</span><span style="font-family: Times New Roman">Temp </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">引入</span><span style="font-family: Times New Roman">Local </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">显示</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">隐藏</span><span style="font-family: Times New Roman">&nbsp; </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">将类型转到文件中</span><span style="font-family: Times New Roman">&nbsp; </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">命名匿名方法</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">命名匿名类型</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">翻转条件</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">分割条件</span><span style="font-family: Times New Roman"> </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">使用</span><span style="font-family: Times New Roman">String.Format </span></font></span></span></span></span></span></span></li>    <li><span style="font-size: 12pt"><span style="font-size: medium"><span style="font-size: x-small"><span style="font-size: xx-small"><span style="font-size: x-small"><span style="font-size: small"><font size="2"><span style="font-family: 宋体">使用</span><span style="font-family: Times New Roman">StringBuilder </span></font></span></span></span></span></span></span></li></ul><p>要使用这些重构特性，可以使用右键菜单或者快捷键Ctrl+`：</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR10.png" /></p><p><strong>7. 可视化元素 </strong></p><p>CodeRushX的一大特色是提供了大量直观、动感的提示信息，比如：</p><p><strong>Action Hints</strong> -&gt;</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR11.png" /></p><p><strong>Big Hints</strong> -&gt;</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR12.png" /></p><p><strong>Smart Tags</strong> -&gt;</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR13.png" /></p><p><strong>Shortcuts</strong> -&gt;</p><p><img alt="" src="http://images.cnblogs.com/cnblogs_com/anderslly/111208_0521_VS2008CodeR14.png" /></p><p>怎么样，是不是很酷？</p><p>当然，上面介绍的这些只是它的部分功能而已，如果你感兴趣，就按照帮助文件尝试一下吧，肯定会有惊喜的。用了CodeRush Xpress，才体会到&quot;工欲善其事，必先利其器&quot;，它无疑会大大改善我们的开发体验，再次强烈推荐。</p><p>参考：</p><p><a href="http://www.infoq.com/cn/news/2008/11/CodeRush-Xpress" target="_blank"><font color="#000000">针对C#的CodeRush Xpress免费发布</font></a></p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>Eratosthenes筛法的F#实现</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/12/4628.shtml</link>
      <pubDate>18 Dec 2008 16:03:23</pubDate>
      <guid>http://qianxun.net/Post/2008/12/4628.shtml</guid>
      <description><![CDATA[<div><p><strong>什么是Eratosthenes筛法</strong></p><p>考虑一个常见的数论问题，指定一个整数，求出不大于该数的所有质数。我们可以先写一个函数来判断某个整数是否为质数，然后用它逐一判断每个整数，而Eratosthenes筛法比这种方法高效得多。</p><p>下面举例来说明它的原理。观察下面的彩图（来自wikipedia），这里是检查120以内的所有质数。首先去掉1，因为1既不是质数也不是合数；然后2是质数，那么2的倍数都肯定不是质数了，所以把2的倍数都涂成红色（它们出局了，这里是质数的游戏...）；接下来3没有被涂掉，所以3是质数，同理把3的倍数涂成绿色；下一个未涂掉的是5，所以5也是质数，同理把5的倍数涂掉；然后再涂掉7的倍数，剩下的就都是质数了。</p><p><img alt="" src="http://pic002.cnblogs.com/img/anderslly/200811/2008111111204361.gif" /></p><p>怎么，只要看2、3、5、7就够了？这里有两个不那么容易确定的问题，一是如何依次断定3、5、7都是质数；二是为何涂掉7的倍数后就完成了。对于问题一，<strong>如果一个整数不能被比它小的所有质数整除（这里就是没被涂掉），那么我们就可以断定它是质数</strong>。另外，该筛法的依据是，<strong>对于整数</strong><strong>n，如果它不能被不大于n的平方根(Sqrt(n))的任何质数所整除，那么n就是质数</strong>。这样就解决了问题二，对于120以内的整数，如果它不是质数，那么它必定能被不大于10的质数（也就是2、3、5、7）所整除。</p><p>这样我们可以确信上述算法是正确的了，下面来看看如何实现它。</p><p><strong>Eratosthenes筛法的C#和F#实现</strong></p><p>&nbsp;</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_120247"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" /><img id="Code_Open_Image_120247"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_120247">C# Code - Eratosthenes筛法</span><span id="Code_Open_Text_120247"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #008000">//</span><span style="color: #008000"> 返回不大于n的质数构成的数组</span><span style="color: #008000"><br /></span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">int</span><span style="color: #000000">[] SieveOfEratosthenes(</span><span style="color: #0000ff">int</span><span style="color: #000000"> n)<br />{<br />    </span><span style="color: #0000ff">if</span><span style="color: #000000"> (n </span><span style="color: #000000">&lt;</span><span style="color: #000000"> </span><span style="color: #800080">2</span><span style="color: #000000">) { </span><span style="color: #0000ff">return</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> </span><span style="color: #0000ff">int</span><span style="color: #000000">[</span><span style="color: #800080">0</span><span style="color: #000000">]; }<br /><br />    </span><span style="color: #008000">//</span><span style="color: #008000"> Init sieve.</span><span style="color: #008000"><br /></span><span style="color: #000000">    </span><span style="color: #0000ff">bool</span><span style="color: #000000">[] sieve </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> </span><span style="color: #0000ff">bool</span><span style="color: #000000">[n </span><span style="color: #000000">+</span><span style="color: #000000"> </span><span style="color: #800080">1</span><span style="color: #000000">];<br />    </span><span style="color: #0000ff">for</span><span style="color: #000000"> (</span><span style="color: #0000ff">int</span><span style="color: #000000"> i </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">2</span><span style="color: #000000">; i </span><span style="color: #000000">&lt;</span><span style="color: #000000"> sieve.Length; i</span><span style="color: #000000">++</span><span style="color: #000000">) { sieve[i] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">true</span><span style="color: #000000">; }<br /><br />    </span><span style="color: #008000">//</span><span style="color: #008000"> Check it.</span><span style="color: #008000"><br /></span><span style="color: #000000">    </span><span style="color: #0000ff">int</span><span style="color: #000000"> upperBound </span><span style="color: #000000">=</span><span style="color: #000000"> Convert.ToInt32(Math.Sqrt(n));<br />    </span><span style="color: #0000ff">for</span><span style="color: #000000"> (</span><span style="color: #0000ff">int</span><span style="color: #000000"> i </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">2</span><span style="color: #000000">; i </span><span style="color: #000000">&lt;=</span><span style="color: #000000"> Math.Sqrt(n); i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />    {<br />        </span><span style="color: #0000ff">if</span><span style="color: #000000"> (sieve[i])<br />        {<br />            </span><span style="color: #0000ff">for</span><span style="color: #000000"> (</span><span style="color: #0000ff">int</span><span style="color: #000000"> j </span><span style="color: #000000">=</span><span style="color: #000000"> i </span><span style="color: #000000">+</span><span style="color: #000000"> i; j </span><span style="color: #000000">&lt;=</span><span style="color: #000000"> n; j </span><span style="color: #000000">+=</span><span style="color: #000000"> i)<br />            {<br />                sieve[j] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">false</span><span style="color: #000000">;<br />            }<br />        }<br />    }<br /><br />    </span><span style="color: #008000">//</span><span style="color: #008000"> Count it.</span><span style="color: #008000"><br /></span><span style="color: #000000">    </span><span style="color: #0000ff">int</span><span style="color: #000000"> count </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">0</span><span style="color: #000000">;<br />    </span><span style="color: #0000ff">for</span><span style="color: #000000"> (</span><span style="color: #0000ff">int</span><span style="color: #000000"> i </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">2</span><span style="color: #000000">; i </span><span style="color: #000000">&lt;</span><span style="color: #000000"> sieve.Length; i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />    {<br />        </span><span style="color: #0000ff">if</span><span style="color: #000000"> (sieve[i])<br />        {<br />            count</span><span style="color: #000000">++</span><span style="color: #000000">;<br />        }<br />    }<br /><br />    </span><span style="color: #008000">//</span><span style="color: #008000"> Generate the result.</span><span style="color: #008000"><br /></span><span style="color: #000000">    </span><span style="color: #0000ff">int</span><span style="color: #000000">[] primes </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> </span><span style="color: #0000ff">int</span><span style="color: #000000">[count];<br />    </span><span style="color: #0000ff">int</span><span style="color: #000000"> index </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">0</span><span style="color: #000000">;<br />    </span><span style="color: #0000ff">for</span><span style="color: #000000"> (</span><span style="color: #0000ff">int</span><span style="color: #000000"> i </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">2</span><span style="color: #000000">; i </span><span style="color: #000000">&lt;</span><span style="color: #000000"> sieve.Length; i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />    {<br />        </span><span style="color: #0000ff">if</span><span style="color: #000000"> (sieve[i])<br />        {<br />            primes[index</span><span style="color: #000000">++</span><span style="color: #000000">] </span><span style="color: #000000">=</span><span style="color: #000000"> i;<br />        }<br />    }<br /><br />    </span><span style="color: #0000ff">return</span><span style="color: #000000"> primes;<br />}</span></span></pre></div><p>&nbsp;</p><p>下面是F#实现，其中getInt和main是辅助函数：</p><p>&nbsp;</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_120427"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" /><img id="Code_Open_Image_120427"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_120427">F# Code - Eratosthenes筛法</span><span id="Code_Open_Text_120427"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> System<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes n = <br />    </span><span style="color: #0000ff">match</span><span style="color: #000000"> n </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> _ </span><span style="color: #0000ff">when</span><span style="color: #000000"> n &lt; </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> [</span><span style="color: #000000">||</span><span style="color: #000000">]<br />    </span><span style="color: #000000">|</span><span style="color: #000000"> _ </span><span style="color: #000000">-&gt;</span><span style="color: #000000"><br />        </span><span style="color: #008000">//</span><span style="color: #008000"> Init sieve.</span><span style="color: #008000"><br /></span><span style="color: #000000">        </span><span style="color: #0000ff">let</span><span style="color: #000000"> sieve = [</span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000ff">for</span><span style="color: #000000"> i </span><span style="color: #0000ff">in</span><span style="color: #000000"> </span><span style="color: #800080">0</span><span style="color: #000000"> .. n </span><span style="color: #0000ff">do</span><span style="color: #000000"> yield </span><span style="color: #0000ff">true</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000">]<br />        <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> isPrime index = sieve.[index]<br />        <br />        </span><span style="color: #008000">//</span><span style="color: #008000"> Check it.</span><span style="color: #008000"><br /></span><span style="color: #000000">        </span><span style="color: #0000ff">let</span><span style="color: #000000"> upperBound = Convert.ToInt32(Math.Sqrt((</span><span style="color: #0000ff">float</span><span style="color: #000000">)n))<br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> upperBound </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />                </span><span style="color: #0000ff">for</span><span style="color: #000000"> j </span><span style="color: #0000ff">in</span><span style="color: #000000"> [i * </span><span style="color: #800080">2</span><span style="color: #000000"> .. i .. sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000">] </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />                    sieve.[j] </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> </span><span style="color: #0000ff">false</span><span style="color: #000000"><br />                    <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">mutable</span><span style="color: #000000"> count = </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000"> </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"> <br />                count </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> count + </span><span style="color: #800080">1</span><span style="color: #000000"><br />                <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primes = Array.create count </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">mutable</span><span style="color: #000000"> index = </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000"> </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />                primes.[index] </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> i<br />                index </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> index + </span><span style="color: #800080">1</span><span style="color: #000000"><br />                <br />        primes<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> getInt() = <br />    Convert.ToInt32(Console.ReadLine())<br />    <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> main() =<br />    </span><span style="color: #0000ff">let</span><span style="color: #000000"> i = getInt()<br />    </span><span style="color: #0000ff">let</span><span style="color: #000000"> primes = generatePrimes i<br />    Console.WriteLine(</span><span style="color: #800000">&quot;</span><span style="color: #800000">find {0} prime(s)</span><span style="color: #800000">&quot;</span><span style="color: #000000">, primes.Length)<br />    print_any primes<br />    <br />main()<br /><br />Console.Read()</span></span></pre></div><p>&nbsp;</p><p>这两段代码也就勉强能实现算法吧，有时间再考虑优化一下。</p><p>（要了解本人所写的其它F#随笔请查看 <a href="http://www.cnblogs.com/anderslly/archive/2008/11/archive/2008/10/archive/2008/10/08/fs-posts-indices.html" target="_blank"><font color="#000000">F#系列随笔索引</font></a>）</p><p>参考：</p><p><a href="http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" target="_blank"><font color="#000000">Sieve of Eratosthenes</font></a></p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>F#探险之旅（六）：F#代码的组织</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/12/4627.shtml</link>
      <pubDate>18 Dec 2008 16:02:36</pubDate>
      <guid>http://qianxun.net/Post/2008/12/4627.shtml</guid>
      <description><![CDATA[<div><p><strong>前言</strong></p><p>是的，我们已经学习了如何在F#中使用各种范式（函数式、命令式、面向对象）进行编程。但是目前还仅限于在单个模块内编写，要知道，不管是采用哪种语言或者范式编程，如果项目规模大了，都不适合把所有代码放在单个模块内。<br /><br />在常规的.NET项目中（比如C#+ASP.NET），我们往往会选择使用Solution的概念作为整个（独立）问题域的解决方案，Solution以下则是Project、File。这些概念在物理上往往表现为程序集（类库或可执行程序）、类文件等，如果项目和文件数量较多，就该好好考虑如何在组织它们。下面从这三个层次上分别来讨论一下。<br /><br /><strong>Solution层次</strong> <br /><br />这里主要考虑的是Project之间的相互关系，此时基本上我们可以忽略语言的不同，也<strong>可以说在这个层次上，语言的影响不大</strong>。所以说我们把那些在用C#开发时采用的代码组织原则搬过来用。比如Martin Fowler在《企业应用架构模式》中谈到的内容，比如Robert Martin在《敏捷软件开发》中提到的关于包的设计原则，还包括.NET社区中关于PetShop架构的讨论等等，都可以加以借鉴。关于这方面的内容已有大量相关的讨论，在此不再赘述。<br /><br />这里只谈一个具体的问题：<strong>如何添加对其它程序集的引用</strong>。在F# CTP 1.9.6.0之前，添加对程序集的引用需要#I和#r指令，#I用来指定要引用的程序集的目录，#r则用来指定要引用程序集的路径（包含文件名，可以是相对路径或绝对路径）。这两个指令既可以放在代码文件中，也可以放在编译选项中。其中有个小窍门，注册表中.NETFramework节点下包含了各.NET版本的一些信息，其中的<strong>AssemblyFoldersEx</strong>中有若干个目录信息，如果程序集所在目录出现在AssemblyFoldersEx中，就可以直接使用#r和文件名来添加引用了。<br /><br />在CTP版本中，可以像常规的C#/VB.NET项目中那样，为项目添加对其它程序集的引用（包括引用同一解决方案中的其它项目）：<br /><img alt="" src="http://pic002.cnblogs.com/img/anderslly/200811/2008110521470764.jpg" /> <br /><br />而#r只能用于fsx脚本文件或者放在编译选项中。<br /><br /><strong>Project层次</strong> <br /><br />现在假定你已经对上述设计原则有了足够的了解，并运用这些原则完成了设计，下一步就是如何使用F#来实现这些设计。现在我们进入到了Project这个层次，需要考虑Project中各代码实体之间的关系，这些实体可以是物理上的源码文件，也可以是逻辑上的模块、类型、配置等。F#中最基本的组织结构是命名空间和模块，命名空间的概念与C#中的一样。借助于Reflector可以看到模块在编译之后就是静态类，我们在为模块添加成员时要了解，这是在向一个静态类添加成员。<strong>关于命名空间和模块的相关知识，强烈推荐<a href="http://www.cnblogs.com/lvxuwen" target="_blank"><font color="#000000">Lvxuwen</font></a>的如何组织程序（<a href="http://www.cnblogs.com/lvxuwen/archive/2008/08/14/1267812.html" target="_blank"><font color="#000000">上</font></a>、<a href="http://www.cnblogs.com/lvxuwen/archive/2008/08/17/1269948.html" target="_blank"><font color="#000000">下</font></a>）</strong>。<br /><br /><strong>File层次</strong> <br /><br />现在考虑源码文件内部的基本问题。在<strong>使用函数式编程范式</strong>时，除了模块，还可以采用<strong>F#的自定义类型</strong>，F#中的类型分为两类，一是元组（Tuple）或记录（Record）类型，它们类似于C#中的类；二是Union类型，有时又称为Sum类型。通过Reflector可以看到，元组值是Tuple类型的实例，而Tuple实现了 Microsoft.FSharp.Core.IStructuralHash和System.IComparable接口；记录和Union则直接实现了这两个接口。要了解IStructualHash接口的更多内容，请参考<a href="http://blogs.msdn.com/jomo_fisher/archive/2007/09/17/adventures-in-f-discriminated-unions.aspx" target="_blank"><font color="#000000">Jome Fisher</font></a>的文章。<br /><br />而在使用<strong>面向对象编程范式</strong>时，我们可以像在C#中那样定义.NET类型，比如接口、类、结构、枚举、委托等等。当然这其中的编程细节比较多（建议看看我前面写过的<a href="http://www.cnblogs.com/anderslly/archive/2008/10/08/fs-posts-indices.html" target="_blank"><font color="#000000">几篇随笔</font></a>），而且对于同一问题可以采取不同的方案。这需要我们去多多学习和实战，根据不同的需要作出选择。<br /><br />这里来看另一个具体的问题：如何使用F#中的<strong>签名文件</strong>（Signature file）。在学习C语言时，接触过<strong>函数原型</strong>的概念，它给出了函数的名称、参数类型和返回类型，函数签名的含义与函数原型是一样的。如果我们把模块内的函数签名抽取出来，放在单独的一个文件中，这就是签名文件的由来。它的作用在于，它可以控制模块内函数的访问修饰符。如果要使用签名文件，那么它必须与其控制的模块文件成对出现，并且文件名相同。比如：</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_215146"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" /><img id="Code_Open_Image_215146"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_215146">F# Code - myModule.fsi</span><span id="Code_Open_Text_215146"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">module</span><span style="color: #000000"> FsLib.MyModule<br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 获取一个浮点数的平方值</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> square: </span><span style="color: #0000ff">float</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">float</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 获取一个浮点数的立方值</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> cube: </span><span style="color: #0000ff">float</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">float</span></span></pre></div><p>&nbsp;</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_215223"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none" /><img id="Code_Open_Image_215223"  height="16" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span class="cnblogs_code_Collapse" id="Code_Closed_Text_215223">F# Code - myModule.fs</span><span id="Code_Open_Text_215223"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">module</span><span style="color: #000000"> FsLib.MyModule<br /><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> System<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> pow x y = Math.Pow(x, y)<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> square x = pow x </span><span style="color: #800080">2.0</span><span style="color: #000000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> cube x = pow x </span><span style="color: #800080">3.0</span></span></pre></div><p><br />*.fsi即签名文件，这里定义了两个函数的签名：square和cube。*.fs即实现文件，它必须要提供对应的签名文件的所有函数的实现。其它程序集的模块，只能访问*.fsi中具有签名的函数。通过Reflector可以看到，对于myModule.fs中的三个函数，square和cube的修饰符为<strong>public</strong>，而pow则为<strong>internal</strong>。<br /><br />由此看来<strong>签名文件的作用很像C#中的接口</strong>。但事实上，编译后并没有真正生成接口。需要注意的是，如果要为代码添加XML文档注释，需要加在签名文件（如果模块有的话）而不是模块中。下面来看看如何在代码中添加注释。<br /><br /><strong>常规注释</strong> <br /><br />在F#中，单行注释使用//，而多行注释则使用(* &hellip; *)。<br /><br /><strong>XML文档注释 </strong><br /><br />如果为代码添加了文档注释，可以在编译时生成XML文档，然后借助于一些工具（如SandCastle）就可以生成容易使用的帮助文档。在上面的代码中可以看到，直接使用///可以为模块或其成员添加文档注释，这个要比C#中简便一些。同时也完全可以使用C#中那样完整的文档注释格式（比如使用Summary、Param等节点）。<br /><br />最后，如果要<strong>在F#使用C#类库中的代码</strong>，可以参考前面写过的一篇随笔：<a href="http://www.cnblogs.com/anderslly/archive/2008/09/28/fs-adventure-ip-part-two.html" target="_blank"><font color="#000000">F#命令式编程</font></a>，了解关于这方面的内容。<br /><br />F#的Project可以编译为类库或可执行应用程序（控制台应用程序或Windows应用程序）。我打算在后面的随笔就这两方面展开讨论，并尝试一些有实战意义的小型项目，相信到那时对代码组织的认识会更为准确。<br /><br /><strong>小结 </strong><br /><br />在初学F#时，我们可以很随便地将代码放在同一模块内做些尝试或者测试。但我们程序员不该是随便的人，随着项目规模的增大，代码的组织问题会变得越发重要，我们应当越加重视。在VS中进行开发时， 整个项目的组织自然地分为了Solution、Project、File三个层次，本文在这三个层次上就代码组织的基本问题做了讨论，写得比较简单，欢迎您来留言讨论 。</p><p>（要了解本人所写的其它F#随笔请查看 <a href="http://www.cnblogs.com/anderslly/archive/2008/10/archive/2008/10/08/fs-posts-indices.html" target="_blank"><font color="#000000">F#系列随笔索引</font></a>）<br /><br /><strong>参考</strong> <br />《Foundations of F#》 by Robert Pickering<br /><a href="http://blogs.msdn.com/dsyme/archive/2008/08/29/detailed-release-notes-for-the-f-september-2008-ctp-release.aspx" target="_blank"><font color="#000000">Detailed Release Notes for the F# Sep 2008 CTP release</font></a><br />园子里<a href="http://www.cnblogs.com/lvxuwen" target="_blank"><font color="#000000">Lvxuwen</font></a>的如何组织程序（<a href="http://www.cnblogs.com/lvxuwen/archive/2008/08/14/1267812.html" target="_blank"><font color="#000000">上</font></a>、<a href="http://www.cnblogs.com/lvxuwen/archive/2008/08/17/1269948.html" target="_blank"><font color="#000000">下</font></a>）<br />F#先锋<a href="http://www.vitarn.com/" target="_blank"><font color="#000000">维坦</font></a>的<a href="http://www.vitarn.com/141.htm" target="_blank"><font color="#000000">F# CTP 1.9.6.0 发行说明(Release Notes)摘要</font></a></p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>理解F#中的模式匹配与活动模式</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/11/4623.shtml</link>
      <pubDate>26 Nov 2008 9:40:57</pubDate>
      <guid>http://qianxun.net/Post/2008/11/4623.shtml</guid>
      <description><![CDATA[<div><p><strong>模式匹配</strong>（Pattern Matching）允许我们根据标识符值的不同进行不同的运算，它通常被拿来跟C#中的if&hellip;else或switch语法结构相比较，结论往往是模式匹配比后者要更为灵活、强大。那先来分析一下它灵活、强大在哪儿。</p><p><strong>为什么说模式匹配是灵活、强大的？</strong><br /><br />在我前面写过的几篇随笔里面，有几次提到了模式匹配，比如它能够对<strong>简单值</strong>（整数、字符串）匹配，也可以对<strong>.NET类型</strong>进行匹配，看下面两个简单的例子：</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_225731"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_225731"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_225731" class="cnblogs_code_Collapse">F# Code - 对简单值和.NET类型进行匹配</span><span id="Code_Open_Text_225731"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #008000">//</span><span style="color: #008000"> 对简单值进行匹配。</span><span style="color: #008000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">rec</span><span style="color: #000000"> fibonacci x =<br />    </span><span style="color: #0000ff">match</span><span style="color: #000000"> x </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> x </span><span style="color: #0000ff">when</span><span style="color: #000000"> x &lt;= </span><span style="color: #800080">0</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> failwith </span><span style="color: #800000">&quot;</span><span style="color: #800000">x必须是正整数。</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #800080">1</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #800080">1</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #800080">1</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> x </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> fibonacci(x - </span><span style="color: #800080">1</span><span style="color: #000000">) + fibonacci(x - </span><span style="color: #800080">2</span><span style="color: #000000">)<br />  <br />printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">%i</span><span style="color: #800000">&quot;</span><span style="color: #000000"> (fibonacci </span><span style="color: #800080">2</span><span style="color: #000000">) </span><span style="color: #008000">//</span><span style="color: #008000"> -&gt; 1</span><span style="color: #008000"><br /></span><span style="color: #000000">printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">%i</span><span style="color: #800000">&quot;</span><span style="color: #000000"> (fibonacci </span><span style="color: #800080">4</span><span style="color: #000000">) </span><span style="color: #008000">//</span><span style="color: #008000"> -&gt; 3<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000"> 对.NET类型进行匹配。</span><span style="color: #008000"><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> System<br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> typeToString x =<br />    </span><span style="color: #0000ff">match</span><span style="color: #000000"> box x </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> :? Int32 </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">Int32</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> :? Double </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">Double</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> :? String </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">String</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> _ </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">Other Type</span><span style="color: #800000">&quot;</span></span></pre></div><p><br />可以看到，这里所用的模式匹配没有给人太多惊喜，不用费多大力气就可以将其转换为if&hellip;else或switch结构了。<br /><br />先别急着离开，列表是FP中的典型数据结构，我们对它应用一下模式匹配看看。</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_225841"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_225841"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_225841" class="cnblogs_code_Collapse">F# Code - 对列表应用模式匹配</span><span id="Code_Open_Text_225841"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #008000">//</span><span style="color: #008000"> 对列表应用模式匹配。</span><span style="color: #008000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> listOfList = [[</span><span style="color: #800080">2</span><span style="color: #000000">; </span><span style="color: #800080">3</span><span style="color: #000000">; </span><span style="color: #800080">5</span><span style="color: #000000">]; [</span><span style="color: #800080">7</span><span style="color: #000000">; </span><span style="color: #800080">11</span><span style="color: #000000">; </span><span style="color: #800080">13</span><span style="color: #000000">]; [</span><span style="color: #800080">17</span><span style="color: #000000">; </span><span style="color: #800080">19</span><span style="color: #000000">; </span><span style="color: #800080">23</span><span style="color: #000000">; </span><span style="color: #800080">29</span><span style="color: #000000">]]<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">rec</span><span style="color: #000000"> concatenateList list =<br />    </span><span style="color: #0000ff">match</span><span style="color: #000000"> list </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> head :: tail </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> head @ (concatenateList tail)<br />    </span><span style="color: #000000">|</span><span style="color: #000000"> [] </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> []<br />   <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">rec</span><span style="color: #000000"> concatenateList2 list =<br />    </span><span style="color: #0000ff">if</span><span style="color: #000000"> List.nonempty list </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> head = List.hd list </span><span style="color: #0000ff">in</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> tail = List.tl list </span><span style="color: #0000ff">in</span><span style="color: #000000"><br />        head @ (concatenateList2 tail)<br />    </span><span style="color: #0000ff">else</span><span style="color: #000000"><br />        []<br />        <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> primes = concatenateList listOfList<br />print_any primes </span><span style="color: #008000">//</span><span style="color: #008000"> [2; 3; 5; 7; 11; 13; 17; 19; 23; 29]</span></span></pre></div><p><br />listOfList是一个列表的列表，两个函数concatenateList和concatenateList2的功能都是将listOfList的元素连接为一个大的列表，只不过一个用模式匹配方式实现，一个使用if&hellip;then&hellip;else结构实现。可以看到concatenateList的代码更为简洁，但仅仅如此吗？在concatenateList2中，我们按照传统的看待链表（F#中的列表以链表实现）的方式，将其中的节点一个一个取出来进行处理，这种处理方式是较为<strong>具体和细节</strong>的；而在concatenateList中我们通过两个简单的模式&ldquo;head :: tail&rdquo;和&ldquo;[]&rdquo;就覆盖了列表的所有可能，可以说，<strong>我们找到了更好地分解列表这种数据结构的方式，从而可以更为通用地处理列表</strong>。<br /><br />类似的，再来看看Union类型的情况。<strong>Union类型</strong>，有时称为sum类型或discriminated union，可将一组具有不同含义或结构的数据组合在一起。它的一个典型应用是表示一颗树：</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_225958"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_225958"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_225958" class="cnblogs_code_Collapse">F# Code - 对Union类型应用模式匹配</span><span id="Code_Open_Text_225958"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #0000ff">type</span><span style="color: #000000"> BinaryTree&lt;</span><span style="color: #800000">'</span><span style="color: #800000">a&gt; =</span><span style="color: #800000"><br /></span><span style="color: #000000">    </span><span style="color: #000000">|</span><span style="color: #000000"> Leaf </span><span style="color: #0000ff">of</span><span style="color: #000000"> </span><span style="color: #800000">'</span><span style="color: #800000">a</span><span style="color: #800000"><br /></span><span style="color: #000000">    </span><span style="color: #000000">|</span><span style="color: #000000"> Node </span><span style="color: #0000ff">of</span><span style="color: #000000"> BinaryTree&lt;</span><span style="color: #800000">'</span><span style="color: #800000">a&gt; * BinaryTree&lt;</span><span style="color: #800000">'</span><span style="color: #000000">a&gt; <br />    <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">rec</span><span style="color: #000000"> printBinaryTreeValues t =<br />    </span><span style="color: #0000ff">match</span><span style="color: #000000"> t </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> Leaf x </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">%i</span><span style="color: #800000">&quot;</span><span style="color: #000000"> x<br />    </span><span style="color: #000000">|</span><span style="color: #000000"> Node (l, r) </span><span style="color: #000000">-&gt;</span><span style="color: #000000"><br />        printBinaryTreeValues l<br />        printBinaryTreeValues r<br />        <br />printBinaryTreeValues (Node ((Node (Leaf </span><span style="color: #800080">1</span><span style="color: #000000">, Leaf </span><span style="color: #800080">2</span><span style="color: #000000">)), (Node (Leaf </span><span style="color: #800080">3</span><span style="color: #000000">, Leaf </span><span style="color: #800080">4</span><span style="color: #000000">))))</span></span></pre></div><p><br />这里通过BinaryTree&lt;'a&gt;定义一个泛型二叉树类型，printBinaryTreeValues函数用于打印其节点的值，这里需要判断节点的类型（子树还是叶子），有趣的是，Leaf和Node自动抽象为&ldquo;模式&rdquo;，不需要任何额外的工作。这样就可以看到一些所谓&ldquo;灵活、强大&rdquo;的影子了，<strong>对于Union类型所表示的数据结构，模式匹配可以极为简单、自然地分解、处理它</strong>。<br /><br />除了列表和Union类型，元组对于模式匹配的&ldquo;自适应&rdquo;也是类似的，这些已经够我们解决很多问题了。那对于其它的更复杂的场景或者更特殊的领域，F#还有什么大招呢？你一定能想得到，这就是活动模式。<br /><br /><strong>活动模式（Active Pattern）</strong><br /><br /><strong>活动模式的思想就是把模式匹配语法用于其他更多的数据结构</strong>。可以把它分为Single-Case、Multi-Case、Partial这几种类型。我将逐一做出介绍。<br /><br /><strong>Single-Case活动模式</strong> <br /><br />Single-Case是最简单的活动模式形式，它将一个输入值转换为其它的值，比如：</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_230122"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_230122"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_230122" class="cnblogs_code_Collapse">F# Code - Single-Case活动模式</span><span id="Code_Open_Text_230122"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #0000ff">let</span><span style="color: #000000"> (</span><span style="color: #000000">|</span><span style="color: #000000">UpperCase</span><span style="color: #000000">|</span><span style="color: #000000">) (x:</span><span style="color: #0000ff">string</span><span style="color: #000000">) = x.ToUpper()<br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> result = </span><span style="color: #0000ff">match</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">foo</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />             </span><span style="color: #000000">|</span><span style="color: #000000"> UpperCase </span><span style="color: #800000">&quot;</span><span style="color: #800000">FOO</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">true</span><span style="color: #000000"><br />             </span><span style="color: #000000">|</span><span style="color: #000000"> _ </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">false</span><span style="color: #000000"><br />             <br />printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">%b</span><span style="color: #800000">&quot;</span><span style="color: #000000"> result </span><span style="color: #008000">//</span><span style="color: #008000"> -&gt; true</span></span></pre></div><p><br />这里的UpperCase就是一个模式，它的类型信息为：active recognizer UpperCase: string -&gt; string，可以看到下面求result值的时候可以像前面一样使用模式匹配的语法了，UpperCase &ldquo;FOO&rdquo;可以理解为对于输入值&rdquo;foo&rdquo;，应用了UpperCase模式后，结果应当为&rdquo;FOO&rdquo;，如果确实如此，那么该模式就匹配了，所以result的值为true。<br /><br />UpperCase模式看起来像是一个函数，不过对于函数来说，没法直接应用模式匹配的语法。<br /><br /><strong>Multi-Case活动模式</strong></p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_230223"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_230223"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_230223" class="cnblogs_code_Collapse">F# Code - Multi-Case活动模式</span><span id="Code_Open_Text_230223"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #0000ff">let</span><span style="color: #000000"> (</span><span style="color: #000000">|</span><span style="color: #000000">Odd</span><span style="color: #000000">|</span><span style="color: #000000">Even</span><span style="color: #000000">|</span><span style="color: #000000">) x = </span><span style="color: #0000ff">if</span><span style="color: #000000"> x % </span><span style="color: #800080">2</span><span style="color: #000000"> = </span><span style="color: #800080">0</span><span style="color: #000000"> </span><span style="color: #0000ff">then</span><span style="color: #000000"> Even </span><span style="color: #0000ff">else</span><span style="color: #000000"> Odd<br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> isDivisibleByTwo x = </span><span style="color: #0000ff">match</span><span style="color: #000000"> x </span><span style="color: #0000ff">with</span><span style="color: #000000"> Even </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">true</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Odd </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">false</span><span style="color: #000000"><br />print_any (isDivisibleByTwo </span><span style="color: #800080">2</span><span style="color: #000000">) </span><span style="color: #008000">//</span><span style="color: #008000"> -&gt; true</span><span style="color: #008000"><br /></span><span style="color: #000000">print_any (isDivisibleByTwo </span><span style="color: #800080">3</span><span style="color: #000000">) </span><span style="color: #008000">//</span><span style="color: #008000"> -&gt; false</span></span></pre></div><p><br />这里(|Odd|Even|)就是Multi-Case模式了，Even的类型信息为：active recognizer Even: int -&gt; unit，即它没有返回值，所以在匹配时，直接写Even或Odd就可以了。<br /><br /><strong>Partial活动模式</strong> <br /><br />简单来说，<strong>Partial模式就是那些并不总是返回值的模式</strong>。比如输入值的范围可能过于庞大，或者对于某些返回值我们并不感兴趣，可以将其忽略。比如，对于自然数来说，只有一小部分是完全平方数或者能够被7整除。</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_230311"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_230311"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_230311" class="cnblogs_code_Collapse">F# Code - Partial活动模式</span><span id="Code_Open_Text_230311"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #008000">//</span><span style="color: #008000"> Partial Active Patterns</span><span style="color: #008000"><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> System<br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> (</span><span style="color: #000000">|</span><span style="color: #000000">DivisibleBySeven</span><span style="color: #000000">|</span><span style="color: #000000">_</span><span style="color: #000000">|</span><span style="color: #000000">) input = </span><span style="color: #0000ff">if</span><span style="color: #000000"> input % </span><span style="color: #800080">7</span><span style="color: #000000"> = </span><span style="color: #800080">0</span><span style="color: #000000"> </span><span style="color: #0000ff">then</span><span style="color: #000000"> Some() </span><span style="color: #0000ff">else</span><span style="color: #000000"> None<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> (</span><span style="color: #000000">|</span><span style="color: #000000">IsPerfectSquare</span><span style="color: #000000">|</span><span style="color: #000000">_</span><span style="color: #000000">|</span><span style="color: #000000">) (input : </span><span style="color: #0000ff">int</span><span style="color: #000000">) =<br />    </span><span style="color: #0000ff">let</span><span style="color: #000000"> sqrt = </span><span style="color: #0000ff">int</span><span style="color: #000000"> (Math.Sqrt(</span><span style="color: #0000ff">float</span><span style="color: #000000"> input))<br />    </span><span style="color: #0000ff">if</span><span style="color: #000000"> sqrt * sqrt = input </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />        Some()<br />    </span><span style="color: #0000ff">else</span><span style="color: #000000"><br />        None<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> describeNumber x =<br />    </span><span style="color: #0000ff">match</span><span style="color: #000000"> x </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> DivisibleBySeven &amp; IsPerfectSquare </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> <br />        printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">x is divisible by 7 and is a perfect square.</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> DivisibleBySeven                   </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">x is divisible by seven.</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> IsPerfectSquare                    </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">x is a perfect square.</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> _                                  </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">x looks normal.</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />    <br />describeNumber </span><span style="color: #800080">49</span><span style="color: #000000"> </span><span style="color: #008000">//</span><span style="color: #008000"> x is divisible by 7 and is a perfect square.</span><span style="color: #008000"><br /></span><span style="color: #000000">describeNumber </span><span style="color: #800080">35</span><span style="color: #000000"> </span><span style="color: #008000">//</span><span style="color: #008000"> x is divisible by seven.</span><span style="color: #008000"><br /></span><span style="color: #000000">describeNumber </span><span style="color: #800080">25</span><span style="color: #000000"> </span><span style="color: #008000">//</span><span style="color: #008000"> x is a perfect square.</span><span style="color: #008000"><br /></span><span style="color: #000000">describeNumber </span><span style="color: #800080">20</span><span style="color: #000000"> </span><span style="color: #008000">//</span><span style="color: #008000"> x looks normal.</span></span></pre></div><p><br />自然数有很多特性，而在函数describeNumber中，我们只关注它是否是完全平方数或者7的倍数，其它的就都舍弃不管了。<br /><br /><strong>应用</strong> <br /><br />我们来看看如何使用活动模式来操作XML文档。</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_230359"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_230359"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_230359" class="cnblogs_code_Collapse">F# Code - 应用活动模式操作XML文档</span><span id="Code_Open_Text_230359"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #008000">//</span><span style="color: #008000"> 定义针对XML节点的模式</span><span style="color: #008000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> (</span><span style="color: #000000">|</span><span style="color: #000000">Node</span><span style="color: #000000">|</span><span style="color: #000000">Leaf</span><span style="color: #000000">|</span><span style="color: #000000">) (node : </span><span style="color: #000000">#</span><span style="color: #000000">System.Xml.XmlNode) =<br />     </span><span style="color: #0000ff">if</span><span style="color: #000000"> node.HasChildNodes </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />         Node (node.Name, { </span><span style="color: #0000ff">for</span><span style="color: #000000"> x </span><span style="color: #0000ff">in</span><span style="color: #000000"> node.ChildNodes </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> x })<br />     </span><span style="color: #0000ff">else</span><span style="color: #000000"><br />         Leaf (node.InnerText)<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000"> 打印XML节点的函数 </span><span style="color: #008000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> printXml node =<br />     </span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">rec</span><span style="color: #000000"> printXml indent node =<br />         </span><span style="color: #0000ff">match</span><span style="color: #000000"> node </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />         </span><span style="color: #000000">|</span><span style="color: #000000"> Leaf (text) </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">%s%s</span><span style="color: #800000">&quot;</span><span style="color: #000000"> indent text<br />         </span><span style="color: #000000">|</span><span style="color: #000000"> Node (name, nodes) </span><span style="color: #000000">-&gt;</span><span style="color: #000000"><br />             printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">%s%s:</span><span style="color: #800000">&quot;</span><span style="color: #000000"> indent name<br />             nodes </span><span style="color: #000000">|</span><span style="color: #000000">&gt; Seq.iter (printXml (indent + </span><span style="color: #800000">&quot;</span><span style="color: #800000">    </span><span style="color: #800000">&quot;</span><span style="color: #000000">))<br />     printXml </span><span style="color: #800000">&quot;&quot;</span><span style="color: #000000"> node<br />     <br /></span><span style="color: #008000">//</span><span style="color: #008000"> 定义XML节点</span><span style="color: #008000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> doc =<br />    </span><span style="color: #0000ff">let</span><span style="color: #000000"> temp = </span><span style="color: #0000ff">new</span><span style="color: #000000"> System.Xml.XmlDocument()<br />    </span><span style="color: #0000ff">let</span><span style="color: #000000"> text =  </span><span style="color: #800000">&quot;</span><span style="color: #800000">&lt;fruit&gt;</span><span style="color: #800000"><br /></span><span style="color: #000000">                 &lt;apples&gt;<br />                     &lt;gannySmiths&gt;</span><span style="color: #800080">1</span><span style="color: #000000">&lt;/gannySmiths&gt;<br />                     &lt;coxsOrangePippin&gt;</span><span style="color: #800080">3</span><span style="color: #000000">&lt;/coxsOrangePippin&gt;<br />                 &lt;/apples&gt;<br />                 &lt;organges&gt;</span><span style="color: #800080">2</span><span style="color: #000000">&lt;/organges&gt;<br />                 &lt;bananas&gt;</span><span style="color: #800080">4</span><span style="color: #000000">&lt;/bananas&gt;<br />             &lt;/fruit&gt;</span><span style="color: #800000">&quot;<br /></span><span style="color: #000000">    temp.LoadXml(text)<br />    temp<br /><br />printXml (doc.DocumentElement :&gt; System.Xml.XmlNode)</span></span></pre></div><p><br />这里首先定义针对XML节点的模式，然后应用该模式来递归打印出一个XML节点及其子节点的信息。<br /><br />可以看到使用活动模式，寥寥数语就可以描述出XML节点的通用数据结构来了，这为接下来对节点的操作提供了良好的基础，而且我们回归了问题本身&mdash;&mdash;XML文档，而不需要关注具体的编程细节。<br /><br /><strong>小结</strong> <br /><br />这里先是介绍了F#中模式匹配的用法，这个可以理解为使用F#内置的模式，这样我们就可以处理F#中的值和特定的数据结构，比如列表、Union类型和元组等；接下来更进一步，活动模式把模式匹配的语法用到了其他更多的数据结构，这样模式的应用范围得到了很大的扩展。而且通过活动模式，我们可以将问题域转换为一套术语来表达，从而脱离编程细节回归到问题域本身，这也就有了一些LOP（Language-Oriented Programming）的特点，事实上，活动模式正是F#中LOP的实现方式之一。这个我将在后面的随笔做更深入的讨论。<br /><br />（要了解本人所写的其它F#随笔请查看 <a target="_blank" href="http://www.cnblogs.com/anderslly/archive/2008/10/archive/2008/10/08/fs-posts-indices.html"><font color="#000000">F#系列随笔索引</font></a>）<br /><br /><strong>参考</strong> <br /><a target="_blank" href="http://www.infoq.com/cn/articles/Beyond-Foundations-FSharp"><font color="#000000">超越F#基础&mdash;&mdash;活动模式 by Robert Pickering</font></a>； <br /><a target="_blank" href="http://blogs.msdn.com/chrsmith/archive/2008/02/21/Introduction-to-F_2300_-Active-Patterns.aspx"><font color="#000000">Introduction to F# Active Patterns by Chris Smith</font></a>；</p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
    <item>
      <title>在F#中进行单元测试</title>
      <author>Myshuiyue</author>
      <link>http://qianxun.net/Post/2008/11/4622.shtml</link>
      <pubDate>18 Nov 2008 13:53:26</pubDate>
      <guid>http://qianxun.net/Post/2008/11/4622.shtml</guid>
      <description><![CDATA[<div><p><strong>单元测试</strong>是开发者编写的一小段代码，用于检验被测代码的一个很小的、很明确的功能是否正确。通常情况下，一个单元测试（用例）用于判断某个特定条件（或场景）下特定函数的行为。如果想对单元测试的好处有更多的了解，可以看一下<a target="_blank" href="http://www.cnblogs.com/anderslly/archive/2008/03/21/unit-test-in-action-introduction.html"><font color="#000000">单元测试实战</font></a>。</p><p>在.NET社区内，<a target="_blank" href="http://www.nunit.org/"><font color="#000000">NUnit</font></a>无疑是最经典的单元测试工具，要了解它的用法，建议看一下园子里的一篇很棒的文章<a target="_blank" href="http://confach.cnblogs.com/archive/2005/06/20/177817.html"><font color="#000000">NUnit详细使用方法</font></a>。本文对此不再赘述。另外<a target="_blank" href="http://www.mbunit.com/Default.aspx"><font color="#000000">MbUnit</font></a>作为后起之秀，也很值得一试。</p><p>在F#中， <a target="_blank" href="http://blogs.msdn.com/chrsmith/archive/2008/05/30/language-oriented-programming-in-f.aspx"><font color="#000000">LOP</font></a>（<a target="_blank" href="http://en.wikipedia.org/wiki/Language-oriented_programming"><font color="#000000">Language-Oriented Programming</font></a>）是它的一个亮点，而FsUnit则是LOP的一个很好的实践。<a target="_blank" href="http://code.google.com/p/fsunit/"><font color="#000000">FsUnit</font></a>使用F#开发，用它编写的测试用例会接近于自然语言（英语），在其中我们也可以看到F#对函数进行组合的强大威力。</p><p>在本文中，我将通过简单的例子分别对NUnit和FsUnit的基本用法进行介绍。假定我们在开发一个类库MyFsLib，其中有一个模块mathHelper，里面有一些关于数学的函数，现在要做的就是测试这些函数。mathHelper的代码如下：</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_132859"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_132859"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_132859" class="cnblogs_code_Collapse">F# Code - mathHelper signature</span><span id="Code_Open_Text_132859"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">module</span><span style="color: #000000"> MyFsLib.MathHelper<br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 获取一个浮点数的平方值</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> square: </span><span style="color: #0000ff">float</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">float</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 获取一个浮点数的立方值</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> cube: </span><span style="color: #0000ff">float</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">float</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 判断一个整数是否为偶数</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> isEven: </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">bool</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 判断一个整数是否为奇数</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> isOdd: </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">bool</span><span style="color: #000000"><br /><br /></span><span style="color: #808080">///</span><span style="color: #008000"> 获取不大于指定正整数的质数数组</span><span style="color: #808080"><br /></span><span style="color: #0000ff">val</span><span style="color: #000000"> generatePrimes: </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">int</span><span style="color: #000000"> array</span></span></pre></div><p>&nbsp;</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_132947"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_132947"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_132947" class="cnblogs_code_Collapse">F# Code - mathHelper implementation</span><span id="Code_Open_Text_132947"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">module</span><span style="color: #000000"> MyFsLib.MathHelper<br /><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> System<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> pow x y = Math.Pow(x, y)<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> square x = pow x </span><span style="color: #800080">2.0</span><span style="color: #000000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> cube x = pow x </span><span style="color: #800080">3.0</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> isEven x = x % </span><span style="color: #800080">2</span><span style="color: #000000"> = </span><span style="color: #800080">0</span><span style="color: #000000"><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> isOdd x = x % </span><span style="color: #800080">2</span><span style="color: #000000"> = </span><span style="color: #800080">1</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes n =<br />    </span><span style="color: #0000ff">match</span><span style="color: #000000"> n </span><span style="color: #0000ff">with</span><span style="color: #000000"><br />    </span><span style="color: #000000">|</span><span style="color: #000000"> _ </span><span style="color: #0000ff">when</span><span style="color: #000000"> n &lt; </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #000000">-&gt;</span><span style="color: #000000"> [</span><span style="color: #000000">||</span><span style="color: #000000">]<br />    </span><span style="color: #000000">|</span><span style="color: #000000"> _ </span><span style="color: #000000">-&gt;</span><span style="color: #000000"><br />        </span><span style="color: #008000">//</span><span style="color: #008000"> Init sieve.</span><span style="color: #008000"><br /></span><span style="color: #000000">        </span><span style="color: #0000ff">let</span><span style="color: #000000"> sieve = [</span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000ff">for</span><span style="color: #000000"> i </span><span style="color: #0000ff">in</span><span style="color: #000000"> </span><span style="color: #800080">0</span><span style="color: #000000"> .. n </span><span style="color: #0000ff">do</span><span style="color: #000000"> yield </span><span style="color: #0000ff">true</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000">]<br />       <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> isPrime index = sieve.[index]<br />       <br />        </span><span style="color: #008000">//</span><span style="color: #008000"> Check it.</span><span style="color: #008000"><br /></span><span style="color: #000000">        </span><span style="color: #0000ff">let</span><span style="color: #000000"> upperBound = Convert.ToInt32(Math.Sqrt((</span><span style="color: #0000ff">float</span><span style="color: #000000">)n))<br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> upperBound </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />                </span><span style="color: #0000ff">for</span><span style="color: #000000"> j </span><span style="color: #0000ff">in</span><span style="color: #000000"> [i * </span><span style="color: #800080">2</span><span style="color: #000000"> .. i .. sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000">] </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />                    sieve.[j] </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> </span><span style="color: #0000ff">false</span><span style="color: #000000"><br />                   <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">mutable</span><span style="color: #000000"> count = </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000"> </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />                count </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> count + </span><span style="color: #800080">1</span><span style="color: #000000"><br />               <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primes = Array.create count </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> </span><span style="color: #0000ff">mutable</span><span style="color: #000000"> index = </span><span style="color: #800080">0</span><span style="color: #000000"><br />        </span><span style="color: #0000ff">for</span><span style="color: #000000"> i = </span><span style="color: #800080">2</span><span style="color: #000000"> </span><span style="color: #0000ff">to</span><span style="color: #000000"> sieve.Length - </span><span style="color: #800080">1</span><span style="color: #000000"> </span><span style="color: #0000ff">do</span><span style="color: #000000"><br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> isPrime i </span><span style="color: #0000ff">then</span><span style="color: #000000"><br />                primes.[index] </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> i<br />                index </span><span style="color: #000000">&lt;-</span><span style="color: #000000"> index + </span><span style="color: #800080">1</span><span style="color: #000000"><br />               <br />        primes</span></span></pre></div><p><br /><strong>使用NUnit进行单元测试</strong></p><p>不要害怕，由于F#植根于.NET平台的本性，你会发现这些测试用例代码都是那么眼熟。</p><p>需要废话的是，先添加对&rdquo;nunit.framework.dll&rdquo;的引用，而且要为测试类添加一个无参构造函数。</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_133109"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_133109"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_133109" class="cnblogs_code_Collapse">F# Code - NUnit tester</span><span id="Code_Open_Text_133109"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /></span><span style="color: #0000ff">namespace</span><span style="color: #000000"> NUnitTester<br /><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> NUnit.Framework<br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> MyFsLib<br /><br />[&lt;TestFixture</span><span style="color: #000000">&gt;]</span><span style="color: #000000"><br /></span><span style="color: #0000ff">type</span><span style="color: #000000"> TestCases = </span><span style="color: #0000ff">class</span><span style="color: #000000"><br />    </span><span style="color: #0000ff">new</span><span style="color: #000000">() = {}<br />   <br />    [&lt;Test</span><span style="color: #000000">&gt;]</span><span style="color: #000000"><br />    </span><span style="color: #0000ff">member</span><span style="color: #000000"> this.TestSquare() =<br />        Assert.AreEqual(</span><span style="color: #800080">0</span><span style="color: #000000">, MathHelper.square(</span><span style="color: #800080">0.0</span><span style="color: #000000">))<br />        Assert.AreEqual(</span><span style="color: #800080">4</span><span style="color: #000000">, MathHelper.square(</span><span style="color: #800080">2.0</span><span style="color: #000000">))<br />       <br />    [&lt;Test</span><span style="color: #000000">&gt;]</span><span style="color: #000000"><br />    </span><span style="color: #0000ff">member</span><span style="color: #000000"> this.TestGeneratePrimes() =<br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primesLessThan2 = MathHelper.generatePrimes(</span><span style="color: #800080">1</span><span style="color: #000000">)<br />        CollectionAssert.IsEmpty(primesLessThan2)<br />       <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primesNotGreaterThan2 = MathHelper.generatePrimes(</span><span style="color: #800080">2</span><span style="color: #000000">)<br />        CollectionAssert.IsNotEmpty(primesNotGreaterThan2)<br />        CollectionAssert.Contains(primesNotGreaterThan2, </span><span style="color: #800080">2</span><span style="color: #000000">)<br />        Assert.AreEqual(</span><span style="color: #800080">1</span><span style="color: #000000">, primesNotGreaterThan2.Length)<br />       <br />        </span><span style="color: #0000ff">let</span><span style="color: #000000"> primesNotGreaterThan10 = MathHelper.generatePrimes(</span><span style="color: #800080">10</span><span style="color: #000000">)<br />        CollectionAssert.IsNotEmpty(primesNotGreaterThan10)<br />        CollectionAssert.Contains(primesNotGreaterThan10, </span><span style="color: #800080">7</span><span style="color: #000000">)<br />        Assert.AreEqual(</span><span style="color: #800080">4</span><span style="color: #000000">, primesNotGreaterThan10.Length)<br />       <br />    </span><span style="color: #008000">//</span><span style="color: #008000"> Other testcases<img alt="" src="http://images.cnblogs.com/dot.gif" /></span><span style="color: #008000"><br /></span><span style="color: #0000ff">end</span></span></pre></div><p>&nbsp;</p><p>这里只编写了对函数square和generatePrimes的测试。如果你在C#中用过NUnit，看这样的代码就没有任何问题了。</p><p><strong>使用FsUnit进行单元测试</strong></p><p><a target="_blank" href="http://code.google.com/p/fsunit/"><font color="#000000">FsUnit</font></a>是一个Specification测试框架。它的目标是将单元测试和行为（函数）的规格尽量简化，并以函数式的风格代替命令式风格的测试代码。</p><p>Specification可以翻译为规格说明，就是说测试代码实际上是对待测代码的一条条规格说明。比如对函数square，它求一个数的平方，那么一条规格可以是：&rdquo;square(2) should equal 4&rdquo;。好了，惊喜就要来了：</p><div class="cnblogs_code"><pre><img id="Code_Closed_Image_133252"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width="11" height="16" style="display: none" /><img id="Code_Open_Image_133252"  alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" height="16" /><span id="Code_Closed_Text_133252" class="cnblogs_code_Collapse">F# Code - FsUnit tester</span><span id="Code_Open_Text_133252"><br /><!--<br  /><br  />Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />http://www.CodeHighlighter.com/<br  /><br  />--><span style="color: #000000">#</span><span style="color: #000000">light<br /><br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> FsUnit<br /></span><span style="color: #0000ff">open</span><span style="color: #000000"> MyFsLib<br /><br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> squareSpecs =<br />    specs </span><span style="color: #800000">&quot;</span><span style="color: #800000">Test square</span><span style="color: #800000">&quot;</span><span style="color: #000000"> [<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">square(0) should equal 0</span><span style="color: #800000">&quot;</span><span style="color: #000000"> <br />            (MathHelper.square(</span><span style="color: #800080">0.0</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">0.0</span><span style="color: #000000">) </span><span style="color: #008000">//</span><span style="color: #008000"> Pass</span><span style="color: #008000"><br /></span><span style="color: #000000">        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">square(2) should equal 2</span><span style="color: #800000">&quot;</span><span style="color: #000000"> <br />            (MathHelper.square(</span><span style="color: #800080">2.0</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">2.0</span><span style="color: #000000">) </span><span style="color: #008000">//</span><span style="color: #008000"> Fail</span><span style="color: #008000"><br /></span><span style="color: #000000">    ]<br />    <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes1Specs =<br />    specs </span><span style="color: #800000">&quot;</span><span style="color: #800000">Test generatePrimes</span><span style="color: #800000">&quot;</span><span style="color: #000000"> [<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(1).Length should equal 0</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">1</span><span style="color: #000000">).Length </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">0</span><span style="color: #000000">)<br />    ]<br />    <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes2Specs =<br />    specs </span><span style="color: #800000">&quot;</span><span style="color: #800000">Test generatePrimes</span><span style="color: #800000">&quot;</span><span style="color: #000000"> [<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(2).Length should equal 1</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">2</span><span style="color: #000000">).Length </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">1</span><span style="color: #000000">)<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(2) should contain 2</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">2</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should contain </span><span style="color: #800080">2</span><span style="color: #000000">)<br />    ]<br />    <br /></span><span style="color: #0000ff">let</span><span style="color: #000000"> generatePrimes10Specs =<br />    specs </span><span style="color: #800000">&quot;</span><span style="color: #800000">Test generatePrimes</span><span style="color: #800000">&quot;</span><span style="color: #000000"> [<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(10).Length should equal 4</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">10</span><span style="color: #000000">).Length </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should equal </span><span style="color: #800080">4</span><span style="color: #000000">)<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(10) should contain 7</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">10</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should contain </span><span style="color: #800080">7</span><span style="color: #000000">)<br />        spec </span><span style="color: #800000">&quot;</span><span style="color: #800000">generatePrimes(10) should not contain 9</span><span style="color: #800000">&quot;</span><span style="color: #000000"><br />            (MathHelper.generatePrimes(</span><span style="color: #800080">10</span><span style="color: #000000">) </span><span style="color: #000000">|</span><span style="color: #000000">&gt; should not</span><span style="color: #800000">'</span><span style="color: #800000"> (contain 9))</span><span style="color: #800000"><br /></span><span style="color: #000000">    ]<br />    <br />printfn </span><span style="color: #800000">&quot;</span><span style="color: #800000">%s</span><span style="color: #800000">&quot;</span><span style="color: #000000"> (Results.summary())</span></span></pre></div><p><br />这里没有Assert，有的是should，这两个词给人的感觉可大不一样，而且通过函数的组合，我们可以写出should equal这样的&ldquo;句子&rdquo;。这里的测试代码已经比较接近自然语言了。</p><p>一条spec就是一条规格说明，它说明待测的函数具有什么样的规格，我们把这些都放在specs中，测试结束后，使用Results.summary函数来显示测试结果：<br />&nbsp;<br />如果对FsUnit感兴趣，可以到<a href="http://code.google.com/p/fsunit/"><font color="#000000">http://code.google.com/p/fsunit/</font></a>这里来看看。感觉目前它还有些欠缺，比如没有像CollectionAssert这样的测试类，接下来看看能不能扩展一下。</p><p><strong>小结</strong></p><p>本文介绍了在F#中如何使用NUnit和FsUnit进行单元测试。可以看到两者都很简单，前者简单是因为能很好地延续在C#中的方式，迁移过来不要费多大力气；后者简单是因为它接近自然语言，看起来很亲切。FsUnit值得关注，除了单元测试本身，我们还可以通过它来了解Language-Oriented Programming的相关知识。</p></div>]]></description>
      <category>2903</category>
      <dc:date.Taken>2009-3-20 10:48:42</dc:date.Taken>
    </item>
  </channel>
</rss>