(Static) Constructors/Destructors in Ruby

P

PrimaryKey

Hello!

After reading the Pickaxe book I noticed it provides almost no
information about object lifecycle and no mention of destructors. As a
Java/C# guy my gut reaction was: Wouldn’t it be nice to have a
“unintialize†method to be called when the object is being destroyed?

There seems to be some form of destructor (called finalizers) in the
ObjectSpace module, but it seems to be an afterthought rather that an
integral feature of the language.

Another thing I find very surprising for a language having such a rich
OO model is the lack of static constructors (available in C# and somehow
in Java) and static destructors (something I always wanted to have in
Java/C#).

Based on that I will appreciate your thoughts on why a language having
such advanced OO features is lacking in these areas and is there any way
to emulate these.

Thanks
 
M

Marcin Mielżyński

PrimaryKey said:
Hello!

After reading the Pickaxe book I noticed it provides almost no
information about object lifecycle and no mention of destructors. As a
Java/C# guy my gut reaction was: Wouldn’t it be nice to have a
“unintialize†method to be called when the object is being destroyed?

Java does not have destructors either. finalize method is not guaranteed
to be called

Another thing I find very surprising for a language having such a rich
OO model is the lack of static constructors (available in C# and somehow
in Java) and static destructors (something I always wanted to have in
Java/C#).

Ruby has them. Every class definition is an executable code (public,
private, protected are methods) so you can alternate method definitions
with arbitrary code (in fact, this is much more powerful mechanism than
static blocks in Java and static constructors in C#)

lopex
 
R

rmagick

PrimaryKey said:
Hello!

After reading the Pickaxe book I noticed it provides almost no
information about object lifecycle and no mention of destructors. As a
Java/C# guy my gut reaction was: Wouldn't it be nice to have a
"unintialize" method to be called when the object is being destroyed?

There seems to be some form of destructor (called finalizers) in the
ObjectSpace module, but it seems to be an afterthought rather that an
integral feature of the language.

Not so much an afterthought as discouraged.

Here's a good discussion about Ruby's finalizers:
http://www.rubygarden.org/ruby?RubyFromCpp
 
J

Jim Weirich

PrimaryKey said:
There seems to be some form of destructor (called finalizers) in the
ObjectSpace module, but it seems to be an afterthought rather that an
integral feature of the language.

Actually, it is a very well thought out feature of the language. In
Java, the finalizer is run when the object is eligible for garbage
collection. But within the finalizer, you can create a new reference to
the object and make it ineligible for collection.

In Ruby, the finalizer is not run until *after* the object is collected.
Since the object itself is no longer around, there is no possibility of
even accidently creating a new reference to the object. It also means
that the finalizer can't be an instance method (because the instance is
gone when the finalizer is run).
Another thing I find very surprising for a language having such a rich
OO model is the lack of static constructors (available in C# and somehow
in Java) and static destructors (something I always wanted to have in
Java/C#).

How would you use static constructors/destructors? Perhaps we can show
you Ruby equivalents.
 
P

PrimaryKey

How would you use static constructors/destructors? Perhaps we can show
you Ruby equivalents.

Please consider the following (pseudo) C# example:

public class AS400Server
{
static AS400 server;

static AS400Server()
{
server = new AS400Connection("SERVERNAME");
}

static ~AS400Server() // This is not real C#
{
server.disconnect();
}

static int GetServer()
{
return server;
}
}

I know this probably can be emulated using a singleton, I still believe
having static destructors will be nice because:

1. I like the constructor/destructor symmetry in C++
2. It can be helpful for meta-programming purposes. My impression is
most languages try to implement the traditional OO tools on class
(static) level

Thanks
 
L

Logan Capaldo

Please consider the following (pseudo) C# example:

public class AS400Server
{
static AS400 server;

static AS400Server()
{
server = new AS400Connection("SERVERNAME");
}

static ~AS400Server() // This is not real C#
{
server.disconnect();
}

static int GetServer()
{
return server;
}
}

I know this probably can be emulated using a singleton, I still
believe
having static destructors will be nice because:

1. I like the constructor/destructor symmetry in C++
2. It can be helpful for meta-programming purposes. My impression is
most languages try to implement the traditional OO tools on class
(static) level

Thanks

class AS400Server
@server = AS400Connection.new
def self.get_server
@server
end
end

As for a static deconstructor, can't really help you, I don't think
classes are really ever GCed until the very end, anyway. however, you
could do this:

class AS400Server
at_exit { @server.disconnect }
end
 
J

Justin Collins

--------------070100070406070206060806
Content-Type: text/plain; charset=ISO-8859-2; format=flowed
Content-Transfer-Encoding: quoted-printable

I believe this is the case if the garbage collector never runs. That is,=20
if the program exits before it is necessary.
Also, there are situations in which objects are never released, so the=20
finalize method won't be called then, either. If I recall correctly.

-Justin

Daniel said:
Does anyone know under what conditions the finalizer won't be called?




--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:
http://odeo.com/sendmeamessage/DanNugent
=20

--------------070100070406070206060806--
 
J

Joel VanderWerf

PrimaryKey said:
Please consider the following (pseudo) C# example:

public class AS400Server
{
static AS400 server;

static AS400Server()
{
server = new AS400Connection("SERVERNAME");
}

static ~AS400Server() // This is not real C#
{
server.disconnect();
}

static int GetServer()
{
return server;
}
}

I would ask first: does having one class per connection ("SERVERAME")
scale well? what if you need two servers...? This question isn't really
off topic, because once you accept this possibility, it becomes very
natural in ruby to do this:

class AS400Server
def initialize(serv_name)
@serv_name = serv_name
end

def connect
# do something to connect to the server
yield self
ensure
# do something to disconnet
end
end

Then in your main code you might have:

def run_my_app
AS400Server.new("SERVERNAME").connect do |serv|
# do something with serv
end
end

or

THE_SERVER = AS400Server.new("SERVERNAME")
def run_my_app
THE_SERVER.connect do
# do something with THE_SERVER
end
end

Unless you exit with Kernel#exit! or the process is killed in a way that
ruby cannot catch (e.g., SIGKILL), the ensure clause will close the
server connection first. (Anyway, in the case of SIGKILL, a static
destructor would not be called either, right? Or can C# do that?)

(You can even roll the #connect method into initialize, if you want.
Passing the server object from yeild isn't really necessary, but you may
need to reference it in the block.)
 
M

Marcin Mielżyński

Jim said:
In Ruby, the finalizer is not run until *after* the object is collected.
Since the object itself is no longer around, there is no possibility of
even accidently creating a new reference to the object. It also means
that the finalizer can't be an instance method (because the instance is
gone when the finalizer is run).


This makes perfect sense since Ruby uses mark&sweep. But in Python is it
possible to supply __del__ method which seems to be an instance one
(correct me if I'm wrong), but the moment of GC cannot be determined
anyways. And as rmagick mentioned, explicit destrutors are not needed
anyways.

lopex
 
J

Jim Weirich

PrimaryKey said:
Please consider the following (pseudo) C# example:

I think Logan Capaldo's answer is hits pretty close to your intention
here. However, I have to comment because I've been retrofitting unit
tests in to a legacy (Java) code base this past week and I've come to
*hate* static initializers.

The code base does something similar to your example and the code is
impossible to unit test without some restructuring. Since the database
connection is made in static initializers, I can't even load the class
without having the infrastructure for a database connection available.
Yuck!

I've come to consider complex static initializers (e.g. making DB
connections in the initilizer) a thing of "evil".

Ok, rant over. ;)
[...]
2. It can be helpful for meta-programming purposes. My impression is
most languages try to implement the traditional OO tools on class
(static) level

I'm not getting statement #2 above.

Thanks.
 
M

Minkoo Seo

Hi.
Based on that I will appreciate your thoughts on why a language having
such advanced OO features is lacking in these areas and is there any way
to emulate these.

Actually, destructor in Java, i.e., finalize( ), does not well behave.
Moreover, using it properly is next to impossible. Have a look at:
http://developers.sun.com/learning/javaoneonline/2005/coreplatform/TS-3281.html

Here's the recap:
(1) Java finalizer is not guranteed to run.
(2) Java finalizer is not executed in the main thread. Instead, it runs
in its own thread. Hence, synchronization mechanism for read/write
visibility and concurrency control is required.
(3) If java finalizer access a certain object which is already garbage
collected, then the object will resurrect. To avoid this situation, you
should not access garbage collected object while finalizing, but it is
not easy because there's no certain order in garbage collection.

Instead of relying on finalize, you'd better use dispose pattern like:

class Foo
def dispose
# release all non-managed resources
end
end

You can find similar interface, IDisposable, in C#. The reason is that
people developed C# already found that writing destructor for releasing
unmanaged resources is not simple than writing explicit dispose method.

Sincerely,
Minkoo Seo
 
B

Benjohn Barnes

Please consider the following (pseudo) C# example:

public class AS400Server
{
static AS400 server;

static AS400Server()
{
server = new AS400Connection("SERVERNAME");
}

static ~AS400Server() // This is not real C#
{
server.disconnect();
}

static int GetServer()
{
return server;
}
}

I know this probably can be emulated using a singleton,

The singleton design pattern certainly can do that, and is easily
used in Ruby by including module "Singleton" (except for the
destruction part - although I expect a finaliser could do that for
you, but I've not used them myself).

When you started to talk about these, I thought you were after
'structors for a class, rather than an instance. These are, of
course, very easy in Ruby, as a class is just an object like any
other. In fact, you can have little factories that will pump out
classes, if you want.

I still believe
having static destructors will be nice because:

1. I like the constructor/destructor symmetry in C++

Actually, I like the c++ destructors too. I'd say they are one of the
very few things that I miss about it :) I quite often made use of a
"stack object". It's an object with no interface except for it's
'structors. You would declare them "on the stack" in c++ (ie, without
using new), so they are local to a code block. They're really useful
for doing setup within a code block and ensuring that teardown
happens when you exit it. They seem like a DRY way to specify the use
of a mode within a code block:

class StackObject
{
public:
StackObject() {do_setup_code();}
~StackObject() {do_teardown_code();}

private:
void do_setup_code();
void do_teardown_code();
};

And to use...

{
// Setup resource.
StackObject stack_object;

// Do stuff with the mode being setup by the stack object.

// Tear down happens automatically at block exit.
}

However, a very similar idea is possible in Ruby, and can be achieved
with passing code blocks...

def run_within_mode
setup_code
yield
ensure
teardown_code
end

And to use:


# Here, the mode is not in use yet.
run_within_mode do
# Anything here is happening with the mode! Hooray!
end
# And the mode's gone again.

As well as ensuring the resource is cleaned up, both of these
approaches are exception safe too.

Cheers,
Ben
 
V

Victor Shepelev

{
// Setup resource.
StackObject stack_object;
// Do stuff with the mode being setup by the stack object.
// Tear down happens automatically at block exit.
}

However, a very similar idea is possible in Ruby, and can be achieved
with passing code blocks...

def run_within_mode
setup_code
yield
ensure
teardown_code
end

And to use:


# Here, the mode is not in use yet.
run_within_mode do
# Anything here is happening with the mode! Hooray!
end
# And the mode's gone again.

As well as ensuring the resource is cleaned up, both of these
approaches are exception safe too.

I like block idea, but must say that blocks can't give full replacement for
C++'s RAII ideom:

C++:

{
File f1,f2,f3;
Socket s1,s2;
Database d;
} //here all f1,f2,f3,s1,s2,d being closed

Ruby:

???
Cheers,
Ben

Victor.
 
B

Benjohn Barnes

I like block idea, but must say that blocks can't give full
replacement for
C++'s RAII ideom:

C++:

{
File f1,f2,f3;
Socket s1,s2;
Database d;
} //here all f1,f2,f3,s1,s2,d being closed

Ruby:

???

:) It's such a fresh beautiful day outside... and here I am talking
tech, when spring is springing :)

