小编Phi*_* P.的帖子

设计F#库以供F#和C#使用的最佳方法

我正在尝试用F#设计一个库.该库应该对F#和C#都很友好.

这就是我被困住的地方.我可以使它F#友好,或者我可以使它C#友好,但问题是如何使它友好的两者.

这是一个例子.想象一下,我在F#中有以下功能:

let compose (f: 'T -> 'TResult) (a : 'TResult -> unit) = f >> a
Run Code Online (Sandbox Code Playgroud)

这完全可以从F#中使用:

let useComposeInFsharp() =
    let composite = compose (fun item -> item.ToString) (fun item -> printfn "%A" item)
    composite "foo"
    composite "bar"
Run Code Online (Sandbox Code Playgroud)

在C#中,该compose函数具有以下签名:

FSharpFunc<T, Unit> compose<T, TResult>(FSharpFunc<T, TResult> f, FSharpFunc<TResult, Unit> a);
Run Code Online (Sandbox Code Playgroud)

但当然我不想FSharpFunc签名,我想要的是Func,Action而是像这样:

Action<T> compose2<T, TResult>(Func<T, TResult> f, Action<TResult> a);
Run Code Online (Sandbox Code Playgroud)

为此,我可以创建这样的compose2函数:

let compose2 (f: Func<'T, 'TResult>) (a : Action<'TResult> ) …
Run Code Online (Sandbox Code Playgroud)

c# f#

104
推荐指数
2
解决办法
7903
查看次数

F#实际上将私有成员编译为IL中的内部成员.错误?

我一直认为,在F#访问控制的关键字(public,private,internal)在,因为他们在C#中做同样的工作方式.确实从MSDN文档访问控制(F#):

  • public表示所有呼叫者都可以访问该实体.
  • internal表示只能从同一个程序集访问该实体.
  • private表示只能从封闭类型或模块访问实体.

这似乎与我的假设非常一致,并且在SO提供的主题上也有多个答案.

但是,当我使用Reflector调入已编译的代码时,我发现所有声明为private的成员实际上都被编译为内部(程序集可见性),这与文档不匹配.

为了避免任何疑问,我创建了一个小测试来确认这一点.

F#代码:

// Make internals visible to other assemblies
[<assembly:InternalsVisibleTo("MyCSharpAssembly")>]


// OK. Expect: "internal static class PrivateModule" in C#
module private PrivateModule =

    // FAIL. Expect: "private static void privateStaticMethod()" in C#
    let private privateStaticMethod() = ignore()

// OK. Expect: "internal class InternalClass" in C#
type private InternalClass() =

    // FAIL. Expect: "private int privateInstanceField" in C#
    let privateInstanceField …
Run Code Online (Sandbox Code Playgroud)

.net f#

16
推荐指数
1
解决办法
580
查看次数

在跨平台C和C++ API中使用字符串的当前最佳实践是什么?

我看起来可能需要开始一些跨平台项目,其中一部分必须用C或C++完成(尚未确定,因此问题是关于它们两者).我将主要处理基于文本的东西和字符串.

C/C++将具有可从更高级别的平台相关代码调用的API.

我的问题是:建议使用什么类型的字符串,特别是在声明公共接口时?有没有推荐的标准技术?有什么可以避免的吗?

我几乎没有编写C或C++代码的经验,甚至那都是在Windows上,所以没有什么比这更像是跨平台了.所以我真正想要的是让某些东西能够让我以正确的方式行事,避免做出愚蠢的事情,这些事情必将引起很多痛苦.


编辑1:提供有关预期用途的更多上下文.API将被以下消费者使用:

  • 通过NSString和朋友在iPhone/iPad/Mac上实现目标C. API可以静态链接,因此无需担心.so .dll问题.

  • Java通过JNI在Android和其他Java平台上运行

  • .NET通过p/invoke从托管C#代码或本机静态链接(如果使用C++/CLI).

  • 关于在这种情况下以某种方式/某处使用lua有一些想法.不知道这是否与任何事情有关.

c c++ api cross-platform

10
推荐指数
1
解决办法
542
查看次数

为什么F#编译器即使在发布版本中也会生成IL NOP?

我偶然发现了这一点,我有点困惑.

我有一个开箱即用的VS 2010 F#项目,所有默认设置都针对.NET 4.0.

F#代码是这样的:

let test(a:int, b:int, c:int) = min a (min b c)
Run Code Online (Sandbox Code Playgroud)

当我编译它以供发布时,生成的IL包含一些NOP 分散的奇怪指令.像这样:

为此生成的IL(具有所有默认设置):

.method public static int32  test(int32 a,
                                  int32 b,
                                  int32 c) cil managed
{
  // Code size       20 (0x14)
  .maxstack  4
  .locals init ([0] int32 V_0)

  // HERE
  IL_0000:  nop

  IL_0001:  ldarg.1
  IL_0002:  ldarg.2
  IL_0003:  bge.s      IL_0009
  IL_0005:  ldarg.1

  // HERE
  IL_0006:  nop

  IL_0007:  br.s       IL_000b
  IL_0009:  ldarg.2

  // HERE
  IL_000a:  nop

  IL_000b:  stloc.0
  IL_000c:  ldarg.0
  IL_000d:  ldloc.0
  IL_000e:  bge.s      IL_0012 …
Run Code Online (Sandbox Code Playgroud)

f#

9
推荐指数
1
解决办法
600
查看次数

IEnumerable <IDisposable>:谁处理什么和何时 - 我做对了吗?

这是一个假设的场景.

我有非常多的用户名(比如10,000,000,000,000,000,000,000.是的,我们处于星际时代:)).每个用户都有自己的数据库.我需要遍历用户列表并对每个数据库执行一些SQL并打印结果.

因为我学会了函数式编程的优点,并且因为我处理了如此多的用户,所以我决定使用F#和纯序列(也就是IEnumerable)来实现它.我走了

// gets the list of user names
let users() : seq<string> = ...

// maps user name to the SqlConnection
let mapUsersToConnections (users: seq<string>) : seq<SqlConnection> = ...

// executes some sql against the given connection and returns some result
let mapConnectionToResult (conn) : seq<string> = ...

// print the result
let print (result) : unit = ...

// and here is the main program
users()
|> mapUsersToConnections
|> Seq.map mapConnectionToResult
|> Seq.iter print
Run Code Online (Sandbox Code Playgroud)

美丽?优雅?绝对.

但! 谁和什么时候处置SqlConnections? …

c# f# functional-programming idisposable sequences

8
推荐指数
1
解决办法
1373
查看次数

是否可以在F#中的函数范围声明一个类型?

假设我有一个功能,它做了一些相当复杂的功能,它是在子功能的帮助下实现的.为了使事情更容易,而不是元组,我想使用一些私有的中间结构来实现这个功能.

我不希望这些结构的声明泄漏到外面.所以我想要这样的东西:

let someComplexFun p =
    type SomeRecord      = {i:int; x:int; y:int;}
    type SomeOtherRecord = {...}

    let innerFunctionA (x:SomeRecord) = ...
    let innerFunctionB (x:SomeOtherRecord) = ...

    ...
Run Code Online (Sandbox Code Playgroud)

我尝试过但当然编译器不允许我这样做.我查看了文档,我无法在任何地方看到类型必须在模块级别声明.

例如,在LISP中,它似乎完全合法,例如:

(defun foo (when)
    (declare (type (member :now :later) when)) ; Type declaration is illustrative and in this case optional.
    (ecase when
        (:now (something))
        (:later (something-else))))
Run Code Online (Sandbox Code Playgroud)

那么,我错过了什么吗?如果F#完全可以吗?

f# functional-programming

8
推荐指数
1
解决办法
520
查看次数

为什么F#编译器会使用seq {0L ..- 5L ..- 10L}进行扭曲?

我在宣告降序的过程中遇到了一些麻烦int64.

我想要的是这个:

seq{0L..-5L..-10L};;
Run Code Online (Sandbox Code Playgroud)

但是,我收到一个错误:

  seq{0L..-5L..-10L};;
  ---^^^^^^^^^^^^^^^

stdin(5,4): error FS0739: Invalid object, sequence or record expression
Run Code Online (Sandbox Code Playgroud)

有趣的是,它适用于普通int:

> seq{0..-5..-10};;
val it : seq<int> = seq [0; -5; -10]
Run Code Online (Sandbox Code Playgroud)

更有趣的是,如果我在..它之间放置空格,它也开始使用int64:

> seq{0L .. -5L .. -10L};;
val it : seq<int64> = seq [0L; -5L; -10L]
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么编译器会进入扭曲状态seq{0L..-5L..-10L}吗?

f#

6
推荐指数
1
解决办法
259
查看次数

标签 统计

f# ×6

c# ×2

functional-programming ×2

.net ×1

api ×1

c ×1

c++ ×1

cross-platform ×1

idisposable ×1

sequences ×1