Infinite number of singleton_classes

Hello!

----8<----
a = Object.new

b = class << a
class << self
  class << self
   class << self
    # "class << self".times(n)
     self
    # "end".times(n)
   end
  end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

---8<---
a = Object.new

begin
b = class << a
  class << self
   self
  end
end
rescue NewError
puts "Sincerely, you don't need the singleton_class of the singleton_class!"
end
---8<---

What do you think of it? Isn't it worth an RCR?

···

--
Lionel Thiry

Personal website: http://users.skynet.be/lthiry/

Lionel Thiry schrieb:

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

I agree, it should not be possible to these classes ...

---8<---
a = Object.new

begin
b = class << a
class << self
  self
end
end
rescue NewError
puts "Sincerely, you don't need the singleton_class of the singleton_class!"
end
---8<---

What do you think of it? Isn't it worth an RCR?

Yes lets get rid of them, they are utterly useless and
a source of distraction (well at least they have been
in past for me:-)

/Christoph

i've found them useful in the following situation:

   harp:~ > cat a.rb
   class C
     class << self
       class << self
         def class_method_generator name
           module_eval <<-code
             def #{ name }; @#{ name }; end
             alias #{ name }? #{ name }
             def #{ name }= value; @#{ name } = value; end
           code
         end
       end
       %w( a b c ).each{|meth| class_method_generator meth}
     end
   end

   class B < C
   end

   C.a = 42
   p C.a

   B.a = 'forty-two'
   p B.a

   C.class_method_generator :x

   harp:~ > ruby a.rb
   42
   "forty-two"
   a.rb:25: undefined method `class_method_generator' for C:Class (NoMethodError)

granted, you could do this with a private class method of C - but this is what
singleton methods are for : defining a method on 'this' instance right here
and right now that only that instance should be able to do. in this case the
instance happens to be a singleton of a singleton.

in any case i don't think one can say when/if that construct would be useful a
priori and think that having that notion enforced by ruby itself ( __i__ know
when need a singleton class and __you__ don't ) is the kind of exception that
reminds of of a 'p' language. ruby programmers are continually pushing the
boundries of oo coding precisely because matz has given them the tools to do
so and it would be a shame to take a tool away just because someone hasn't
figured out something indespesible to do with that particular tool __yet__.

kind regards.

-a

···

On Sun, 15 May 2005, Lionel Thiry wrote:

Hello!

----8<----
a = Object.new

b = class << a
class << self
class << self
  class << self
   # "class << self".times(n)
    self
   # "end".times(n)
  end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

---8<---
a = Object.new

begin
b = class << a
class << self
  self
end
end
rescue NewError
puts "Sincerely, you don't need the singleton_class of the singleton_class!"
end
---8<---

What do you think of it? Isn't it worth an RCR?

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi

===============================================================================

Hi --

Hello!

----8<----
a = Object.new

b = class << a
class << self
class << self
  class << self
   # "class << self".times(n)
    self
   # "end".times(n)
  end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

[...]

What do you think of it? Isn't it worth an RCR?

No; it's just a consequence of the underlying design principles. Yes,
there are a few objects that can't have a singleton class (Fixnums and
Symbols are the ones I can think of). But Class objects can, and
singleton classes are Class objects. So you'd be asking for
special-case treatment for a subset of classes.

It would be a bit like saying: Surely no one will ever use a
singleton class as a hash key, so let's remove the #hash method from
it. There's just no reason to constrain the language and its usage
that way.

Also, I don't see any harm or danger here. I suppose one could
accidentally write a loop that kept creating singleton classes, but
one could also write a loop that kept creating *non*-singleton classes
-- or arrays, or hashes, or MyClass objects, and so on.

David

···

On Sun, 15 May 2005, Lionel Thiry wrote:

--
David A. Black
dblack@wobblini.net

Ara.T.Howard@noaa.gov a écrit :

···

On Sun, 15 May 2005, Lionel Thiry wrote:

Hello!

----8<----
a = Object.new

b = class << a
class << self
class << self
  class << self
   # "class << self".times(n)
    self
   # "end".times(n)
  end
end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I
really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a
singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

---8<---
a = Object.new

begin
b = class << a
class << self
  self
end
end
rescue NewError
puts "Sincerely, you don't need the singleton_class of the
singleton_class!"
end
---8<---

What do you think of it? Isn't it worth an RCR?

i've found them useful in the following situation:

  harp:~ > cat a.rb
  class C
    class << self
      class << self
        def class_method_generator name
          module_eval <<-code
            def #{ name }; @#{ name }; end
            alias #{ name }? #{ name }
            def #{ name }= value; @#{ name } = value; end
          code
        end
      end
      %w( a b c ).each{|meth| class_method_generator meth}
    end
  end

  class B < C
  end

  C.a = 42
  p C.a

  B.a = 'forty-two'
  p B.a

  C.class_method_generator :x

  harp:~ > ruby a.rb
  42
  "forty-two"
  a.rb:25: undefined method `class_method_generator' for C:Class
