Class#=== has interesting results

Discussion in 'Ruby' started by Charles Comstock, Jul 7, 2004.

  1. Why does this happen?

    class A
    end

    A == A #1 => true
    A === A #2 => false

    a = A.new

    a === A #3 => false
    a == A #4 => false
    A === a #5 => true
    A == a #6 => false

    1 makes sense, A is an A so therefor it should be true
    3 and 4 make sense since instance of A is not A and does not match A
    5 and 6 make sense in that A matches a, but A is not an a.

    But 2 doesn't make any sense to me, why doesn't an A match another A?
    Is this just something that slipped through or is there a specific
    reason for this?

    Charles Comstock
    Charles Comstock, Jul 7, 2004
    #1
    1. Advertising

  2. --- Charles Comstock <> wrote:
    > Why does this happen?
    >
    > class A
    > end
    >
    > A == A #1 => true
    > A === A #2 => false
    >
    > a = A.new
    >
    > a === A #3 => false
    > a == A #4 => false
    > A === a #5 => true
    > A == a #6 => false
    >
    > 1 makes sense, A is an A so therefor it should be true
    > 3 and 4 make sense since instance of A is not A and does not match A
    > 5 and 6 make sense in that A matches a, but A is not an a.
    >
    > But 2 doesn't make any sense to me, why doesn't an A match another A?
    > Is this just something that slipped through or is there a specific
    > reason for this?


    whatisit = case obj
    when Array
    "it's an array!"
    when Hash
    "it's a hash!"
    when Septuagenarian
    "it's a septuagenarian!"
    end

    $ ri Module#===
    ------------------------------------------------------------- Module#===
    mod === obj => true or false
    ------------------------------------------------------------------------
    Case Equality---Returns +true+ if _anObject_ is an instance of
    _mod_ or one of _mod_'s descendents. Of limited use for modules,
    but can be used in +case+ statements to classify objects by class.




    __________________________________
    Do you Yahoo!?
    Yahoo! Mail - Helps protect you from nasty viruses.
    http://promotions.yahoo.com/new_mail
    Jeff Mitchell, Jul 7, 2004
    #2
    1. Advertising

  3. >
    > whatisit = case obj
    > when Array
    > "it's an array!"
    > when Hash
    > "it's a hash!"
    > when Septuagenarian
    > "it's a septuagenarian!"
    > end
    >
    > $ ri Module#===
    > ------------------------------------------------------------- Module#===
    > mod === obj => true or false
    > ------------------------------------------------------------------------
    > Case Equality---Returns +true+ if _anObject_ is an instance of
    > _mod_ or one of _mod_'s descendents. Of limited use for modules,
    > but can be used in +case+ statements to classify objects by class.
    >


    Right I was trying to use it in an example almost exactly like that
    except that obj was a name of a commandclass.

    Ie:
    def parse(str)
    input = str.chomp.split
    comm = CommandFactory[input[0]]

    case comm
    when StartCommand
    comm.new(input[1],input[2..-1])
    @mobile = input[1]
    when HelpCommand
    else
    comm.new(@mobile,input[1..-1])
    end
    end

    The idea was for a command factory to return the name of the command,
    and instantiate that command with the rest of the string as parameters,
    except for a few special case examples which would be checked against in
    a case statement. Since StartCommand === StartCommand returns false
    this doesn't work. Why you would want == to return true and === to
    return false in this case is beyond me. I knew about the example you
    gave above, that was what I was trying to emulate except at a step before.

    Charles Comstock
    Charles Comstock, Jul 7, 2004
    #3
  4. On Wed, Jul 07, 2004 at 04:22:36PM +0900, Charles Comstock wrote:
    > Why does this happen?
    >
    > class A
    > end
    >
    > A == A #1 => true
    > A === A #2 => false
    >
    > But 2 doesn't make any sense to me, why doesn't an A match another A?
    > Is this just something that slipped through or is there a specific
    > reason for this?


    A is not an instance of A; see the ri info for Module#===.

    --
    Running Debian GNU/Linux Sid (unstable)
    batsman dot geo at yahoo dot com

    - long f_ffree; /* free file nodes in fs */
    + long f_ffree; /* freie Dateiknoten im Dateisystem */
    -- Seen in a translation
    Mauricio Fernández, Jul 7, 2004
    #4
  5. --- Charles Comstock <> wrote:
    > >
    > > whatisit = case obj
    > > when Array
    > > "it's an array!"
    > > when Hash
    > > "it's a hash!"
    > > when Septuagenarian
    > > "it's a septuagenarian!"
    > > end
    > >
    > > $ ri Module#===
    > > ------------------------------------------------------------- Module#===
    > > mod === obj => true or false
    > > ------------------------------------------------------------------------
    > > Case Equality---Returns +true+ if _anObject_ is an instance of
    > > _mod_ or one of _mod_'s descendents. Of limited use for modules,
    > > but can be used in +case+ statements to classify objects by class.
    > >

    >
    > Right I was trying to use it in an example almost exactly like that
    > except that obj was a name of a commandclass.
    >
    > Ie:
    > def parse(str)
    > input = str.chomp.split
    > comm = CommandFactory[input[0]]
    >
    > case comm
    > when StartCommand
    > comm.new(input[1],input[2..-1])
    > @mobile = input[1]
    > when HelpCommand
    > else
    > comm.new(@mobile,input[1..-1])
    > end
    > end
    >
    > The idea was for a command factory to return the name of the command,
    > and instantiate that command with the rest of the string as parameters,
    > except for a few special case examples which would be checked against in
    > a case statement. Since StartCommand === StartCommand returns false
    > this doesn't work. Why you would want == to return true and === to
    > return false in this case is beyond me. I knew about the example you
    > gave above, that was what I was trying to emulate except at a step before.


    I'm not sure what you mean. StartCommand is not and instance of
    StartCommand or one of its decendants, therefore

    StartCommand === StartCommand

    returns false. Did you want the case statement behave differently
    different when given a class?

    Does this help:

    case comm.to_s.intern
    when :StartCommand
    comm.new(input[1],input[2..-1])
    @mobile = input[1]
    when :HelpCommand
    else
    comm.new(@mobile,input[1..-1])
    end





    __________________________________
    Do you Yahoo!?
    New and Improved Yahoo! Mail - 100MB free storage!
    http://promotions.yahoo.com/new_mail
    Jeff Mitchell, Jul 7, 2004
    #5
  6. Charles Comstock

    Guest

    Hi,

    At Wed, 7 Jul 2004 17:17:36 +0900,
    Charles Comstock wrote in [ruby-talk:105460]:
    > Ie:
    > def parse(str)
    > input = str.chomp.split
    > comm = CommandFactory[input[0]]
    >

    case
    when comm == StartCommand
    > comm.new(input[1],input[2..-1])
    > @mobile = input[1]

    when comm == HelpCommand
    > else
    > comm.new(@mobile,input[1..-1])
    > end
    > end


    You just stand on a wrong assumption, case/when/=== don't work
    as you imagine.

    --
    Nobu Nakada
    , Jul 7, 2004
    #6
  7. Mauricio Fernández wrote:

    > On Wed, Jul 07, 2004 at 04:22:36PM +0900, Charles Comstock wrote:
    >
    >>Why does this happen?
    >>
    >>class A
    >>end
    >>
    >>A == A #1 => true
    >>A === A #2 => false
    >>
    >>But 2 doesn't make any sense to me, why doesn't an A match another A?
    >>Is this just something that slipped through or is there a specific
    >>reason for this?

    >
    >
    > A is not an instance of A; see the ri info for Module#===.
    >


    At what point does it cause trouble for it to also return true if the
    class matches? Can someone give me an example of why it must match an
    instance and couldn't match the exact class? I understand it's only
    matching instances of the class, I just don't follow the logic behind
    why this is the default. Is there example code that uses this assumption?

    Charles Comstock
    Charles Comstock, Jul 7, 2004
    #7
  8. On Thu, 8 Jul 2004 02:32:36 +0900, Charles Comstock <> wrote:
    > At what point does it cause trouble for it to also return true if the
    > class matches? Can someone give me an example of why it must match an
    > instance and couldn't match the exact class? I understand it's only
    > matching instances of the class, I just don't follow the logic behind
    > why this is the default. Is there example code that uses this assumption?


    Class === Array

    -austin
    --
    Austin Ziegler *
    * Alternate:
    Austin Ziegler, Jul 7, 2004
    #8
  9. Hi --

    On Thu, 8 Jul 2004, Charles Comstock wrote:

    > Mauricio Fernández wrote:
    >
    > > On Wed, Jul 07, 2004 at 04:22:36PM +0900, Charles Comstock wrote:
    > >
    > >>Why does this happen?
    > >>
    > >>class A
    > >>end
    > >>
    > >>A == A #1 => true
    > >>A === A #2 => false
    > >>
    > >>But 2 doesn't make any sense to me, why doesn't an A match another A?
    > >>Is this just something that slipped through or is there a specific
    > >>reason for this?

    > >
    > >
    > > A is not an instance of A; see the ri info for Module#===.
    > >

    >
    > At what point does it cause trouble for it to also return true if the
    > class matches?


    At the point where you call it :) It can't do both; there would be no
    way to interpret the result:

    case s
    when String ... # what do you do here? print it? instantiate it?


    David

    --
    David A. Black
    David A. Black, Jul 7, 2004
    #9
  10. On Thu, 8 Jul 2004, Austin Ziegler wrote:

    > On Thu, 8 Jul 2004 02:32:36 +0900, Charles Comstock <> wrote:
    > > At what point does it cause trouble for it to also return true if the
    > > class matches? Can someone give me an example of why it must match an
    > > instance and couldn't match the exact class? I understand it's only
    > > matching instances of the class, I just don't follow the logic behind
    > > why this is the default. Is there example code that uses this assumption?

    >
    > Class === Array


    Which works because array is a descendent of class. I understand that. I'm
    getting the impression that people aren't following why this doesn't make sense
    to me so perhaps I can clarify:

    ------------------------------------------------------------- Module#===
    mod === obj => true or false
    ------------------------------------------------------------------------
    Case Equality---Returns +true+ if _anObject_ is an instance of
    _mod_ or one of _mod_'s descendents. Of limited use for modules,
    but can be used in +case+ statements to classify objects by class.


    Why is that this is defined like that and not like this:

    Case Equality --- Returns true if anObject is an instance of mod, one of mod's
    descendents or _is mod_.

    I understand what it matches, that is not the purpose of my line of questions, I
    am asking why it doesn't also match itself, and for what reason you would want
    to match descendents of x but not x itself. Does anyone have a logical reason
    why this is the case?

    Charles Comstock
    Charles Comstock, Jul 7, 2004
    #10
  11. On Thu, 8 Jul 2004, David A. Black wrote:

    > Hi --
    >
    > On Thu, 8 Jul 2004, Charles Comstock wrote:
    >
    > > Mauricio Fernández wrote:
    > >
    > > > On Wed, Jul 07, 2004 at 04:22:36PM +0900, Charles Comstock wrote:
    > > >
    > > >>Why does this happen?
    > > >>
    > > >>class A
    > > >>end
    > > >>
    > > >>A == A #1 => true
    > > >>A === A #2 => false
    > > >>
    > > >>But 2 doesn't make any sense to me, why doesn't an A match another A?
    > > >>Is this just something that slipped through or is there a specific
    > > >>reason for this?
    > > >
    > > >
    > > > A is not an instance of A; see the ri info for Module#===.
    > > >

    > >
    > > At what point does it cause trouble for it to also return true if the
    > > class matches?

    >
    > At the point where you call it :) It can't do both; there would be no
    > way to interpret the result:
    >
    > case s
    > when String ... # what do you do here? print it? instantiate it?
    >


    Sorry perhaps I didn't word my question well. I meant when does it cause a
    problem for a class x to match itself? What code fails if A === A results in
    true? Why would you ever want to match the descendents and instances of A but
    not match A itself.

    Charles Comstock
    Charles Comstock, Jul 7, 2004
    #11
  12. Hi --

    On Thu, 8 Jul 2004, Charles Comstock wrote:

    > On Thu, 8 Jul 2004, David A. Black wrote:
    >
    > > Hi --
    > >
    > > On Thu, 8 Jul 2004, Charles Comstock wrote:
    > >
    > > > Mauricio Fernández wrote:
    > > >
    > > > > On Wed, Jul 07, 2004 at 04:22:36PM +0900, Charles Comstock wrote:
    > > > >
    > > > >>Why does this happen?
    > > > >>
    > > > >>class A
    > > > >>end
    > > > >>
    > > > >>A == A #1 => true
    > > > >>A === A #2 => false
    > > > >>
    > > > >>But 2 doesn't make any sense to me, why doesn't an A match another A?
    > > > >>Is this just something that slipped through or is there a specific
    > > > >>reason for this?
    > > > >
    > > > >
    > > > > A is not an instance of A; see the ri info for Module#===.
    > > > >
    > > >
    > > > At what point does it cause trouble for it to also return true if the
    > > > class matches?

    > >
    > > At the point where you call it :) It can't do both; there would be no
    > > way to interpret the result:
    > >
    > > case s
    > > when String ... # what do you do here? print it? instantiate it?
    > >

    >
    > Sorry perhaps I didn't word my question well. I meant when does it cause a
    > problem for a class x to match itself? What code fails if A === A results in
    > true? Why would you ever want to match the descendents and instances of A but
    > not match A itself.


    It doesn't match the descendants of A, but rather instances of the
    descendants of A:

    irb(main):001:0> class A; end; class B < A; end
    => nil
    irb(main):002:0> case A
    irb(main):003:1> when B: puts "yes" end
    => nil
    irb(main):004:0> case B
    irb(main):005:1> when A: puts "yes" end
    => nil
    irb(main):006:0> case B.new
    irb(main):007:1> when A: puts "yes" end
    yes

    It's really the same test as #is_a? The docs should probably add
    an "of":

    Returns true if anObject is an instance of mod or of
    one of mod's descendents.


    David

    --
    David A. Black
    David A. Black, Jul 7, 2004
    #12
  13. --- "David A. Black" <> wrote:
    > On Thu, 8 Jul 2004, Charles Comstock wrote:
    > > Sorry perhaps I didn't word my question well. I meant when does it cause a
    > > problem for a class x to match itself? What code fails if A === A results in
    > > true? Why would you ever want to match the descendents and instances of A but
    > > not match A itself.

    >
    > It doesn't match the descendants of A, but rather instances of the
    > descendants of A:
    > [...]


    He is asking why isn't === defined as

    class Module
    def ===(obj)
    obj.is_a?(self) or obj == self
    end
    end

    or maybe

    class Module
    def ===(obj)
    obj.is_a?(self) or obj.ancestors.include?(self)
    end
    end

    Not that I advocate either definition.


    __________________________________________________
    Do You Yahoo!?
    Tired of spam? Yahoo! Mail has the best spam protection around
    http://mail.yahoo.com
    Jeff Mitchell, Jul 7, 2004
    #13
  14. --- Jeff Mitchell <> wrote:
    > or maybe
    >
    > class Module
    > def ===(obj)
    > obj.is_a?(self) or obj.ancestors.include?(self)
    > end
    > end


    Er, scratch this definition. obj.is_a?(self) is the same thing
    as obj.ancestors.include?(self) AFAIK.




    __________________________________
    Do you Yahoo!?
    Yahoo! Mail - 50x more storage than other providers!
    http://promotions.yahoo.com/new_mail
    Jeff Mitchell, Jul 7, 2004
    #14
  15. Hi --

    On Thu, 8 Jul 2004, Jeff Mitchell wrote:

    > --- "David A. Black" <> wrote:
    > > On Thu, 8 Jul 2004, Charles Comstock wrote:
    > > > Sorry perhaps I didn't word my question well. I meant when does it cause a
    > > > problem for a class x to match itself? What code fails if A === A results in
    > > > true? Why would you ever want to match the descendents and instances of A but
    > > > not match A itself.

    > >
    > > It doesn't match the descendants of A, but rather instances of the
    > > descendants of A:
    > > [...]

    >
    > He is asking why isn't === defined as


    Right, but the question becomes less relevant given that the method
    doesn't actually match the descendants of A -- so the answer is: you
    wouldn't, and it doesn't :)

    > class Module
    > def ===(obj)
    > obj.is_a?(self) or obj == self
    > end
    > end
    >
    > or maybe
    >
    > class Module
    > def ===(obj)
    > obj.is_a?(self) or obj.ancestors.include?(self)
    > end
    > end


    I think you mean obj.class.ancestors, in which case is_a? should take
    care of it -- which means that your second definition is actually how
    the method works, I believe.

    As for the first, and Charles's question about why it doesn't work
    that way: look again at my earlier example:

    case s
    when String ...

    With the "is_a? or ==" implementation, this 'when' clause could mean
    either that s is String (the Class object) or that s is "Hi, how are
    you?" (a String object). Knowing that something is either String or a
    string, but not knowing which, isn't very valuable; it's hard to imagine
    a case where you would act on that kind of information.


    David

    --
    David A. Black
    David A. Black, Jul 7, 2004
    #15
  16. Charles Comstock

    Aredridel Guest

    > Why is that this is defined like that and not like this:
    >
    > Case Equality --- Returns true if anObject is an instance of mod, one of mod's
    > descendents or _is mod_.


    Because then it would match some instances of class Class, instances of
    mod and instances of descendants of mod. That's three separate things,
    two closely related and a third that's not.

    It doesn't match descendants of mod -- it matches instances of
    descendants of mod.

    I can't think of any use-case where matching instances of Class in
    addition to instances of Mod would be useful.

    > I understand what it matches, that is not the purpose of my line of questions, I
    > am asking why it doesn't also match itself, and for what reason you would want
    > to match descendents of x but not x itself. Does anyone have a logical reason
    > why this is the case?


    I think you confuse the kind_of? relation with the equals or "is"
    relation.

    Class kind_of Class
    Class kind_of Object
    Object kind_of Object
    Class is Class
    mod is_a Class
    instance kind_of mod
    instance kind_of Object

    but not

    instance kind_of Class
    instance is_a Class

    Ari
    Aredridel, Jul 7, 2004
    #16
  17. Charles Comstock

    Pit Capitain Guest

    David A. Black schrieb:

    > As for the first, and Charles's question about why it doesn't work
    > that way: look again at my earlier example:
    >
    > case s
    > when String ...
    >
    > With the "is_a? or ==" implementation, this 'when' clause could mean
    > either that s is String (the Class object) or that s is "Hi, how are
    > you?" (a String object). Knowing that something is either String or a
    > string, but not knowing which, isn't very valuable; it's hard to imagine
    > a case where you would act on that kind of information.


    Ack.

    And a question to the OP: why do you want to apply the case statement to classes
    instead of to their instances? What should this case statement do (depending on
    which class is given)? Maybe we can find an alternative to what you think you need.

    Regards,
    Pit
    Pit Capitain, Jul 7, 2004
    #17
  18. >
    > I think you mean obj.class.ancestors, in which case is_a? should take
    > care of it -- which means that your second definition is actually how
    > the method works, I believe.
    >
    > As for the first, and Charles's question about why it doesn't work
    > that way: look again at my earlier example:
    >
    > case s
    > when String ...
    >
    > With the "is_a? or ==" implementation, this 'when' clause could mean
    > either that s is String (the Class object) or that s is "Hi, how are
    > you?" (a String object). Knowing that something is either String or a
    > string, but not knowing which, isn't very valuable; it's hard to imagine
    > a case where you would act on that kind of information.
    >


    I don't think you would generally pass either an instance of string or
    String to a case statement like this, so it shouldn't generally matter.
    However I think I found a better logical explanation as to why this is
    false.

    String is a constant name that represents a String, however constants
    names that represent String are not strings themselves, so therefor it
    doesn't match. Thus if s holds String it is holding a reference to a
    constant name and not to a String, so it doesn't match.

    Which makes sense, and I can accept that logic. Sorry I guess I wasn't
    making myself clear in what I was asking and so alot of your responses
    were to the question of what Module#=== is useful for, as opposed to
    answering my question which was "why doesn't A === A return true".
    Which has now been answered.

    So now I revise my question:

    Given that A === A logically returns false, is there a good way in a
    case statement to check if these things are the same by some other
    property? For instance a = A; a.id === A.id returns true, but is
    that a logical way to test this? Or is there another way?

    Charles Comstock
    Charles Comstock, Jul 8, 2004
    #18
  19. > Ack.
    >
    > And a question to the OP: why do you want to apply the case statement to
    > classes instead of to their instances? What should this case statement
    > do (depending on which class is given)? Maybe we can find an alternative
    > to what you think you need.
    >
    > Regards,
    > Pit
    >
    >

    def parse(str)
    input = str.chomp.split
    comm = CommandFactory[input[0]]

    case comm
    when StartCommand
    comm.new(input[1],input[2..-1])
    @mobile = input[1]
    when HelpCommand
    else
    comm.new(@mobile,input[1..-1])
    end
    end

    CommandFactory returns the name of the class so that can instantiate it
    later with different arguments. Normally all commands reference who
    they are from but the start command and help are different since the
    start command defines who it is from, and the help command needs to be
    accessable before and after the start command has actually instantiated
    a character. I could pass these as parameters later on through a
    different function, but this seemed a logical way to do it. I think
    this should work:

    def parse(str)
    input = str.chomp.split
    comm = CommandFactory[input[0]]

    case comm.id
    when StartCommand.id
    comm.new(input[1],input[2..-1])
    @mobile = input[1]
    when HelpCommand.id
    else
    comm.new(@mobile,input[1..-1])
    end
    end

    Since we are matching id's now which is valid. The command factory part
    is actually pretty slick too, there is a Command superclass and whenever
    anything derives from it, self.inherited gets called on Command, which
    then grabs the singleton instance of CommandFactory and adds the
    inherited class name to a hash in CommandFactory. So CommandFactory has
    a hash which amoung other things includes {"start" => StartCommand,
    "help" => HelpCommand}, so when I parse the commandline I just grab the
    needed command right out of the CommandFactory and then instantiate it
    with the rest of the commandline parameters.

    It's just a stupid mud project I am doing to test out pattern based
    software design. When it's finished I'll release it to the community as
    example code.

    I think id should fix my problem, it just suprised me when it didn't
    match the name like I thought it would.

    Charles Comstock
    Charles Comstock, Jul 8, 2004
    #19
  20. Hi --

    On Thu, 8 Jul 2004, Charles Comstock wrote:

    > >
    > > I think you mean obj.class.ancestors, in which case is_a? should take
    > > care of it -- which means that your second definition is actually how
    > > the method works, I believe.
    > >
    > > As for the first, and Charles's question about why it doesn't work
    > > that way: look again at my earlier example:
    > >
    > > case s
    > > when String ...
    > >
    > > With the "is_a? or ==" implementation, this 'when' clause could mean
    > > either that s is String (the Class object) or that s is "Hi, how are
    > > you?" (a String object). Knowing that something is either String or a
    > > string, but not knowing which, isn't very valuable; it's hard to imagine
    > > a case where you would act on that kind of information.
    > >

    >
    > I don't think you would generally pass either an instance of string or
    > String to a case statement like this, so it shouldn't generally matter.


    The problem is more fundamental, though: you would be unable to know
    why "when String" had returned true, so you'd have to test it further
    -- so the case statement would have done you no good. If you're sure
    in advance, then having the double behavior isn't necessary; and if
    you're not sure, then the double behavior makes the method useless.

    > However I think I found a better logical explanation as to why this is
    > false.
    >
    > String is a constant name that represents a String, however constants
    > names that represent String are not strings themselves, so therefor it
    > doesn't match. Thus if s holds String it is holding a reference to a
    > constant name and not to a String, so it doesn't match.
    >
    > Which makes sense, and I can accept that logic. Sorry I guess I wasn't
    > making myself clear in what I was asking and so alot of your responses
    > were to the question of what Module#=== is useful for, as opposed to
    > answering my question which was "why doesn't A === A return true".


    You were clear; my point was that if A === A is true, and A === A.new
    is also true, the === method isn't giving you any useful information,
    which in turn is a reason for its not being designed that way. As for
    the design choice between the two, my impression has always been that
    Matz felt the #is_a? one would be more likely to be useful than the
    #== one.

    > Which has now been answered.
    >
    > So now I revise my question:
    >
    > Given that A === A logically returns false, is there a good way in a
    > case statement to check if these things are the same by some other
    > property? For instance a = A; a.id === A.id returns true, but is
    > that a logical way to test this? Or is there another way?


    id should achieve what you want, or maybe you could use an if
    statement instead of a case statment.


    David

    --
    David A. Black
    David A. Black, Jul 8, 2004
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Monique Y. Mudama
    Replies:
    1
    Views:
    443
    Monique Y. Mudama
    Jun 28, 2005
  2. E11
    Replies:
    1
    Views:
    4,720
    Thomas Weidenfeller
    Oct 12, 2005
  3. Replies:
    0
    Views:
    287
  4. lovecreatesbeauty
    Replies:
    8
    Views:
    1,630
    Old Wolf
    Sep 12, 2005
  5. Ken Fine
    Replies:
    3
    Views:
    521
    Steven Cheng [MSFT]
    Jul 23, 2008
Loading...

Share This Page