1

我正在研究 F# 是出于个人“有趣”的原因,并以一种功能性的方式探索思维。我正在尝试复制我今天早上编写的其他代码片段的功能:here

我在下面编写了这段代码,但似乎我无法真正访问我的for ... in声明中的项目。

open System
open System.Net
open System.Web.Helpers

let data = Json.Decode((new WebClient()).DownloadString("http://sw.cs.wwu.edu/~fugiera/matches"))

let myList = [for x : DynamicJsonArray in downcast data do if x?status != "complete" then yield x?home_team.goals ]

Console.ReadKey() |> ignore

我现在真的只是想把所有东西都包起来,并且可以使用一两个指针!

谢谢

4

1 回答 1

4

首先,您的for循环在错误的位置投射。你想投到dataDynamicJsonArray不是x。您还需要转换xDynamicJsonObject.

let myList = [
    for x in (data :?> DynamicJsonArray) do
        let x = x :?> DynamicJsonObject
        ... 

F# 不像 C# 那样内置对动态对象的支持,因此您不能使用标准运算符?来获取对象的属性。

我花了大约 20 秒试图弄清楚如何使用普通 API 提取动态属性,但很无聊。

幸运的是,F# 有一个称为 Type Providers 的功能,它在某些方面类似于动态对象,但在超级类固醇上。他们会在这里完美地工作。

添加对 NuGet 包的引用FSharp.Data并尝试使用以下代码来确定大小:

open FSharp.Data

type WorldCup = JsonProvider<"http://worldcup.sfg.io/matches">

for game in WorldCup.GetSamples() do
    match (game.Status, game.HomeTeam.Record, game.AwayTeam.Record) with
    | ("completed", Some(ht), Some(at)) ->
        printfn "%s %d vs %s %d" ht.Country ht.Goals at.Country at.Goals
    | _ -> () 

如果您只想要工作代码,那就去吧。有关更多详细信息,请继续阅读。

与链接的 C# 代码相比,需要注意的一些事项:

  • 您在 JSON 对象上获得智能感知,向您显示可用的属性(不要在 C# 中获得)
  • 如果您打错了属性名称,或者假设某个属性在不可用时始终可用,则您的代码将无法构建。这可以防止 C# 中可能发生的各种运行时错误。

特别要注意的是,在原始 JSON 中,game.HomeTeam并不总是存在(即,对于尚未玩过的游戏,它不会被填充)。您的 C# 仍然可以访问game.home_team.country, game.home_team.goals,因为您正在过滤status. 这目前还可以,但总的来说这是有风险的,因为这可能会在运行时爆炸。

在 F# 中,JSON 类型提供程序注意到HomeTeam并且AwayTeam并不总是存在,因此它将它们公开为optiontypes类型系统要求您考虑当这些值丢失时该怎么做。这是好事!

因此,您会看到代码检查了 3 件事:1. status = "completed"2.HomeTeam已定义(是Some(homeTeam),不是None)3.AwayTeam已定义。如果是这样,我们打印详细信息。如果没有,请跳过它。

于 2014-06-24T03:02:38.587 回答