(NoMethodError)

granted, you could do this with a private class method of C - but this
is what
singleton methods are for : defining a method on 'this' instance right here
and right now that only that instance should be able to do. in this
case the
instance happens to be a singleton of a singleton.

in any case i don't think one can say when/if that construct would be
useful a
priori and think that having that notion enforced by ruby itself ( __i__
know
when need a singleton class and __you__ don't ) is the kind of exception
that
reminds of of a 'p' language. ruby programmers are continually pushing the
boundries of oo coding precisely because matz has given them the tools
to do
so and it would be a shame to take a tool away just because someone hasn't
figured out something indespesible to do with that particular tool __yet__.

kind regards.

-a

I just ask for opinions, you know... :frowning:

What did make you so angry? The fact that I've thought it could be worth an RCR?

--
Lionel Thiry

Personal website: http://users.skynet.be/lthiry/

David A. Black schrieb:

Also, I don't see any harm or danger here. I suppose one could
accidentally write a loop that kept creating singleton classes, but
one could also write a loop that kept creating *non*-singleton classes
-- or arrays, or hashes, or MyClass objects, and so on.

At least you can print any self referential (looping) object involving the
standard container classes, Hash, Arrays. Structs and Sets- however

···

---
class O
end

CrashChild = class << O; self end.dup

Crash = class << CrashChild
  superclass
end

Crash.inspect
---

results in a system stack overflow (for the "stock 1.8.2 windows
installer" ruby). This probably has to do with the fact that the
superclass of a normal "singleton singleton class" of a class, is
necessarily equal to

Klass = class << Class; self end # singleton class of class Class, e.g.
---
class O
end

nocrash = class << (class << O; self end)
  superclass
end

Klass = class << Class; self end

p (nocrash == Klass) # true
---

The core problem is (I assume because of efficiency reasons), that Matz
took "a little short cut" of not creating the natural chain of "higher order"
singleton classes, and cheated by declaring the superclass of any
"higher order" singleton class to be Klass.

Instead of going to the trouble of implementing an ad hoc "higher order
singleton class scheme" (b.t.w. - Ruby had a completely different higher
order singleton class scheme in past) it might have been wiser,
well at least less work, of preventing the creation of "higher order"
singleton classes in the first place.

/Christoph

David A. Black a écrit :

Hi --

Hello!

----8<----
a = Object.new

b = class << a
class << self
class << self
  class << self
   # "class << self".times(n)
    self
   # "end".times(n)
  end
end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I
really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a
singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

[...]

What do you think of it? Isn't it worth an RCR?

No; it's just a consequence of the underlying design principles. Yes,
there are a few objects that can't have a singleton class (Fixnums and
Symbols are the ones I can think of). But Class objects can, and
singleton classes are Class objects. So you'd be asking for
special-case treatment for a subset of classes.

It would be a bit like saying: Surely no one will ever use a
singleton class as a hash key, so let's remove the #hash method from
it. There's just no reason to constrain the language and its usage
that way.

Also, I don't see any harm or danger here. I suppose one could
accidentally write a loop that kept creating singleton classes, but
one could also write a loop that kept creating *non*-singleton classes
-- or arrays, or hashes, or MyClass objects, and so on.

Well, I had something in mind when I wrote this... and it was not "Surely no one
will ever use this feature, then let's remove it". It was something more subtle.

I may be wrong in my interpretation, but I remember that Matz expected some
freedom of implementation of singleton method mechanism. Present mechanism is
that singleton methods are hold in a singleton class, which happens to be an
object instance of the class Class. But this may change in future version of
ruby. For example, singleton "classes" could not be a class anymore, or it could
even not be a normal object anymore. It could be anything, whatever please Matz.

Then, giving that fact as true, for the sake of future ruby versions, wouldn't
it be more consistent to forbid singleton class of singleton class?

I may admit that the such said "sake of future ruby versions" may need some
other marginal never truly used features be forbidden either. I don't know, I'm
not sure of anything.

