概要
在任何表示整数的语言中发布示例,而不直接使用机器整数。包括到的映射和用户定义类型的。空间和/或时间效率的要点。
原始问题
在a certain rather bold answer关于面向对象编程问题的评论中,我表示我相信机器原语不是对象,但无法真正证实这种说法,就像那张海报一样。答案无法证实他关于面向对象哲学的普遍性和基本性的主张。
这让我思考。在C ++中,机器基元不参与类层次结构的语言是否可以定义一个对象类型 - 比如Integer
- 不使用机器基元存储它的价值?
有this beautiful bit of template hackery实现教会数字。不幸的是,由于整数和教堂数字之间的转换严格地发生在编译时,因此没有办法绕过用户输入使用机器整数。
所以我正在寻找的是与上述相同的运行时,但不一定使用具有合理空间要求的教会数字,可以用C ++等语言实现,而不是更高 - 订单功能。我希望看到其他语言的例子,特别是那些利用有趣的动态打字技巧的例子。只要存储的地址严格地使用而不是其整数值,指针和函数指针就不应算作基元。
用于容纳所有整数(即不仅仅是整数)的奖励积分,以及用于设计也可以实现浮点数的系统的超级奖励积分。
为了避免任何不愉快,并鼓励礼貌的讨论,我从一开始就把它作为一个社区维基问题。
答案 0 :(得分:2)
这里有一个可用于正整数的类。并且可以很容易地扩展到负面因素。 它支持加法,减法,相等,不等式和乘法。可以基于现有运营商来划分分部。总而言之,我会说它几乎代表整数,并且没有任何简单类型的使用。实际上,班级使用的唯一类型就是自我。
实现基本上是一个带有一些优化的链接列表,因此每次操作都不需要遍历列表。
public class MyInt
{
private MyInt _previous;
private MyInt _first;
private bool isEven;
private MyInt(MyInt previous)
{
next++;
_previous = previous;
isEven = previous == null ? true : !previous.isEven;
getFirst();
x = next;
}
private void getFirst()
{
if (_previous == null)
_first = null;
else if (_previous._first == null)
_first = this;
else
_first = _previous._first;
}
private MyInt(MyInt copy, bool dontuse)
{
_previous = copy._previous == null ? null : new MyInt(copy._previous,true);
getFirst();
x = copy.x;
}
public static MyInt operator +(MyInt lhs, MyInt rhs)
{
if (object.ReferenceEquals(lhs, rhs))
rhs = new MyInt(rhs, true);
if (lhs == MyInt.Zero)
return rhs;
if (rhs == MyInt.Zero)
return lhs;
else
{
var isEven = rhs.isEven == lhs.isEven;
var result = new MyInt(rhs, true);
result._first._previous = lhs;
result._first = lhs._first;
result.isEven = isEven;
return result;
}
}
public static MyInt operator -(MyInt lhs, MyInt rhs)
{
if (lhs == rhs)
return MyInt.Zero;
if (rhs == MyInt.Zero)
return lhs;
if (lhs == MyInt.Zero)
throw new InvalidOperationException("Negatives not supported");
else
{
return lhs._previous - rhs._previous;
}
}
public static MyInt operator --(MyInt un)
{
if (un == MyInt.Zero)
throw new InvalidOperationException("Negatives not supported");
return un._previous;
}
public static MyInt operator *(MyInt lhs, MyInt rhs)
{
if (lhs == MyInt.Zero || rhs == MyInt.Zero)
return MyInt.Zero;
var temp = lhs;
var one = One;
var two = one + one;
var zero = MyInt.Zero;
var dbl = lhs + lhs;
if (rhs == MyInt.One)
return lhs;
if (rhs == two)
return dbl;
for (MyInt times = rhs + one; times._previous._previous != zero && times._previous != zero; times = times-two)
{
temp = temp + dbl;
}
if (rhs.isEven)
temp = temp - lhs;
return temp;
}
public static bool operator ==(MyInt lhs, MyInt rhs)
{
if (object.ReferenceEquals(lhs, null) && object.ReferenceEquals(rhs, null))
return true;
if ((object.ReferenceEquals(lhs, null) || object.ReferenceEquals(rhs, null)))
return false;
if (object.ReferenceEquals(lhs._previous, null) && object.ReferenceEquals(rhs._previous, null))
return true;
if ((object.ReferenceEquals(lhs._previous, null) || object.ReferenceEquals(rhs._previous, null)))
return false;
return (lhs._previous == rhs._previous);
}
public static bool operator !=(MyInt lhs, MyInt rhs)
{
return !(lhs == rhs);
}
public override bool Equals(object obj)
{
return obj is MyInt && ((MyInt)obj) == this;
}
public static MyInt Zero
{
get
{
return new MyInt(null);
}
}
public static MyInt One
{
get
{
return new MyInt(new MyInt(null));
}
}
}
答案 1 :(得分:1)
总有Lisp,其中0可以表示为()
(空列表),1表示(())
,2表示(() ())
,等等。一天,但当然没有任何Lisp实现使用它,因为它太慢而不能相信。