小编Rus*_*tam的帖子

流畅的API - 返回这个还是新的?

我最近提出了一个有趣的问题,流利的方法应该返回什么?他们应该改变当前对象的状态还是创建一个具有新状态的全新对象?

如果这个简短描述不是非常直观,这是一个(不幸的)冗长的例子.这是一个计算器.它执行非常繁重的计算,这就是他通过异步回调返回结果的原因:

public interface ICalculator {
    // because calcualations are too lengthy and run in separate thread
    // these methods do not return values directly, but do a callback
    // defined in IFluentParams
    void Add(); 
    void Mult();
    // ... and so on
}
Run Code Online (Sandbox Code Playgroud)

所以,这是一个设置参数和回调的流畅界面:

public interface IFluentParams {
    IFluentParams WithA(int a);
    IFluentParams WithB(int b);
    IFluentParams WithReturnMethod(Action<int> callback);
    ICalculator GetCalculator();
}
Run Code Online (Sandbox Code Playgroud)

这个接口实现有两个有趣的选项.我将展示它们,然后我会写出我发现它们各自的好坏.

因此,首先是普通,它返回:

public class FluentThisCalc : IFluentParams {
    private int? _a;
    private int? _b;
    private Action<int> _callback;

    public …
Run Code Online (Sandbox Code Playgroud)

c# java oop design-patterns fluent-interface

13
推荐指数
1
解决办法
1420
查看次数

将元组添加到printfn等函数中

我想给一个printf函数一个元组:

let tuple = ("Hello", "world")
do printfn "%s %s" tuple
Run Code Online (Sandbox Code Playgroud)

当然,这不起作用,编译器首先说,它需要string而不是string*string.我写的如下:

let tuple = ("Hello", "world")
do printfn "%s %s" <| fst tuple
Run Code Online (Sandbox Code Playgroud)

然后编译器合理地注意到现在我有类型的函数值string -> unit.说得通.我可以写

let tuple = ("Hello", "world")
do printfn "%s %s" <| fst tuple <| snd tuple
Run Code Online (Sandbox Code Playgroud)

它对我有用.但我想知道,如果有任何方法可以做得更好,就像

let tuple = ("Hello", "world")
do printfn "%s %s" <| magic tuple
Run Code Online (Sandbox Code Playgroud)

我的问题是我无法获得printf需要哪种类型以便打印两个参数.什么magic功能看起来像?

f# tuples operators

12
推荐指数
1
解决办法
2377
查看次数

Microsoft.FSharp.Collections与System.Collections.Immutable

我重新发现在.Net中有一堆不可变的集合

F#是一种专注于不变性的语言,它有自己的不可变数据类型.有趣的是,在F#的任何阅读中我都没有看到上述不可变集合的引用.

我想知道那些不可变集合和F#集合之间有什么关系吗?有什么指导方针可以使用吗?什么是更好的,F#Map<_,_>还是ImmutableDictionary(TKey, TValue)等等?

更新也许我可以问如下:有没有人在同一个项目中使用这两个库或者比较他们的生产力?或者就是这样 - 首先是C#,后者是F#,就是这样吗?

.net collections f# immutability

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

具有超时的F#异步工作流程

我真的很喜欢F#的async工作流程,但就我而言,它有一个严重的问题:它不允许创建应该执行不超过某个特定时间跨度的工作流程.

为了更清楚,这是我为自己写的一个简单的函数:

let withTimeout operation timeout = async {
    try
        return Some <| Async.RunSynchronously (operation, timeout)
    with :? TimeoutException -> return None
}
Run Code Online (Sandbox Code Playgroud)

即签名是

val withTimeout : operation:Async<'a> -> timeout:int -> Async<'a option>
Run Code Online (Sandbox Code Playgroud)

示例用法:

let op = async { 
    do! Async.Sleep(1000) 
    return 1
}
#time
withTimeout op 2000 |> Async.RunSynchronously;;
// Real: 00:00:01.116, CPU: 00:00:00.015, GC gen0: 0, gen1: 0, gen2: 0
// val it : unit option = Some 1
withTimeout op 2000 |> Async.RunSynchronously;;
// Real: …
Run Code Online (Sandbox Code Playgroud)

.net f# asynchronous timeout

8
推荐指数
3
解决办法
1679
查看次数

按位运算结果和布尔值

让我感到沮丧的代码如下:

bool a = 0x00000FF0 & 0x00000FF0 == 0x00000FF0;
if (a) {
  Serial.println("True");
} else {
  Serial.println("False");
}
Run Code Online (Sandbox Code Playgroud)

这打印"假".我真的不明白为什么.更多测试:

bool a = 0x00000FF0 & 0x00000FF0 == 0x00000FF0;
Serial.println(a);
Run Code Online (Sandbox Code Playgroud)

打印0.

和:

unsigned long a = 0x00000FF0 & 0x00000FF0;
Serial.println(a, HEX);
Run Code Online (Sandbox Code Playgroud)

打印FF0.

c c++

6
推荐指数
3
解决办法
207
查看次数

反思以确定属性是否属于选项类型

我使用反射用数据填充一些对象的字段.由于我的对象是F#类型,它有一些Option字段.如有选择权

property.SetValue(object, newValue)
Run Code Online (Sandbox Code Playgroud)

合理地失败,因为它需要

property.SetValue(object, Some(newValue))
Run Code Online (Sandbox Code Playgroud)

因此,我试图找出一个属性是否类型Option.我可以这样做:

let isOption (p:PropertyInfo) = p.PropertyType.Name.StartsWith("FSharpOption")
Run Code Online (Sandbox Code Playgroud)

但必须有更好的方法,不是吗?我必须说,这是奇怪,我有没有方法IsOptionFSharpType.

reflection f#

5
推荐指数
1
解决办法
714
查看次数

管道运营商拒绝工作

我无法理解为什么会这样

let data = 
    JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(
         File.ReadAllText <| Path.Combine(myPath, "ejv.json"))
Run Code Online (Sandbox Code Playgroud)

没关系,而这个

let data = 
    JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> 
    <| File.ReadAllText
    <| Path.Combine(myPath, "ejv.json")
Run Code Online (Sandbox Code Playgroud)

给我两个错误,首先是:

第一个错误

第二是:

第二个错误

我做错了什么?

UPDATE @PatrykĆwiek提出了一个很好的编辑,它似乎修复了类型的错误:

let data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> 
       << File.ReadAllText 
       <| Path.Combine(myPath, "ejv.json")
Run Code Online (Sandbox Code Playgroud)

但它产生了另一个令人费解的消息:意外的类型参数.这是一个截图:

意外的类型参数.

我可以很容易地删除它删除<Dictionary<string, Dictionary<string, string>>>但在这种情况下我的数据是object类型,而不是Dictionary.我可以以某种方式保存类型信息使用流水线吗?

感谢@PatrykĆwiek解决方案如下:

let d<'a>(s:string) = JsonConvert.DeserializeObject<'a>(s)
let data = 
    Path.Combine(myPath, "ejv.json") 
    |> File.ReadAllText 
    |> d<Dictionary<string, Dictionary<string, string>>> with 
Run Code Online (Sandbox Code Playgroud)

我不知道为什么,但没有别名d它不起作用.

generics f# pipeline

5
推荐指数
1
解决办法
122
查看次数

VBA Double vs Single舍入

在我的MS Excel中,我对不同数据类型的舍入操作有不同的行为:

如果是单身:

? Application.Round(6.575!, 2)
 6.57 
Run Code Online (Sandbox Code Playgroud)

如果是Double:

? Application.Round(6.575#, 2)
 6.58 
Run Code Online (Sandbox Code Playgroud)

有人知道为什么吗?


更新:@paxdiablo给出了一个很好的答案,所以只是为了在这里重现它:

在单精度中,6.575是二进制表示的0 10000001 101001 0011 0011 0011 0011,或6.57499980926513671875.这轮到6.57

在双精度中,增加了更多的0011,它们的重量足以使数量略大于6.575(6.57500000000000017763568394003),因此它将达到6.58

math excel vba excel-vba

4
推荐指数
1
解决办法
4074
查看次数

F#中的Postfix条件运算符

在Perl语言中,人们可以写出类似的内容

someFunction() if $x == 0
Run Code Online (Sandbox Code Playgroud)

即在后缀表示法中应用条件.

我确信在F#中必须有类似的表达式,因为它在处理函数时非常灵活.但是当我试着写的时候

someFunction() if x = 0
Run Code Online (Sandbox Code Playgroud)

要么

someFunction() << if x = 0
Run Code Online (Sandbox Code Playgroud)

我收到了预期的错误消息.有没有办法在F#中实现更多或更少的通用后缀条件运算符?

f# postfix-operator

4
推荐指数
1
解决办法
420
查看次数

通过函数调用区分联合模式匹配

我的问题受到这个问题的启发:链接

这是一个代码:

    type A = 
        | X of int * int
        | Y of string

    let f (A.X(a, b)) = a + b 
Run Code Online (Sandbox Code Playgroud)

它有效,但有警告: 警告

说得通; 我和Y没有比赛.

但是,如果我添加一行

    let f (A.Y(s)) = 10
Run Code Online (Sandbox Code Playgroud)

然后我收到一个错误:

错误

有没有一种很好的方法来修复它并仍然在函数参数中使用模式匹配?如果没有,那么为什么他们会创建这样奇怪的语法,这总是会引发警告?

f# pattern-matching discriminated-union

4
推荐指数
1
解决办法
350
查看次数