And, please note this: I agree with you. There is nothing wrong or harmfull in
the current behavior, while looking from the point of view of a ruby user. But I
think it may be different from the point of view of a language designer and I
like to take count of it.

···

On Sun, 15 May 2005, Lionel Thiry wrote:

--
Lionel Thiry

Personal website: http://users.skynet.be/lthiry/

Lionel Thiry wrote:

I just ask for opinions, you know... :frowning:

What did make you so angry? The fact that I've thought it could be worth an RCR?

You have misunderstood somewhere. Ara was not angry.

His "__i__" and "__you__" were quotes -- the Ruby interpreter
talking to the programmer.

Hal

Hi --

The core problem is (I assume because of efficiency reasons), that Matz
took "a little short cut" of not creating the natural chain of "higher order"
singleton classes, and cheated by declaring the superclass of any
"higher order" singleton class to be Klass.

Instead of going to the trouble of implementing an ad hoc "higher order
singleton class scheme" (b.t.w. - Ruby had a completely different higher
order singleton class scheme in past) it might have been wiser,
well at least less work, of preventing the creation of "higher order"
singleton classes in the first place.

I'd rather just see the #inspect bug fixed :slight_smile:

I don't think having (class << Class; self; end) be the superclass of
these singletons is a problem. At least, if one had a reason to want
to go higher than one level (for example, adding a class method to a
singleton class -- has anyone done that?), it wouldn't really matter
what the class's superclass was.

David

···

On Mon, 16 May 2005, Christoph wrote:

--
David A. Black
dblack@wobblini.net

Hi --

Well, I had something in mind when I wrote this... and it was not "Surely no one
will ever use this feature, then let's remove it". It was something more subtle.

I may be wrong in my interpretation, but I remember that Matz expected some
freedom of implementation of singleton method mechanism. Present mechanism is
that singleton methods are hold in a singleton class, which happens to be an
object instance of the class Class. But this may change in future version of
ruby. For example, singleton "classes" could not be a class anymore, or it could
even not be a normal object anymore. It could be anything, whatever please Matz.

Then, giving that fact as true, for the sake of future ruby versions, wouldn't
it be more consistent to forbid singleton class of singleton class?

It would only be consistent to forbid them if singleton classes
themselves cease to exist (in some future Ruby implementation). As
long as objects have singleton classes, and as long as those classes
are objects, it's consistent for them, too, to have singleton classes.

The closest thing to a possible use I can think of is class methods
(including accessors) on a singleton class -- like this:

   obj = Object.new
   c = class << obj; self; end
   c.class_eval { class << self; attr_accessor :x; end }
   c.x = 123

etc. But it's probably a bit of a stretch. Still, I don't feel that
there's any reason for c (in that example) not to be allowed to create
class methods (i.e., singleton methods for itself).

David

···

On Mon, 16 May 2005, Lionel Thiry wrote:

--
David A. Black
dblack@wobblini.net

this makes a good bit more sense to me - but think matz would need to comment
to consider further.

kind regards.

-a

···

On Mon, 16 May 2005, Lionel Thiry wrote:

Well, I had something in mind when I wrote this... and it was not "Surely no
one will ever use this feature, then let's remove it". It was something more
subtle.

I may be wrong in my interpretation, but I remember that Matz expected some
freedom of implementation of singleton method mechanism. Present mechanism
is that singleton methods are hold in a singleton class, which happens to be
an object instance of the class Class. But this may change in future version
of ruby. For example, singleton "classes" could not be a class anymore, or
it could even not be a normal object anymore. It could be anything, whatever
please Matz.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi

===============================================================================

Hal Fulton a écrit :

Lionel Thiry wrote:

I just ask for opinions, you know... :frowning:

What did make you so angry? The fact that I've thought it could be
worth an RCR?

You have misunderstood somewhere. Ara was not angry.

His "__i__" and "__you__" were quotes -- the Ruby interpreter
talking to the programmer.

In that quote, Ara *was* angry, not with me, but about the 'p' language.

But here:
----8<---
it would be a shame to take a tool away just because someone hasn't figured out
something indespesible to do with that particular tool __yet__
---8<---

Have I misunderstood something once again?

···

--
Lionel Thiry

Personal website: http://users.skynet.be/lthiry/

David A. Black schrieb:

I'd rather just see the #inspect bug fixed :slight_smile:

I don't think having (class << Class; self; end) be the superclass of
these singletons is a problem. At least, if one had a reason to want
to go higher than one level (for example, adding a class method to a
singleton class -- has anyone done that?), it wouldn't really matter
what the class's superclass was.