Ok, in Ruby, each of those resources could easily be turned in to a
method that will run a block. What you want to be able to do then, is
easily compose those methods in to one, and have that run something
within the context of resources being available?

Something along the lines of (unchecked code warning!)...?

def run_with_resources(*resources, &block)
if resources == []
yield
else
send(resources.slice(0)) {run_with_resources(*resources, &block)}
end
end

You can then do...

run_with_resources
:)file_handle, :db_connection, :socket_and_things, :eek:ther_groovy_bits) d
o
#Wooo - look at all these resources!
end

It wouldn't be a big extension to collect up the resources passed in,
and pop them in a map, or something. I don't think it would be hard
to give the resources arguments either.

Cheers,
Ben
 
B

Benjohn Barnes

--Apple-Mail-14-224241553
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed


:) It's such a fresh beautiful day outside... and here I am talking
tech, when spring is springing :)

It really is!
Ok, in Ruby, each of those resources could easily be turned in to a
method that will run a block. What you want to be able to do then,
is easily compose those methods in to one, and have that run
something within the context of resources being available?

Something along the lines of (unchecked code warning!)...?

def run_with_resources(*resources, &block)
if resources == []
yield
else
send(resources.slice(0)) {run_with_resources(*resources, &block)}

That was supposed to be:
send(resources.slice!(0)) {run_with_resources(*resources, &block)}

