Square is-a Rect? (more thoughts on immutable programming)

ajoo 2002-05-07 07:27:50
there's classic paradox, "whether square is a rectangle".
Actually this question does not make sense. Without giving all the required behavior and runtime semantics definition, nobody can tell the answer.

I remember somebody presented this question to me on mit bbs. Based on my assumption of the required operations, getter and setters, I told him "yes". And then he started laughing at me, "I set a trap, and you jumped in. How do you handle the setters?"

I knew what he means, in his assumption, the interface would be like
Rectangle
int getWidth();
int getHeight();
void setWidth(int);
void setHeight(int);
Square
int getSize();
void setSize();

Then of course, Square cannot be a subtype of Rectangle because the setters are not safe after subsumption.
Square s;
Rectangle r = s;
r.setWidth(5);
//now s is not a square at all!

But the fact is: we made different assumptions.

If I implement this, I would implement it immutably. i.e.
Rectangle
int getWidth();
int getHeight();
Rectangle setWidth(int); //this is also called functional update
Rectangle setHeight(int);
Square
int getSize();
Square setSize();

then we are safe to say "Square is a Rectangle" now!

Another benefit of "immutable pattern", right?



Also, even though we want to insist on mutable implementation, dividing mutable and immutable parts can also work. i.e.

RectR
int getWidth();
int getHeight();
RectW
void setWidth(int);
void setHeight(int);
Rect: RectR, RectW

SquareR
int getSize();
SquareW
void setSize();
Square: SquareR, SquareW

Here, although there's no "is-a" relationship between Square and Rectangle, there exists such thing between SquareR and RectR, SquareW and RectW.

That is:
SquareR is a RectR (this is natural)

RectW is a SquareW (people may feel surprised by this, but, trust me, it is safe)

So, if you have a function void display(RectR rect);
you can safely use it to display a Rectangle or a Square.

Another advantage of "immutable programming".
...全文
63 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
ajoo 2002-05-25
  • 打赏
  • 举报
回复
bug report? for what? It is not a bug yah! gc works that way. it's almost impossible to design a gc algorithm that can collect only part of an array.
of course, copying instead of sharing would be free of this problem, but it's too expensive. (and even if you are realy concerned about this problem, just use StringBuffer, not hard at all).
jimjxr 2002-05-24
  • 打赏
  • 举报
回复
Runtime complexity, I like that. You're right, JDK's document is not clear on substring, fortunately we have the source code to back it up. Apparently someone filed a bug report on the behavior of the substring, and Sun said it's going to fix it in the next release by adding a compact method, but I'm not sure how it's going to work.
ajoo 2002-05-24
  • 打赏
  • 举报
回复
the only way I can think is to document it clearly.

JDK's documentation lacks many things. they should also add the runtime complexity for each method, specially for methods like substring.
ajoo 2002-05-23
  • 打赏
  • 举报
回复
is the jimjxr yesterday the real jimjxr, or the jimjxr today the real one? If I say jimjxr is happier after the benefit, I need two jimjxr objects to compare, right? how can I compare if you're mutable?
it's getting more and more philosophical. :)
But, it's not so straight-forward to see if mutable or immutable is more natural.

for the substring, I don't think that's a memory leak. nothing can be perfect. immutable string has a lot of benefits. this is just a trade-off.
that's just the way life is, right?

jimjxr 2002-05-22
  • 打赏
  • 举报
回复
hehe, then which one is really me? But I do get your point on the read/write thing. I'm just not sure if immutable is the only way to exploit it.
Anyway, I'm kinda busy these days, hopefully we can continue this topic next week when I have more time to think it through. BTW, on the substring memory leak problem, do you have any good ideas to deal with it?
wangwenyou 2002-05-22
  • 打赏
  • 举报
回复
呵呵:)
ajoo 2002-05-22
  • 打赏
  • 举报
回复
public interface Employee
{
Employee setBenefit(int i);
}
public interface Employees
{
Employee getEmployee(String name);
Employees cons(Employee emp);
}

Employees performance_review(Employees old_employees)
{
Employees newEmployees = Employees.empty;
Employee sad_jimjxr = old_employees.getEmployee("jimjxr(宝宝猫)");
Employee happy_jimjxr = sad_jimjxr.setBenefit(1000000000);
newEmployees = newEmployees.cons(happy_jimjxr);
......
}

before the benefit, jimjxr is the sad jimjxr, after you get the benefit, you are the happy jimjxr.
why so "zhi zhuo" the "self"?

:-)
ajoo 2002-05-19
  • 打赏
  • 举报
回复
love to play computer game. So, in real world, whenever something's going wrong, the first response is "reload!"
but, not possible.

guess this is the only thing that God did a worse job than we can. now, when we are playing "God" in our virtual world (programming), immutable makes reload so easy!



ajoo 2002-05-19
  • 打赏
  • 举报
回复
when I said rare/common, I meant the frequency of doing that.
Of course, each of us will need to drive back sometimes. It's not possible for a car that never need to drive backward.

But, in real world, the read operation is still much more frequent than write operation.

if, we can achieve better performance and a simpler system by sacrificing write operation a bit, I think that's acceptable.