If you are "singleton class" you only have to do house keeping for a one
instance only. There is a potential benefit of inheriting house keeping methods
but this is broken if Klass is the superclass of all "higher order" singleton
classes. If inheritance does not work any more "higher order" singleton classes
are pretty much fake "higher order" singleton classes.

···

---
  # From Ara example
  class C
    class << self
      class << self
        def class_method_generator name
          module_eval <<-code
            def #{ name }; @#{ name }; end
            alias #{ name }? #{ name }
            def #{ name }= value; @#{ name } = value; end
          code
        end
      end
      %w( a b c ).each{|meth| class_method_generator meth}
    end
  end

  class B < C
  end

  C.a = 42
  p C.a

  B.a = 'forty-two'
  p B.a
       class << B
        class << self
            class_method_generator :wont_work_in_182
        end
    end
----

/Christoph

David A. Black a écrit :

Hi --

Well, I had something in mind when I wrote this... and it was not
"Surely no one
will ever use this feature, then let's remove it". It was something
more subtle.

I may be wrong in my interpretation, but I remember that Matz expected
some
freedom of implementation of singleton method mechanism. Present
mechanism is
that singleton methods are hold in a singleton class, which happens to
be an
object instance of the class Class. But this may change in future
version of
ruby. For example, singleton "classes" could not be a class anymore,
or it could
even not be a normal object anymore. It could be anything, whatever
please Matz.

Then, giving that fact as true, for the sake of future ruby versions,
wouldn't
it be more consistent to forbid singleton class of singleton class?

It would only be consistent to forbid them if singleton classes
themselves cease to exist (in some future Ruby implementation). As
long as objects have singleton classes, and as long as those classes
are objects, it's consistent for them, too, to have singleton classes.

You have skipped this part of my post in your answer:
----8<----
And, please note this: I agree with you. There is nothing wrong or harmfull in
the current behavior, while looking from the point of view of a ruby user. But I
think it may be different from the point of view of a language designer and I
like to take count of it.
----8<----

The feature is currently avaible, but unless Matz state otherwise, it is an
accident, it shouldn't have never happened. Why? Because it may disapear in any
future version of ruby. Who said it? Matz himself. It then should be accessible
only via special module like evil.rb if one really want the feature.

On the other hand, if it was said that ruby won't never change about singleton
methods hold in singleton classes, I wouldn't care at all about this.

···

On Mon, 16 May 2005, Lionel Thiry wrote:

--
Lionel Thiry

Personal website: http://users.skynet.be/lthiry/

hal is quite right! sorry if the original came out wrong - it's what i get
for posting before coffee i the morning!

cheers.

-a

···

On Mon, 16 May 2005, Hal Fulton wrote:

Lionel Thiry wrote:

I just ask for opinions, you know... :frowning:

What did make you so angry? The fact that I've thought it could be worth an RCR?

You have misunderstood somewhere. Ara was not angry.

His "__i__" and "__you__" were quotes -- the Ruby interpreter
talking to the programmer.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi

===============================================================================

Hi,

David A. Black wrote:

I'd rather just see the #inspect bug fixed :slight_smile:

I rather guess singleton class would not be allowed to copy, from its
definition.

Index: class.c

···

===================================================================
RCS file: /cvs/ruby/src/ruby/class.c,v
retrieving revision 1.89
diff -U2 -p -r1.89 class.c
--- class.c 4 Mar 2005 06:47:45 -0000 1.89
+++ class.c 16 May 2005 05:35:05 -0000
@@ -106,4 +106,7 @@ rb_class_init_copy(clone, orig)
   rb_raise(rb_eTypeError, "already initialized class");
     }
+ if (FL_TEST(orig, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "can't copy singleton class");
+ }
     return rb_mod_init_copy(clone, orig);
}

--
Nobu Nakada

Ara.T.Howard@noaa.gov a écrit :

···

On Mon, 16 May 2005, Lionel Thiry wrote:

Well, I had something in mind when I wrote this... and it was not
"Surely no
one will ever use this feature, then let's remove it". It was
something more
subtle.

I may be wrong in my interpretation, but I remember that Matz expected
some
freedom of implementation of singleton method mechanism. Present
mechanism
is that singleton methods are hold in a singleton class, which happens
to be
an object instance of the class Class. But this may change in future
version
of ruby. For example, singleton "classes" could not be a class
anymore, or
it could even not be a normal object anymore. It could be anything,
whatever
please Matz.

this makes a good bit more sense to me - but think matz would need to
comment
to consider further.

