2017-11-10 101 views
2

我对SML(来自java世界)和我所了解的 结构与java类相似&的签名是java接口。如何将getter/setter与sml结构相关

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的值并给出不同的回调函数?

回答

2

结构是最类似的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 

另外请注意,没有new运营商SML结构。函子可以用来创建新的结构,但是它们都必须在源代码级别进行表示。例如,不可能在循环中创建可变数目的结构。

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

+0

所以现在我可以在changeCallback()中设置'state'?但后来我有一个函数引用不是一个int。那会是什么语法(已经试过'_')? –

+0

我不认识'_'语法。我认为你需要在仿函数的签名参数中提供一个具体的类型。 –

1

要提供弗洛里安的答案,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?”,考虑到它不是面向对象的,导向。