这是类似C#问题的毫不掩饰的尝试.
那么你最喜欢的F#隐藏(或不是)功能是什么?
到目前为止,我使用的大部分功能并没有完全隐藏,但却非常令人耳目一新.就像C#或VB.NET相比,重载运算符是多么微不足道.
并Async
帮助我削减了一些真正丑陋的代码.
我对这种语言还很陌生,所以了解野外使用的其他功能会很棒.
用户定义的数字文字可以通过提供一个模块名称以开始被定义NumericLiteral
并限定某些方法(FromZero
,FromOne
等).
特别是,您可以使用它来为调用提供更易读的语法,LanguagePrimitives.GenericZero
并且LanguagePrimitives.GenericOne
:
module NumericLiteralG = begin let inline FromZero() = LanguagePrimitives.GenericZero let inline FromOne() = LanguagePrimitives.GenericOne end let inline genericFactorial n = let rec fact n = if (n = 0G) then 1G else n * (fact (n - 1G)) fact n let flt = genericFactorial 30. let bigI = genericFactorial 30I
F#有一个很少使用的功能,称为"签名文件".您可以拥有一个充满公共类型/方法/模块/函数的大型实现文件,但是您可以通过签名文件隐藏并选择性地将该功能公开给程序的续集.也就是说,签名文件充当一种屏幕/过滤器,使您可以将实体"公开到此文件",但"对程序的其余部分是私有的".
我觉得这在.Net平台上是一个非常杀手级的功能,因为这种封装的唯一其他/先前工具是程序集.如果你有一个带有一些相关类型的小组件,希望能够看到彼此的内部细节,但不希望这些类型将所有这些位公开给每个人,你能做什么?好吧,你可以做两件事:
您可以将该组件放在单独的程序集中,并使这些类型共享的成员为"内部",并使您希望其他人看到的缩小部分为"公共",或者
你只需将内部内容标记为"内部",但是你将这些类型留在巨大的程序集中,只希望程序集中的所有其他代码选择不调用那些只标记为"内部"的成员,因为需要另外一种类型才能看到它.
根据我的经验,在大型软件项目中,每个人总是排在第2位,因为#1因各种原因而不起作用(人们不需要50个小型组件,他们需要1个或2个或3个大型组件,其他可能 - 与我提出的封装点无关的好理由(除此之外:每个人都提到ILMerge,但没有人使用它)).
所以你选择了#2选项.然后一年之后,你终于决定重构那个组件了,你发现在过去的一年里,其他17个地方现在调用了那个"内部"方法,这个方法实际上只适用于另一种类型的方法来调用它很难分解这一点因为现在每个人都依赖于那些实现细节.游民.
关键是,没有好的方法在.Net中创建中等大小的组件内封装范围/边界.通常,"内部"太大而"私人"太小.
......直到F#.使用F#签名文件,您可以通过在实现文件中将一堆内容标记为公共来创建"此源代码文件"的封装范围,因此文件中的所有其他代码都可以看到它并在其上聚会,但随后使用一个隐藏所有细节的签名文件,期望该组件向世界其他地方公开的狭窄公共接口.这很开心.在一个文件中定义三个高度相关的类型,让他们看到彼此的实现细节,但只将真正公开的东西暴露给其他人.赢得!
签名文件可能不是组装封装边界的理想特征,但它们是我所知道的唯一这样的特征,因此我像海洋中的救生筏一样紧紧抓住它们.
TL; DR
复杂性是敌人.封装边界是对付这个敌人的武器."私人"是一个很好的武器,但有时太小而不适用,而"内部"通常太弱,因为如此多的代码(整个程序集和所有InternalsVisibleTo)可以看到内部的东西.F#提供的范围大于"私有到类型"但小于"整个组件",这非常有用.
我想知道如果添加会发生什么
到你的devenv.exe.config文件?(使用风险自负.)
传递--warnon:1182
给编译器会打开有关未使用变量的警告; 以下划线开头的变量名称是免疫的.
代数数据类型的自动生成比较函数(基于词典排序)是一个相对未知的很好的特征; 看到
http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!548.entry
举个例子.
是的,F#没有任何"隐藏"功能,但它确实在简单语言中有很多功能.该语言的一个鲜为人知的特性是,尽管F#是静态类型的,但您基本上可以启用鸭子类型.
看到这个问题
F#运算符"?"
有关问号运算符的信息以及它如何提供基本语言机制来构建类似于C#中的"动态"的功能.
没有真正隐藏,但作为一个非ML人,这让我逃脱了一段时间:
模式匹配可以任意深度分解为数据结构.
这是一个[令人难以置信的任意]嵌套元组示例; 这适用于列表或联合或嵌套值的任何组合:
let listEven = "Manipulating strings can be intriguing using F#".Split ' ' |> List.ofArray |> List.map (fun x -> (x.Length % 2 = 0, x.Contains "i"), x) |> List.choose ( function (true, true), s -> Some s | _, "F#" -> Some "language" | _ -> None )