The ! after slice is vital!


--Apple-Mail-14-224241553--
 
V

Victor Shepelev

-----Original Message-----
From: Benjohn Barnes [mailto:[email protected]]
Sent: Saturday, April 01, 2006 1:25 PM
To: ruby-talk ML
Subject: Re: (Static) Constructors/Destructors in Ruby


I like block idea, but must say that blocks can't give full
replacement for
C++'s RAII ideom:

C++:

{
File f1,f2,f3;
Socket s1,s2;
Database d;
} //here all f1,f2,f3,s1,s2,d being closed

Ruby:

???

:) It's such a fresh beautiful day outside... and here I am talking
tech, when spring is springing :)

Hmmm... Not so beautiful/springy day in Kharkov, Ukraine :)
Ok, in Ruby, each of those resources could easily be turned in to a
method that will run a block. What you want to be able to do then, is
easily compose those methods in to one, and have that run something
within the context of resources being available?

Something along the lines of (unchecked code warning!)...?

def run_with_resources(*resources, &block)
if resources == []
yield
else
send(resources.slice(0)) {run_with_resources(*resources,
&block)}
end
end

You can then do...

run_with_resources
:)file_handle, :db_connection, :socket_and_things, :eek:ther_groovy_bits) d
o
#Wooo - look at all these resources!
end

