【问题标题】:How to associate a getter/setter with a sml structure如何将 getter/setter 与 sml 结构相关联
【发布时间】:2017-11-12 03:00:15
【问题描述】:

我对 SML(来自 java 世界)和我的理解相对较新 结构类似于 java 类,签名是 java 接口。

SML 结构中的一切都是不可变的。有没有可能有一个可以设置值的变量?

functor Make(M : sig
                 type data
                 val callback : _
             end) = struct

    val cb  = M.callback

    fun simple nn =
        cb(nn);
        return nn

    fun changeCallback cc = 
        cb = cc
end

上面的代码在没有 changeCallback 函数的情况下编译得很好。有什么办法可以改变变量cb的值,给出不同的回调函数?

【问题讨论】:

    标签: sml smlnj


    【解决方案1】:

    结构是最相似的 Java 类,它们不能被实例化并且只有静态成员。就像在 Java 中一样,拥有全局可变状态被认为是一个坏主意。

    你可以添加可变的全局状态

    val cb : (argtype -> unit) ref = ref M.callback
    

    声明,就像您可以在 Java 类中拥有 public static Callback 成员一样。但这往往会导致问题。您还必须稍微调整其余代码,以使用! 读取引用并使用:= 写入它:

    functor Make(M : sig
                     type data
                     type arg
                     val callback : arg -> unit
                 end) = struct
    
        val cb = ref M.callback
    
        fun simple nn = ((!cb) nn; nn)
    
        fun changeCallback cc =
            cb := cc
    end
    

    另请注意,SML 结构没有new 运算符。函子可用于创建新结构,但它们都必须在源代码级别表示。例如,不可能在循环中创建可变数量的结构。

    要模拟 Java 类,您需要使用记录(可能带有 … ref 类型的成员)。

    【讨论】:

    • 所以现在我可以在 changeCallback() 中设置 state 了吗?但后来我有一个函数引用,而不是真正的 int。那会是什么语法(已经尝试过_)?
    • 我不认识_ 语法。我认为您需要在函子的签名参数中提供具体类型。
    【解决方案2】:

    为了提供 Florian 的答案,SML 确实有可变变量,其中 val foo = ref 0 使 foo 成为可变 int,!foo 是取消引用的值(实际的 int),foo := 2 更改其值,fun incr r = (r := !r + 1 ; !r) 是一个将其可变参数增加 1 并返回更新值的函数。这是在不使用模块系统(结构、签名、函子)的情况下完成的。请注意,将; 视为 SML 中的二元运算符比将其视为命令式语言中的“语句分隔符”更好。

    SML 不像 Ocaml 那样支持基于类的面向对象编程,坦率地说,用模块系统来模拟这一点很可惜。你可能想看看Ocaml's object-oriented programming

    如果您正在尝试完成一项特定任务,而您的基于类的思维阻碍了您的工作,那么考虑到它不是面向对象的,也许一个更好的问题是“您将如何在 SML 中为 X 建模?” .

    【讨论】:

      猜你喜欢
      • 2017-02-26
      • 1970-01-01
      • 2019-09-04
      • 1970-01-01
      • 2014-05-18
      • 2023-03-04
      • 2014-02-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多