【问题标题】:SML : Changing value of INT in a structureSML:改变结构中 INT 的值
【发布时间】:2016-04-10 18:43:11
【问题描述】:

我有一个小问题。

我进行了计算,但我的所有 ID 不再相互跟踪(因为在计算过程中进行了一些删除)。不幸的是,为了使我的结果有效,我需要这个顺序......:/

因此,为了简化任务,我创建了一个外部函数,它将“重命名”所有 ID,但我不知道如何执行此操作。

这是我得到的功能:

fun setId (W {id, ...}) = 
let 
in
    print( "[" ^ Int.toString (id) ^ "]");
    print( "[" ^ Int.toString (!nextId) ^ "]\n");
    Ref.incr nextId
end

(对于那些正在徘徊的人app只是一个自制函数,可以对列表的每个元素执行相同的计算,但这并不重要。)

当我执行这段代码时,我在输出中获得:

[0][0]
[1][1]
[2][2]
[3][3]
[4][4]
[5][5]
[6][6]
[7][7]
[8][8]
[9][9]
[10][10]
[11][11]
[12][12]
[13][13]
[14][14]
[15][15]
[16][16]
[17][17]
[18][18]
[19][19]
[20][20]
[21][21]
[22][22]
[39][23]
[40][24]
[41][25]
[42][26]
[43][27]
[44][28]
[45][29]
[46][30]
[47][31]
[48][32]
[49][33]
[50][34]
[51][35]
[52][36]
[53][37]

如您所见,[23] [39] 存在一个大问题,该列表没有以下数字。 :/

基本上,我希望函数setId能够修改节点的ID。但我不知道如何:/

这里是数据类型 Node 用于理解目的:

    datatype node =
          W of {
              id              : int
            , predId          : int option
            , creationDepcy   : Dependency.depcy
            , nominalDepcies  : Dependency.depcy list ref
            , pattern         : Termstore.store
            , propositions    : Propstore.pstore
            , nominals        : Propstore.pstore
            , diamonds        : Termstore.store
            , boxes           : Termstore.store
            , disjunctions    : Termstore.store
            , nglstore        : Termstore.store
            , lazyProps       : Lazystore.store
            , lazyNoms        : Lazynomstore.store
            , lazyBoxes       : Lazyboxstore.store
            , blockedDiamonds : (Term.index * int) list ref
            , branchPoints    : int list ref
            }

提前感谢您的帮助!

最好的问候。

【问题讨论】:

    标签: algorithm types sml smlnj


    【解决方案1】:

    由于id 输入为int,因此无法修改。如果将其更改为 int ref,则可以对其进行修改,但您还必须更改访问器以取消引用 ref

    另一种解决方案是创建一个从旧 ID 映射到新 ID 的数组,并使用该数组进行表示,但这似乎更复杂。

    【讨论】:

      【解决方案2】:

      由于ints 是不可变的——您可以获取节点列表并将其替换为新的节点列表:

      fun newID (W(x), i) =
                 W({
                    id               = i
                  , predId           =  #predId x
                  , creationDepcy    =  #creationDepcy x
                  , nominalDepcies   =  #nominalDepcies x
                  , pattern          =  #pattern x
                  , propositions     =  #propositions x
                  , nominals         =  #nominals x
                  , diamonds         =  #diamonds x
                  , boxes            =  #boxes x
                  , disjunctions     =  #disjunctions x
                  , nglstore         =  #nglstore x
                  , lazyProps        =  #lazyProps x
                  , lazyNoms         =  #lazyNoms x
                  , lazyBoxes        =  #lazyBoxes x
                  , blockedDiamonds  =  #blockedDiamonds x
                  , branchPoints     =  #branchPoints x
                 });
      
      
      fun imap _ [] _ = []
      |   imap f (x::xs) i = f(x,i):: (imap f xs (i+1));
      

      imap 代表“增量映射”)

      那么如果xs是函数调用的节点列表

      imap newID xs 0
      

      将产生一个新的节点列表,其中 id 字段以 0 开头的连续整数

      免责声明:我当然没有在您的设置上尝试此操作,因为我创建了一个具有id 字段的记录数据类型并成功使用了这种方法。显然,由于所有的复制,这不是您想要做的很多事情,但如果它位于代码中的某个特定点,那应该没问题。

      【讨论】:

      • 是的,需要注意的是它是一个 new 节点列表,任何持有对初始列表的引用的东西都不会看到更改。
      • @DougCurrie 是的,这是一个重要的警告。我认为对于 OP 来说,最有意义的做法是要么遵循您将 id 更改为 int ref 的建议,要么找到一种重写它的方法,以便在整个过程中使用不可变的数据结构。
      【解决方案3】:

      几乎等同于 John 的解决方案,以下是如何在不使用引用的情况下更新节点列表,而是使用折叠。函数setId是一样的。

      fun setIds firstId ws =
          #1 (foldr (fn (w,(ws',nextId)) => (setId w nextId::ws', nextId+1)) ([],firstId) ws)
      

      运行setIds 1 [w1, w2, w3, ...] 将产生[w1', w2', w3', ...]

      【讨论】:

      • 哇,我没有意识到我的答案与约翰的答案有多接近。我将缩短它以突出差异。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多