It wouldn't be a big extension to collect up the resources passed in,
and pop them in a map, or something. I don't think it would be hard
to give the resources arguments either.

Yes, I know all those trick (I'm not a VERY newbie :) - my point was "blocks
not always good alternative for RAII".

BTW, I recalled I saw some library at RAA, which does the stuff. But I don't
remember it's name (because in real life it is not as necessary as in dumb
examples ;)
Cheers,
Ben

Victor.
 
B

Benjohn Barnes

Yes, I know all those trick (I'm not a VERY newbie :) - my point
was "blocks
not always good alternative for RAII".

:) I thought it was quite clever, I was feeling very pleased with
myself :)
BTW, I recalled I saw some library at RAA, which does the stuff.
But I don't
remember it's name (because in real life it is not as necessary as
in dumb
examples ;)

Well, that's the thing though, really :)
 
J

Joel VanderWerf

Victor said:
Hmmm... Not so beautiful/springy day in Kharkov, Ukraine :)

Nor in Northern California. It's so wet the sidewalks are turning green.

Here's an idea:

require 'socket'

class ResourceMgr
def [](*resources)
@resources = resources
end

def cleanup
@resources.reverse_each do |resource, cleanup_method|
resource.__send__ cleanup_method || :close
end
end
end

def with_resources
res = ResourceMgr.new
yield res
ensure
res.cleanup
end

rl_test = nil

with_resources do |res|
res[
f = File.open("/tmp/file", "w"),
s = UDPSocket.open,
[t = Thread.new {sleep}, :kill]
]

rl_test = [f,s,t]
p rl_test
# use resources here
end

p rl_test

__END__

Output:

[#<File:/tmp/file>, #<UDPSocket:0xb7dca598>, [#<Thread:0xb7dca4e4
sleep>, :kill]]
[#<File:/tmp/file (closed)>, #<UDPSocket:0xb7dca598>,
[#<Thread:0xb7dca4e4 dead>, :kill]]
 
P

Primary Key

Jim said:
I'm not getting statement #2 above.

Please consider the evolution of the class-level language features:

1. C++ - static member variables
2. Java - static members and static initialization blocks
3. C# - static members and static constructors

I think there is a clear pattern of implementing more and more of the
object-level OO features on class (static) level. I believe the next
logical step will be a language support for static destructors. As far
as meta-progamming is concerned the static features will beef up the
class level in the object-class-metaclass triad. Again, this is just the
personal opinion of a "evil" legacy(Java) programmer :)

Thanks again,
Primary Key
 
J

Jim Weirich

Primary said:
Please consider the evolution of the class-level language features:

1. C++ - static member variables
2. Java - static members and static initialization blocks
3. C# - static members and static constructors

I think there is a clear pattern of implementing more and more of the
object-level OO features on class (static) level.

Ok, at least for C-style languages I won't argue the point (although I'm
not entirely clear what a static constructor is ... other than a factory
function).
[...] As far
as meta-progamming is concerned the static features will beef up the
class level in the object-class-metaclass triad.

I'm still unclear on how static methods do anything to support
meta-progarmming. Perhaps an example might prove illuminating.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top