F#隐藏的功能

Hidden Features of F#

这是一个类似C问题的毫不掩饰的尝试。

那么,您最喜欢的隐藏(或不隐藏)功能是什么?

到目前为止,我使用的大多数功能并不是完全隐藏的,而是非常令人耳目一新的。比如,与C或VB.NET相比,重载操作符是多么的简单。

Async帮助我去掉了一些真正丑陋的代码。

我对这门语言还很陌生,所以了解野外使用的其他功能是很好的。


用户定义的数字文字可以通过提供一个模块来定义,该模块的名称以NumericLiteral开头,并定义某些方法(FromZeroFromOne等)。

特别是,您可以使用它来为调用LanguagePrimitives.GenericZeroLanguagePrimitives.GenericOne提供更为可读的语法:

1
2
3
4
5
6
7
8
9
10
11
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个大型组件,因为与我提出的封装点无关的其他好的原因(除了:每个人离子会融合,但没有人使用)。

    所以你选择了选项2。然后一年后,您最终决定重构该组件,并且发现在过去的一年中,有17个其他地方现在调用了这个"内部"方法,而这个方法实际上只适用于另一种类型的调用,这使得很难考虑到这一点,因为现在每个人都依赖于关于这些实现细节。真倒霉。

    关键是,在.NET中没有创建中等大小的程序集内部封装范围/边界的好方法。通常,"内部"太大,"私人"太小。

    …直到F。使用F签名文件,您可以通过在实现文件中将一堆内容标记为公共内容来创建"此源代码文件"的封装范围,这样文件中的所有其他代码都可以看到它并参与其中,但随后使用签名文件隐藏所有细节,除了窄的pu组件向世界其他地方公开的Blic接口。这是幸福的。在一个文件中定义三个高度相关的类型,让他们查看彼此的实现细节,但只向其他人公开真正的公共内容。赢!

    签名文件可能不是内部组件封装边界的理想功能,但它们是我所知道的唯一这样的功能,因此我像海洋中的救生筏一样紧紧抓住它们。

    DR

    复杂性是敌人。封装边界是对付敌人的武器。""private"是一个很好的武器,但有时太小而不适用,"internal"通常太弱,因为太多的代码(整个程序集和所有internalsVisibleto的代码)可以看到内部的东西。F提供的范围大于"私有到类型",但小于"整个组件",这非常有用。


    我想知道如果你加上

    1
    </appSettings>

    到devenv.exe.config文件?(自担风险使用。)


    --warnon:1182传递给编译器会打开有关未使用变量的警告;以下划线开头的变量名是免疫的。


    为代数数据类型自动生成的比较函数(基于词典编纂顺序)是一个相对未知的好特性;请参见

    http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!548.进入

    例如。


    看到这个问题

    F操作员"?"

    有关问号运算符以及它如何提供基本语言机制来构建类似于C_中"动态"的特性的信息。


    是的,F没有任何"隐藏"的特性,但它确实在简单的语言中有很多功能。该语言的一个鲜为人知的特性是,尽管f是静态类型,但您基本上可以启用duck类型。


    不是真的隐藏了,但作为一个非ML的人,这让我有一段时间逃脱了:

    模式匹配可以任意深入到数据结构中。

    这是一个[难以置信的任意]嵌套元组示例;它适用于列表或联合或任何嵌套值组合:

    1
    2
    3
    4
    5
    6
    7
    8
    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 )

    使用f作为实用程序脚本语言可能会被低估。F狂热者往往是定量的。有时,您需要一些东西来备份您的MP3(或几十个数据库服务器),它比批处理更健壮一些。我一直在寻找jscript/vbscript的现代替代品。最近,我使用了Ironpython,但是f可能更完整,而且.NET交互也不那么麻烦。

    我喜欢有娱乐价值的课程功能。为至少三个WTF的纯过程/OOP程序显示一个课程化函数。不过,从这开始是一个让F转换的坏方法。


    泛型类型上的内联运算符可以具有不同的泛型约束:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type 'a Wrapper = Wrapper of 'a with
      static member inline (+)(Wrapper(a),Wrapper(b)) = Wrapper(a + b)
      static member inline Exp(Wrapper(a)) = Wrapper(exp a)

    let objWrapper = Wrapper(obj())
    let intWrapper = (Wrapper 1) + (Wrapper 2)
    let fltWrapper = exp (Wrapper 1.0)

    (* won''t compile *)
    let _ = exp (Wrapper 1)


    没有隐藏的功能,因为F处于设计模式。我们所拥有的只是技术预览,每两个月进行一次更改。

    请参阅http://research.microsoft.com/fsharp/