灰色维坦 以示哀悼

2008-05-12 14:28

5月18日, 为表达全国各族人民对四川汶川大地震遇难同胞的深切哀悼, 国务院决定:

  • 5月19日至21日为全国哀悼日, 下半旗致哀, 停止公共娱乐活动.
  • 5月19日14时28分起, 全国人民默哀3分钟, 鸣笛 鸣警报.
  • 与此同时, 奥运圣火传递也将暂停三天.

过滤路径和文件名中的特殊字符

工作中碰到的一个问题.

控件的标签对应的是文件名, 如何有效过滤用户输入的内容, 以保证文件名符合规则呢?

.NET平台果然够强大, 拥有两个静态方法, 分别代表在路径和文件名里禁止使用的字符数组. Path.GetInvalidPathChars() Path.GetInvalidFileNameChars()

之后我第一个想到的是字符串的Replace()方法: "123#4".Replace("#", "")

可是对于Replace(oldChar, newChar)这种重载的使用, 却碰到了一些问题.str.Replace(\'#\', \'\') str.Replace(\'#\', Char.MinValue) 两个都不行.

那就把字符数组转换成字符串数组吧

1
2
3
4
5
6
7
8
9
let cleanFileName str =
let rec repeat (s :string) invalidCharList =
match invalidCharList with
| h :: t -> repeat (s.Replace(h, "")) t
| [] -> s
Path.GetInvalidFileNameChars()
|> List.of_array
|> List.map (fun x -> x.ToString())
|> repeat str

虽然说问题能够得到解决, 但总觉得有点缺憾, 接下来我想到了String.Split()方法, 此方法不正是需要Char[]这样的参数么?

1
2
3
4
5
6
7
8
9
10
let cleanFileName (str :string) =
let join s = String.Join("", s)
Path.GetInvalidFileNameChars() // 使用特殊字符数组
|> str.Split // 把字符串拆分开来
|> join // 然后连接在一起
// 哈~ 汉编如果能做到这样, 会有很多人认同的.

// 要是连可读性都不要了, 也可以写成这样:
let cleanFileName (str :string) =
String.Join("", str.Split(Path.GetInvalidFileNameChars()))

F#装箱(box)与拆箱(unbox)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// int装箱 此时o的类型是 obj
let o = box 1
// 常规的拆箱方法是
let a = unbox<int> o
let b : int = unbox o
let c = o :?> int

// 如果把元组装箱呢?
let o = box (1, "a")
// FSI显示数据类型是 int * string
// 以下三种方法都通过了
let a = unbox<int string *> o
let b : (int * string) = unbox o
let c = o :?> int * string

// 接下来把一个表装箱
let o = box [1; 2; 3]
// 用unbox拆箱表是可行的
let a = unbox<int list> o
let b : (int list) = unbox o
// 但是下面这句却不行
let c = o :?> (int list)

// 感谢code17的指正
// 由于多余的括号 误把list当成了int的参数了
// 正确写法是:
let c = o :?> int list

// 同理 array与option的拆箱方法:
(box [|"a"; "b"|] :?> string array)
(box (Some(1)) :?> int option)

之前以为这些集合类型是不能动态拆箱的, 还由此得出了错误结论, 再次感谢code17的及时指正.

F#QQ群:61436709

新建一个F#的QQ群

61436709

如果碰巧你来到了这里, 无论是通过什么方式, 只要你喜欢F#, 那么请加入这个群, 希望可以让散落在互联网上的微量F#粉丝能够相聚在一起, 共同提高.

本人不才, 从年初开始研究F#到现在, 处处碰壁, Google在这个时候也显得格外吝啬, 大部分时候我都得不到想要的答案. 更要命的是F#方面的中文资料实在是少的太可怜了, 除去新闻报道和重复转载, 就只剩下那寥寥无几的有价值的篇幅.

但同时, 微软已经决定要将F#产品化, 这给了我们足够的信心, 即便不能像C#那样普及, 也会在.NET上占有重要一席.

F#群61436709 等待您的加入 彼此都是对方的老师 让我们一起分享蟹肉大餐吧.

F# - 1.9.4.15 (MSI/ZIP) 发布

订阅中收到消息, Don于5月2日发布了版本号为1.9.4.15的F#新版本.

.msi 下载地址

.zip 下载地址



目前已经有MSI安装包的链接了, 以下方法已过时!

不过只给出了ZIP压缩包的链接地址, 不知道是因为没有MSI版本还是搞错了.

> 下载解压缩后发现安装方式没有变化, 和以前一样只提供了两个.bat文件, 分别用于VS2003和VS2005.
之前看到过一篇文章, 用修改路径的方法安装到VS2008会有一些问题, 不过还是决定尝试一下.
我的机器上曾经装过上一版本F# - 1.9.3.14, 安装目录是D:\\Program Files\\FSharp-1.9.3.14. 于是把ZIP包解压缩到D:\\Program Files\\FSharp-1.9.4.15. 之后把注册表里能搜索到的 FSharp-1.9.3.14 字符串全部替换成 FSharp-1.9.4.15.
打开VS2008中的F#解决方案, 基本正常(除了编译…), 错误信息是说找不到FSharp.Core.
仔细研究批处理安装文件中发现这样一段:
if exist “%_ROOT%\bin\FSharp.Core%%n.dll” (
if “%CORDIR:v1.=X%” == “%CORDIR%” (
“%_ROOT%\setup\gac” %1 “%_ROOT%\bin\FSharp.Core%%n.dll”
REM if ERRORLEVEL 0 (
if NOT “%NGEN%”==”” (
“%NGEN%” /nologo “%_ROOT%\bin\FSharp.Core%%n.dll”
)
)
)
大致明白了报错的原因是找不到FSharp.Core.dll文件, 解决办法是打开CMD.EXE, 切换到F#安装目录, 运行如下命令: setup\\gac.exe bin\\fsharp.core.dll. 返回如下结果就代表成功了:Added bin\\FSharp.Core.dll to the global assembly cache.


新版本的F#更新列表已经公布了, 粗略的看了一遍, 对于我这样的菜鸟来说有些地方之前都没碰过, 怎么改变和我的关系也不大. 不过有几个细节是会经常碰到的:

负号无需括号

  • 3 * (-2)
  • 3 * -2

减号 避免与负号产生歧义

  • 3 - 23-2
  • 3 -2

转换 反对使用OCaml风格

  • int
  • int_of_float

字符串 为将来转换字符串打下基础

  • String.CompareTo
  • string.CompareTo

输出 尽量不要使用OCaml了

  • Console.WriteLine()
  • print_newline

FireFox3b5怕见Google?

  • Windows Server 2008
  • Mozilla FireFox 3 Beta 5

在Google搜索框中按任意键, FireFox会100%崩溃!

记得从2.0开始FireFox中一用智能ABC输入法就会崩溃, 现在再加上Google的这个问题, 真的耗不起了, 还是换回beta4吧.

今天FF特别的任性, 着急要查点东西, 它倒爽起性子来了, 换用IE7, 只打开两个标签页, 1个小时后发现内存使用率500M+

照这样发展下去, 会不会有一天没得浏览器可用啊?

使用.NET压缩文件

貌似10几天都没有更新了, 因为正在苦练F#内功心法, 同时还要现学现用完成一个S/C模式的管理系统, 实在是有些心力不足.

.NET命令空间System.IO.Compression提供了基本的流压缩实现, 其中包含RFC文档中规定的DeflateGZip两种算法.

两种算法有许多相同点:

  • 不涉及专利使用权
  • 采用LZ77 算法和霍夫曼编码 (压缩率基本相同)
  • 无损压缩
  • 重复压缩只会导致体积更大
  • 不能用于压缩大于 4 GB 的文件
  • 原本并不提供向 .zip 存档中添加或提取文件

也有一些区别:

  • GZip包括一个检测数据损坏的循环冗余校验值
  • GZip压缩后的文件可以用大多数解压缩软件打开

总的来讲, GZip略胜一筹. 下面是F#代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#light
open System.IO
open System.IO.Compression
// GZip压缩文件
// 参数: 文件名 字据
let GZipWrite (filename : string) (data : string) =
// 创建文件流
use fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write)
// 创建压缩流
use compressionStream = new GZipStream(fileStream, CompressionMode.Compress)
use writer = new StreamWriter(compressionStream)
// 将数据写入流中
writer.Write(box data)
writer.Close()
// GZip解压文件
// 参数: 文件名
// 返回: 数据
let GZipRead filename =
use fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)
use compressionStream = new GZipStream(fileStream, CompressionMode.Decompress)
use reader = new StreamReader(compressionStream)
let data = reader.ReadToEnd()
reader.Close()
data

