这是类似 C# 问题的坦诚尝试。
那么,你最喜欢的 F# 隐藏(或非隐藏)功能是什么?
到目前为止,我使用的大多数功能并不完全是隐藏的,但确实很令人耳目一新。比如说,与 C# 或 VB.NET 相比,重载运算符是多么简单。
Async<T>
帮助我摆脱了一些真正丑陋的代码。
由于我对这种语言还很新,因此了解在实际应用中使用的其他功能将非常有帮助。
这是类似 C# 问题的坦诚尝试。
那么,你最喜欢的 F# 隐藏(或非隐藏)功能是什么?
到目前为止,我使用的大多数功能并不完全是隐藏的,但确实很令人耳目一新。比如说,与 C# 或 VB.NET 相比,重载运算符是多么简单。
Async<T>
帮助我摆脱了一些真正丑陋的代码。
由于我对这种语言还很新,因此了解在实际应用中使用的其他功能将非常有帮助。
用户可以通过提供一个模块来定义自己的数字字面量,该模块的名称以 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平台上的一个非常重要的特性,因为您可以用它来进行封装,而使用的唯一其他/之前的工具是程序集。如果您有一个小组件,其中包含一些相关类型,这些类型想要能够看到彼此的内部详细信息,但不希望这些类型都对所有人公开,则可以怎么做?有两个方法:
在我参与的大型软件项目中,我的经验是每个人都会选择第二种方法,因为第一种方法由于各种原因(人们不想要50个小程序集,他们想要1个或2个或3个大型程序集,与我提出的封装点无关的其他好原因(另外:每个人都提到了ILMerge,但没有人使用它))而不可行。
那么您就选择了第二种方法。然后一年后,您终于决定重构该组件,发现在过去的一年中,还有17个其他位置调用了那个“internal”方法,而这个方法只是为了让另一个类型调用,使得现在非常难以重构该组件,因为现在所有人都依赖于那些实现细节。很遗憾。
问题在于,在.NET中没有好的方法来创建适度大小的程序集级封装范围/边界。往往“internal”太大,“private”太小。
... 直到有了F#。通过使用F#签名文件,您可以通过在实现文件中将一堆东西标记为public来创建“此源代码文件”的封装范围,因此文件中的所有其他代码都可以看到它并对其进行操作,但然后使用签名文件隐藏除组件向世界其他部分公开的狭窄公共接口之外的所有细节。这是愉快的。在一个文件中定义三个高度相关的类型,让它们看到彼此的实现细节,但仅向其他人公开真正的公共内容。胜利!
签名文件也许不是程序集内封装边界的理想功能,但它们是我所知道的唯一这样的功能,因此我像漂浮在海洋中的救生筏一样依靠它们。
简而言之:
复杂性是敌人。封装边界是对抗这个敌人的武器。 “private”是一个很好的武器,但有时太小而无法应用,“internal”通常太弱,因为整个程序集和所有InternalsVisibleTo都可以看到内部内容。 F#提供了比“对于类型为private”更大但比“整个程序集”小的作用域,这非常有用。
我想知道如果添加了什么会发生
<appSettings>
<add key="fsharp-navigationbar-enabled" value="true" />
</appSettings>
你想将此代码添加到devenv.exe.config文件中吗?(使用需谨慎)
--warnon:1182
传递给编译器可以打开有关未使用变量的警告;以下划线开头的变量名不受影响。虽然不是真的“隐藏”,但作为一个非机器学习专业人员,我很长一段时间没有意识到这一点:
模式匹配可以将数据结构“任意深度”地分解。
这里有一个[非常随意]的嵌套元组示例;它适用于列表、联合或任何组合的嵌套值:
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 )
泛型类型的内联运算符可以有不同的泛型约束:
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)
float Wrappers
。 - kvb