When I wrote my initial post, I suppose I took for granted that this was
evident, given the so many discussions about singleton class. And I also took
for granted that if one couldn't grasp my position in the first place, he would
be nice enough to ask me to elaborate. :wink:

Cheers.

--
Lionel Thiry

Personal website: http://users.skynet.be/lthiry/

Hi --

David A. Black schrieb:

I'd rather just see the #inspect bug fixed :slight_smile:

I don't think having (class << Class; self; end) be the superclass of
these singletons is a problem. At least, if one had a reason to want
to go higher than one level (for example, adding a class method to a
singleton class -- has anyone done that?), it wouldn't really matter
what the class's superclass was.

If you are "singleton class" you only have to do house keeping for a one
instance only. There is a potential benefit of inheriting house keeping methods
but this is broken if Klass is the superclass of all "higher order" singleton
classes. If inheritance does not work any more "higher order" singleton classes
are pretty much fake "higher order" singleton classes.

Here's another interesting variant:

   Klass = class << Class; self; end
   def Klass.m; puts "here"; end

   class C; end
   class << C
     class << self
       p superclass == Klass # true
       Klass.m # "here"
       m # NoMethodError
     end
   end

i.e, having Klass as your superclass does not give you access to
Klass's class methods. I'm not sure whether I think this makes it
more consistent (explained in a moment) or whether it makes the whole
thing, as you say, kind of fake.

By "more consistent", I mean:

Having a subclass able to call its superclass's singleton (class)
methods is, as far as I know, the only case where one object can call
another's singleton methods. This arrangement seems to disappear in
the case of singleton classes of singleton classes... but at least it
disappears consistently (i.e., even in the case of "Klass" above).

Or something. In practical terms there's probably not much mileage to
be had out of these.

David

···

On Mon, 16 May 2005, Christoph wrote:

--
David A. Black
dblack@wobblini.net

You have skipped this part of my post in your answer:
----8<----
And, please note this: I agree with you. There is nothing wrong or harmfull in
the current behavior, while looking from the point of view of a ruby user. But I
think it may be different from the point of view of a language designer and I
like to take count of it.
----8<----

I didn't have anything to add to it, so I didn't quote it back.
Otherwise we get into infinite recursion :slight_smile:

The feature is currently avaible, but unless Matz state otherwise, it is an
accident, it shouldn't have never happened. Why? Because it may disapear in any
future version of ruby. Who said it? Matz himself. It then should be accessible
only via special module like evil.rb if one really want the feature.

If it disappears, it can't be accessible from any module, at least not
in exactly that form.

On the other hand, if it was said that ruby won't never change about singleton
methods hold in singleton classes, I wouldn't care at all about this.

There's a bit of a paradox there. If Ruby shouldn't contain anything
that might be absent in a future Ruby, then Ruby today must be exactly
what Ruby in the future will be.... If singleton classes disappear,
lots of things will change, possibly including:

    class << obj # this form of the class keyword
      X = 1 # constants -- where would this go?
      def self.x # class methods on the singleton class
      end
    end

as well as just the fact that you can call Class's instance methods,
in general, on singleton classes.

So if you apply the rule: it should never have happened because it
may disappear in a future version of Ruby, then all of this should
never have happened and should disappear. But so should lots of other
things, because Matz is planning lots of changes. So that means Ruby
should be turned into future Ruby *now*. But that takes time :slight_smile:

David

···

On Mon, 16 May 2005, Lionel Thiry wrote:

--
David A. Black
dblack@wobblini.net

well - sorta :wink:

i only meant to say that the behaviour is consistent and, although there is no
regular ruby idiom that makes use of it now, there may well be in the future.
if it were inconsistent, but could have a potential use, i'd say take 'em
   away. my worry is that taking them away now would, in fact, be inconsistent
   and that's what reminded me of perl - which is ripe with inconsistencies -
   am i making more sense?

cheers.

-a

···

On Mon, 16 May 2005, Lionel Thiry wrote:

Hal Fulton a écrit :

Lionel Thiry wrote:

I just ask for opinions, you know... :frowning:

What did make you so angry? The fact that I've thought it could be
worth an RCR?

You have misunderstood somewhere. Ara was not angry.

His "__i__" and "__you__" were quotes -- the Ruby interpreter
talking to the programmer.

In that quote, Ara *was* angry, not with me, but about the 'p' language.

But here:
----8<---
it would be a shame to take a tool away just because someone hasn't figured out
something indespesible to do with that particular tool __yet__
---8<---

Have I misunderstood something once again?

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi

===============================================================================