most of the real world objects have states, I don't disagree on that. But, we are only programmers, not God. I don't expect we could make a system that's as complex as the real world.

also, are you comfortable with
int i = a + b;
?
this is a quite natural immutable operation.
wangwenyou 2002-05-18
  • 打赏
  • 举报
回复
二位所言甚是:)
其实,这是所有热爱自己事业的程序员的追求--我们不怕麻烦喜欢麻烦,不是吗:)
jimjxr 2002-05-18
  • 打赏
  • 举报
回复
Ok, I'm not good at metaphors, but I think in real world, mutable is common and immutable is rare, that's why we're more comfortable with mutable objects. Almost all objects in real world are mutable, that is, when they change states, they themselves change, not their clones. Actually I can't think of something that are immutable in real world. It would be really wired for me to get promoted, but have a clone of myself to get the new benefits, don't you think so? :-)
ajoo 2002-05-17
  • 打赏
  • 举报
回复
thanks to wangwenyou. Flattered!

I do like to see my code elegant. Even though I have to spend twice the time to think. But sometimes, it's not possible. just like the "mission impossible". :<
practically, not everything can be perfect. you can go to sun jdk's java.util documentation page. they documented some thought of their collection framework about why they made the compromise in allowing optional methods.
That's a typical example of the conflict between ideal and the reality.

by the way, my research interest is programming languages and OO, that's why I sound quite academic.
wangwenyou 2002-05-17
  • 打赏
  • 举报
回复
呵呵,我一向认为ajoo兄与我不同:我注重商业的可行性,能够降低成本提高效率,构建稳定可靠的商业应用,我就认可--急功近利,所求并非最优的。而你偏重于理论上学术上的提升,很深入的研究各种方案的优劣。对我来说,开发快捷而最好维护,就是好的;对你而言,效率最高最美丽最和谐的代码,犹如美妙的乐章。
看来我错了--这个现实的例子证明了:)
很形象
ajoo 2002-05-17
  • 打赏
  • 举报
回复
an example from real world:
we all know Cars are efficient in moving forward and awkward in moving back.
Would it be more convenient and efficient if the auto manufacturers make cars bidirectional?

1. it'll be more costly to make such car. (as it's harder to write mutable data structure than immutable ones)
2. the requirement to drive backward is rare (normally we do read much more than write)
3. it's much easier to design highway and road to only support forward-only vehicles. (with immutable data structures, the whole system becomes simpler)
4. even if we somehow designed a highway that supports bidirectional vehicles, the overall traffic would be much much worse than a unidirectional one. (with mutable structure, we have to do synchronized for concurrent access, we either have to do copy-on-write or lose resource sharing)

So, although theoretically, a bidirectional car should be more efficient than a unidirectional car because you don't have to turn around to go backward,
in practice, it may be the opposite.
wangwenyou 2002-05-16
  • 打赏
  • 举报
回复
Up
ajoo 2002-05-15
  • 打赏
  • 举报
回复
imho,
functional programming is BETTER than imperative way.

why?
let's first look at some functional language's features
higher order function
pattern match
immutability
All these are great features and will make your coding much easier!

People don't like the idea of immutability because they are used to imperative languages where you can freely change states.
they may say "what do I need variables for if I cannot change their values?"

Well, first of all, without mutability, you can definitely achieve the same thing that imperative language can do.
(let's not talk about db, file, network etc. they need mutability, but they can be implemented as an extension of language)

secondly, it is immutability that enables the higher-order functions.
(remember anonymous class in Java? it can only reference final local variables, it's a verbose version of higher-order function)


At the first look, functional programming may not be that intuitive and easy.
But in large program, you will appreciate the simple world that functional programming gives you.
don't need to spend hours to debug "how and where this variable gets changed?" any more.

performance-wise, functional programming is supposed to be slower than imperatlve way theoretically.
However, in practice, it may be even faster than imperative code. the reasons are listed:
1. immutable structure can dramatically reduce the need of "synchronized".
2. you can safely and easily share instances in your program.
3. without worrying about state change, implementation of immutable data structure can achieve better performance for read.
4. the code is much easier to optimize by the compiler

In Java, functional update means something like Sequence rotate(int r);
what you can get from this kind of functional update is:
1. immutable data structure
2. more freedom in subtype relationship (Square can be subtype of Rect)
3. freedom in changing underlying impl on updates.
(imperative programming does not have this flexibility, even when the current implementation does not fit so well after update)
4. undo becomes a piece of cake.

jimjxr 2002-05-14
  • 打赏
  • 举报
回复
Hehe, you bet functional programming is confusing. I used OCaml once, it confused the hell of me. Do you have any insight in functional programming? Is it better, worse or just different?
wangwenyou 2002-05-14
  • 打赏
  • 举报
回复
我也来Up:)
ajoo 2002-05-13
  • 打赏
  • 举报
回复
up myself.

add points again!
ajoo 2002-05-11
  • 打赏
  • 举报
回复
object oriented, not guru-oriented
:)
He made that assertion based on the same assumption (rect is mutable).

we should not just remember the conclusion. the reasoning is more important.

Hey, how's your progress in the Array example? don't be too lazy.
加载更多回复(11)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