我正在考虑为Haskell中的面向对象语言设计Python解释器。我面临的一个特殊问题涉及对象身份的概念。如果我们考虑Python的id(object)
函数,则定义表明它返回对象的“标识”。这是一个整数(或长整数),保证在该生命周期内该对象是唯一且恒定的。具有非重叠生存期的两个对象可以具有相同的id()值。 (实施说明:这是对象的地址。)
在Haskell中实现这样的概念的一般方法是什么?
答案 0 :(得分:4)
我假设您的翻译将在State
monad中工作。可能该州将包括一系列活动对象和诸如此类的东西。您可以做的是跟踪可用(未使用)id
s(表示为Int
s)的列表,并使用Object
为每个Int
添加注释,即它的id
。此id
取自可用id
列表,并在创建时分配给它。因此,两个Object
实例不能具有相同的id
。
观察我谈过Int
。你可以去Integer
,但最终可能效率降低。使用Int
s确实意味着您必须将id
个已销毁的对象添加回可用id
的池(列表)中(否则您将耗尽,最终)。因此,我设想这样的事情:
data Object a = Obj Int a
instance Eq (Object a) where
Obj i _ == Obj j _ = i == j
type InterpreterState a = State [Int] a
createObject :: a -> InterpreterState (Object a)
createObject a = do
(i:is) <- get
put is
return $ Obj i a
destroyObject :: Object a -> InterpreterState ()
destroyObject (Obj i a) = do
modify (i:)
(请注意InterpreterState
在您的情况下要复杂得多,createObject
和destroyObject
应该在状态中添加/删除对象。但这不是重点。)
答案 1 :(得分:3)
这个问题的答案取决于你将如何实现这些想要获取id的对象。如果两个变量包含相同的对象,它将如何看待?您基本上需要在变量中存储对“可变”对象的引用,问题是您是如何做到这一点的。如果你只是将简单值与变量名相关联,那么一个变量中的变化永远不会反映在另一个变量中,并且不存在对象标识这样的东西。
因此变量需要保持对对象的实际当前值的引用。这看起来像这样:
data VariableContent = Int | String | ObjRef Int | ...
data ObjStore = ObjStore [(Int, Object)]
data ProgramState = ProgramState ObjStore VariableStore ...
此处ObjRef
每个ObjStore
引用Int
中可以通过ObjRef
中存储的Int
ID访问的值。这id(object)
函数返回id
是正确的。
通常,{{1}}函数很大程度上取决于您实际实现对象引用的方式。