【问题标题】:Going over a record type in SML?浏览 SML 中的记录类型?
【发布时间】:2017-03-22 08:33:18
【问题描述】:

我有这种特殊的类型,采取。

type taken = {course:string, student:int, grade:real};

我想查看此类列表,并找到匹配的课程和学生。如果我找到了,那么我必须将等级更改为预设变量 G。以下是我现在拥有的。

exception unTaken;
fun updateGrade (T:taken, []:taken list) = raise unTaken
  | updateGrade (T, {course = #course(T), student = #student(T), ...}::rest) =
    {course = #course(T), student = #student(T), grade = G}
  | updateGrade (T, TL) = updateGrade (T, (tl TL));

如果到达已获取列表的末尾,我会引发异常。 第二个选项是,如果它与 T 中的课程和名称匹配,则将其设置为相同的课程和学生,但将 G 更改为预设变量。否则,请继续浏览列表。


问题是,我不断收到类似于以下错误的错误

stdIn:3.21-3.28 Error: syntax error: deleting  HASH ID
stdIn:3.43-3.52 Error: syntax error: deleting  HASH ID LPAREN
stdIn:3.53 Error: syntax error found at RPAREN

知道发生了什么吗?请问如何解决这些错误?

【问题讨论】:

    标签: list tuples sml


    【解决方案1】:

    这里有一些问题:

    • 按照惯例,变量名保持小写,值构造函数保持大写。
    • 不要在同一模式中两次使用同一变量(您在多个地方使用了T)。一些模式匹配语言(Erlang、Prolog)允许这意味着这些变量覆盖的值应该是等价的,但标准 ML 不支持这一点。
    • 不要在模式中使用记录获取器#course / #student。它们是行为类似于函数的宏。您可以对部分记录进行模式匹配,但语法略有不同(参见下面的第二个示例)。

    这是一个固定版本:

    fun updateGrade (t1 : taken, []) = raise unTaken
      | updateGrade (t1 : taken, t2::ts) =
        if #course t1 = #course t2 andalso #student t1 = #student t2
        then t1 :: ts
        else t2 :: updateGrade (t1, ts)
    

    这是对记录执行模式匹配的固定版本:

    fun updateGrade (t1 : taken, []) = raise unTaken
      | updateGrade (t1 as { course = course1, student = student1, ... },
                     (t2 as { course = course2, student = student2, ... })::ts) =
        if course1 = course2 andalso student1 = student2
        then t1 :: ts
        else t2 :: updateGrade (t1, ts)
    

    我也能问一下如何调试这些错误吗?

    由于编译器通常在发生语法错误时仍然无用,我不确定是否有比将代码展示给其他人或将其与您所知道的最相似的教科书示例进行比较更好的解决方案。标准 ML 确实缺少示例代码,并且记录语法比大多数语言的其他部分更复杂。

    【讨论】:

    • 我认为您已经正确识别了问题和解决方案,但我不确定,因为您的术语对我来说似乎很奇怪。 “将T{course = #student(T), ...} 统一”是否意味着“拥有一个引用值变量T 的子模式{course = #student(T), ...}”?
    • @ruakh:我怀疑 Andrew 的意图是两次使用相同的模式变量,并且只有当它们匹配相同的子结构时才使模式成功。我将重新表述我的答案,以减少对 Andrew 意图的假设。
    • 您对编译器消息的无用性质是正确的。根据我的经验,SML/NJ 是最没有帮助的编译器之一。你知道吗? Poly/ML 更好吗?
    • @JohnColeman:根据我的经验,Poly/ML 和莫斯科 ML 的错误都更容易阅读。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多