谁在用F#? - 摘自Foundations of F#

原文: Robert Pickering

F#在微软的MSR甚至是整个公司都很风光. Ralf Herbrich(MSR应用游戏组的领袖, 专攻机器自学习技术)是个典型的F#粉丝:

第一个程序是解析110GB日志数据, 拆分到300个目录中的11000个文件里, 之后再输入到SQL数据库中. 整个程序只有90行(包括注释!), 完成这项任务只花了18小时; 每秒处理10000行日志, 简直不可思议! 注意我并没有优化代码, 只是用常规的方法写的. 我真的很吃惊, 因为之前按计划整个工作要花费一周时间的.
第二个程序用于统计数百万个回馈. 之前已经开发过了, 这次我只是照搬到F#程序当中; “从SQL数据库读取数据”和”将结果写入MATLAB数据文件”两项工作同时进行, F#源代码只有100行(包括注释). 当运行时我又一次惊呆了; 上百万条数据处理只花了10分钟, 就一台普通的桌面电脑. 之前的C#程序有1000行那么长. 从开发程序到输出结果一共花了两天.
Ralf Herbrich, Microsoft Research

微软之外F#同样成长迅速. 我问过Chris Barwick(cs.hubFS.net)站长, 专注F#的知名站点), 为什么你觉得使用这门语言呢? 他的回答是:
我做科学数学计算已经有14年了. 这些年来我一直期望能有一个健壮的平台. 提供有效的工具进行简单构建和并行使用, 推动科学计算的发展. .NET描绘了一个提升产品访问一致性平台. F#成为这一平台上有能力进行科学数学计算的语言. 借助这些工具和其它服务器产品, 在低成本创建复杂系统过程中拥有更多选择, 代码维护成本也很低廉. F#是高级科学计算的基石.
Christopher J. Barwick, JJB Research

最后, 我与Jude O’Kelly探讨, 他是Derivatives One的一名软件设计师, 这家公司从事金融软件, 谈论的话题是为什么Derivatives One在他们的产品当中使用F#:
我们使用C#和F#测试自己的金融系统; 性能基本相同, 但是我们喜欢F#版本是因为它的语法简单明了. F#的问题在于相关信息太少了; 我相信这本书对这一现状会有很大改善.
Jude O’Kelly, Derivatives One