[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Can't change the value of self

Jonathan Leighton

1/2/2006 12:38:00 AM

This code:

--------------
class Time

# Rounds a time sensibly.
# Currently just hour is supported (as that's the only one needed)
def round_to(unit = :hour)
unless min == 0
new_hour = hour
new_hour += 1 if min > 30
time = Time.local(year, month, day, new_hour)
end
time
end

def round_to!(*args)
self = round_to *args
end

end
--------------

Throws this error:

Can't change the value of self (SyntaxError)
self = round_to *args

Why doesn't it work? What can I do instead?

Thanks

--
Jonathan Leighton
http://turnips... | http://jonathanlei... | http://digital-...



10 Answers

james_b

1/2/2006 12:42:00 AM

0

Jonathan Leighton wrote:
> Can't change the value of self (SyntaxError)
> self = round_to *args
>
> Why doesn't it work? What can I do instead?

"Destructive" methods must alter self using that self's existing
destructive methods.


James

--

http://www.ru... - Ruby Help & Documentation
http://www.artima.c... - Ruby Code & Style: Writers wanted
http://www.rub... - The Ruby Store for Ruby Stuff
http://www.jame... - Playing with Better Toys
http://www.30seco... - Building Better Tools


Hal E. Fulton

1/2/2006 12:48:00 AM

0

James Britt wrote:
> Jonathan Leighton wrote:
>
>> Can't change the value of self (SyntaxError)
>> self = round_to *args
>>
>> Why doesn't it work? What can I do instead?
>
>
> "Destructive" methods must alter self using that self's existing
> destructive methods.

To which we should add: Time has no destructive methods, since
Time objects are immutable.

But someone once created a MutableTime class -- anyone recall
who/when/where and whether it's complete?


Hal




Gary Wright

1/2/2006 1:17:00 AM

0


On Jan 1, 2006, at 7:37 PM, Jonathan Leighton wrote:
> Can't change the value of self (SyntaxError)
> self = round_to *args
>
> Why doesn't it work? What can I do instead?

Instead of

a.round_to!(:hour)

just write

a = a.round_to(:hour)

Or maybe a different name would help:

a = a.closest(:hour)


Gary Wright





Wilson Bilkovich

1/2/2006 3:21:00 AM

0

On 1/1/06, Hal Fulton <hal9000@hypermetrics.com> wrote:
> James Britt wrote:
> > Jonathan Leighton wrote:
> >
> >> Can't change the value of self (SyntaxError)
> >> self = round_to *args
> >>
> >> Why doesn't it work? What can I do instead?
> >
> >
> > "Destructive" methods must alter self using that self's existing
> > destructive methods.
>
> To which we should add: Time has no destructive methods, since
> Time objects are immutable.
>
> But someone once created a MutableTime class -- anyone recall
> who/when/where and whether it's complete?
>

This is why I can't do:
class Fixnum
def double!
self *= 2
end
end
..right? Too bad.

Speaking of methods.. is there a way to do:
class Something
def <<(a, b)
# do something with a and b
end
end

s = Something.new
s << 'a', 'b'
results in a syntax error.

Is that another of those YACC limitations?


George Ogata

1/2/2006 7:19:00 AM

0

Wilson Bilkovich <wilsonb@gmail.com> writes:

> Speaking of methods.. is there a way to do:
> class Something
> def <<(a, b)
> # do something with a and b
> end
> end
>
> s = Something.new
> s << 'a', 'b'
> results in a syntax error.
>

You could do s.<<('a', 'b'), but it seems unrubyish. Perhaps you
could settle for:

s << ['a', 'b']

> Is that another of those YACC limitations?

Hmmm, I don't know if it's a limitation, but it could get confusing.
Consider:

four, three = 1 << 2, 3
arr = [x << 1, x << 2]

And if you do it for `<<', then what about `+', `-', `%'? If you do
do it for those, then you start to lose really basic stuff like:

arr = [a + 1, b + 1]
b, a = a % b, b until b == 0

Ronald E Jeffries

1/2/2006 10:28:00 AM

0

On Mon, 2 Jan 2006 09:37:45 +0900, Jonathan Leighton <lists@turnipspatch.com>
wrote:

>Can't change the value of self (SyntaxError)
> self = round_to *args
>
>Why doesn't it work? What can I do instead?

One way of thinking about reassigning self is if you imagine in a numeric class
saying

def double
self *= 2
end

That would amount to saying, if we did 1.double,
1 becomes 2
which would mean that 1+1 would thereafter be 4, and that would be bad.

What we need is not the value 1 to become 2, but to get the value 2 back when we
say 1.double. So we say

def double
return self*2
end

or, since "return" is implied

def double
self*2
end

In general in OO, an object can change its contents, but it cannot change its
"self". What should happen in this program?

one = 1
another_one = 1
assert_equal(2, one+one)
assert_equal(2, another_one+another_one)
one.double
assert_equal(4, one+one)
assert_equal(???,another_one+another_one)
assert_equal(???, 1+1)

When we double one, if the self*=2 thing worked, the ??? asserts would also find
4. We might be able to understand another_one being 2, but to have all
occurrences of 1+1 in the program turn into 4 ... that would be bad.

Certain objects are called "value objects", and the idea is that like numbers,
they never change value. For many objects it is a design choice whether or not
to make them value objects, even if they are quite complex. For example, in the
articles I'm currently writing on extended set theory on my site, I'm moving in
the direction of making my sets value objects. They are essentially arbitrarily
large collections of records (like relational database relations), and most DB
apps think of relations as mutable. I'm going to make a different decision,
namely that any set, once created, is a constant. It'll be interesting to see
what happens.


--
Ron Jeffries
www.XProgramming.com
I'm giving the best advice I have. You get to decide if it's true for you.

Hal E. Fulton

1/2/2006 7:44:00 PM

0

Jonathan Leighton wrote:
> Thanks very much for this explanation, the restriction makes a lot more
> sense to me now.

You should also know that more complex objects (as you know) can
often change their state. In particular, Array and String both
implement a replace method, which totally replaces their contents.
But even then, the object id stays the same.


Hal



Henrik Martensson

1/5/2006 1:33:00 AM

0

Immutable classes are less prone to bugs than mutable classes. This is
because they have a single state. They are also thread safe.

It is good practise to favor immutability when there are no compelling
reasons for making a class mutable.

A Time object represents an instance in time. Making it mutable could
easily get confusing. Consider:

time = MutableTime.at(946702800)
rocket.launch_time = time
...
time.change(946701565) # Changes the launch time of the rocket


The launch time of the rocket can be changed without setting the
launch_time property explicitly. This is a potential source of bugs.

/Henrik


On Mon, 2006-01-02 at 02:11, Jonathan Leighton wrote:
> On Mon, 2006-01-02 at 09:47 +0900, Hal Fulton wrote:
> > James Britt wrote:
> > > Jonathan Leighton wrote:
> > >
> > >> Can't change the value of self (SyntaxError)
> > >> self = round_to *args
> > >>
> > >> Why doesn't it work? What can I do instead?
> > >
> > >
> > > "Destructive" methods must alter self using that self's existing
> > > destructive methods.
> >
> > To which we should add: Time has no destructive methods, since
> > Time objects are immutable.
> >
> > But someone once created a MutableTime class -- anyone recall
> > who/when/where and whether it's complete?
>
> Thanks for the replies. Why is Time immutable (presumably it's
> deliberately designed like that)? The MutableTime class sounds
> interesting but it's probably overkill for what I wanted to do -- I'll
> just modify variables at a higher level.
>
> Thanks



Hal E. Fulton

1/5/2006 3:29:00 AM

0

Henrik Martensson wrote:
> Immutable classes are less prone to bugs than mutable classes. This is
> because they have a single state. They are also thread safe.
>
> It is good practise to favor immutability when there are no compelling
> reasons for making a class mutable.
>
> A Time object represents an instance in time. Making it mutable could
> easily get confusing. Consider:
>
> time = MutableTime.at(946702800)
> rocket.launch_time = time
> ...
> time.change(946701565) # Changes the launch time of the rocket
>
>
> The launch time of the rocket can be changed without setting the
> launch_time property explicitly. This is a potential source of bugs.


Thanks, Henrik. That's a great discussion and a great example.


Hal




Gavin Kistner

1/5/2006 6:27:00 AM

0

On Jan 1, 2006, at 5:47 PM, Hal Fulton wrote:

> James Britt wrote:
>> Jonathan Leighton wrote:
>>> Can't change the value of self (SyntaxError)
>>> self = round_to *args
>>>
>>> Why doesn't it work? What can I do instead?
>> "Destructive" methods must alter self using that self's existing
>> destructive methods.
>
> To which we should add: Time has no destructive methods, since
> Time objects are immutable.
>
> But someone once created a MutableTime class -- anyone recall
> who/when/where and whether it's complete?

That'd be me, and it's documented at http://phrogz.net/Ruby...
classes/MutableTime.html and available for download at http://
phrogz.net/RubyLibs/MutableTime.rb

As to whether it's 'complete'...I dunno. I nominally labeled it
v1.0.5, but who knows what that means :)