热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

处理F#中的.NET通用词典?

如何解决《处理F#中的.NET通用词典?》经验,为你挑选了1个好方法。



1> Fyodor Soiki..:

首先,你的直接问题:你定义Atts属性的方式,它不是一个"存储"在某个地方的值,可以通过属性访问.相反,您的定义意味着"每次有人读取此属性,创建一个新字典并返回它".这就是你的新属性没有出现在词典中的原因:每次阅读时它都是一个不同的词典root.Atts.

要创建具有支持字段和初始值的属性,请使用member val:

type XmlNode(...) =
   ...
   member val Atts = Dictionary()

现在,回答一些隐含的问题.

第一项业务: "修改属性"和"纯粹功能"是矛盾的想法.函数式编程意味着不可变数据.什么都没有改变.推进计算的方法是在每一步创建一个新的数据,而不是覆盖前一个.这个基本思想在实践中证明是非常有价值的:更安全的线程,琐碎的"撤销"场景,平凡的并行化,对其他机器的简单分配,甚至通过持久数据结构减少内存消耗.

不变性是非常重要的一点,我恳请你不要瞥一眼.接受它需要精神上的转变.从我自己(以及我认识的其他人)的经验来看,很难从命令式编程中获得,但它非常值得.

第二:不要使用类和属性.从技术上讲,面向对象的编程(在消息传递的意义上)与功能并不矛盾,但在C++,Java,C#等人的实践中使用的企业风格矛盾的,因为它强调了这个想法"方法是改变对象状态的操作",这是不起作用的(参见上文).所以最好避免面向对象的结构,至少在你学习的时候.特别是因为F#提供了更好的数据编码方式:

type XmlNode = { TagName: string; InnerValue: string; Atts: (string*string) list }

(注意我Atts的不是字典;我们稍后会谈到这一点)

同样,要表示对数据的操作,请使用函数,而不是方法:

 let printNode (node: XmlNode) = (* we'll come to the implementation later *)

第三:为什么你说你"显然"需要修改属性?您展示的代码并不需要这样做.例如,使用我XmlNode上面的定义,我可以这样重写你的代码:

[]
let main argv = 
    let root = { TagName = "root"; InnerValue = "test"; Atts = ["att", "val"] }
    printfn "%s" (printNode root)
    ...

但即使这是真正的需要,你也不应该"到位".正如我在上面讨论不变性时所描述的那样,你不应该改变现有节点,而是创建一个与你想要"修改"的新节点不同的新节点:

let addAttr node name value = { node with Atts = (name, value) :: node.Atts }

在此实现中,我获取属性的节点和名称/值,并生成一个节点,该节点的Atts列表包含原始节点中Atts具有前置新属性的任何内容.

原始Atts列表保持不变,未经修改.但这并不意味着内存消耗的两倍:因为我们知道原始列表永远不会改变,我们可以重用它:我们通过仅为新项目分配内存并将旧列表的引用包括为"其他项目"来创建新列表".如果旧列表可能会发生变化,我们无法做到这一点,我们必须创建一个完整的副本(请参阅" 防御性副本 ").该策略称为" 持久数据结构 ".它是函数式编程的支柱之一.

最后,对于字符串格式化,我建议使用sprintf而不是StringBuilder.它提供类似的性能优势,但另外提供类型安全性.例如,代码sprintf "%s" 5将无法编译,抱怨格式需要一个字符串,但最后一个参数5是一个数字.有了这个,我们可以实现这个printNode功能:

 let printNode (node: XmlNode) =
    let atts = seq { for n, v in node.Atts -> sprintf " %s=\"%s\"" n v } |> String.concat ""
    sprintf "<%s%s>%s" node.TagName atts node.InnerValue node.TagName

作为参考,这是您的完整程序,以功能样式重写:

type XmlNode = { TagName: string; InnerValue: string; Atts: (string*string) list }

let printNode (node: XmlNode) =
    let atts = seq { for n, v in node.Atts -> sprintf " %s=\"%s\"" n v } |> String.concat ""
    sprintf "<%s%s>%s" node.TagName atts node.InnerValue node.TagName

[]
let main argv = 
   let root = { TagName = "root"; InnerValue = "test"; Atts = ["att", "val"] }
   printfn "%s" (printNode root)

   Console.ReadLine() |> ignore
   0


推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文详细介绍了PHP中与URL处理相关的三个函数:http_build_query、parse_str和查询字符串的解析。通过示例和语法说明,讲解了这些函数的使用方法和作用,帮助读者更好地理解和应用。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
author-avatar
仰望天空说再见
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有