Kirbybase Hacks NilClass

Discussion in 'Ruby' started by James Edward Gray II, Mar 4, 2006.

  1. I'm examining Kirbybase for use it a project and was surprised to
    find this bit of code in it:

    #-----------------------------------------------------------------------
    ----
    # NilClass
    #-----------------------------------------------------------------------
    ----
    class NilClass

    #-----------------------------------------------------------------------
    # method_missing

    #-----------------------------------------------------------------------
    #
    # This code is necessary because if, inside a select condition code
    # block, there is a case where you are trying to do an expression
    # against a table field that is equal to nil, I don't want a method
    # missing exception to occur. I just want the expression to be
    nil. I
    # initially had this method returning false, but then I had an
    issue
    # where I had a YAML field that was supposed to hold an Array.
    If the
    # field was empty (i.e. nil) it was actually returning false
    when it
    # should be returning nil. Since nil evaluates to false, it
    works if I
    # return nil.
    # Here's an example:
    # #select { |r| r.speed > 300 }
    # What happens if speed is nil (basically NULL in DBMS terms)?
    Without
    # this code, an exception is going to be raised, which is not
    what we
    # really want. We really want this expression to return nil.
    def method_missing(method_id, *stuff)
    return nil
    end
    end

    This has been a popular discussion lately, but I just don't think
    loading a database library should fundamentally change the language.
    ActiveRecord doesn't hack NilClass and we seem to do okay with that.
    Why can't the above example just be coded as:

    select { |r| r.speed and r.speed > 300 }

    or:

    select { |r| r.speed > 300 rescue false }

    Are Kirbybase users really liking this behavior?

    James Edward Gray II
     
    James Edward Gray II, Mar 4, 2006
    #1
    1. Advertising

  2. James Edward Gray II

    Ross Bamford Guest

    On Sun, 2006-03-05 at 01:37 +0900, James Edward Gray II wrote:
    > I'm examining Kirbybase for use it a project and was surprised to
    > find this bit of code in it:
    >
    > #-----------------------------------------------------------------------
    > ----
    > # NilClass
    > #-----------------------------------------------------------------------
    > ----
    > class NilClass
    >
    > #-----------------------------------------------------------------------
    > # method_missing
    >
    > #-----------------------------------------------------------------------
    > #
    > # This code is necessary because if, inside a select condition code
    > # block, there is a case where you are trying to do an expression
    > # against a table field that is equal to nil, I don't want a method
    > # missing exception to occur. I just want the expression to be
    > nil. I
    > # initially had this method returning false, but then I had an
    > issue
    > # where I had a YAML field that was supposed to hold an Array.
    > If the
    > # field was empty (i.e. nil) it was actually returning false
    > when it
    > # should be returning nil. Since nil evaluates to false, it
    > works if I
    > # return nil.
    > # Here's an example:
    > # #select { |r| r.speed > 300 }
    > # What happens if speed is nil (basically NULL in DBMS terms)?
    > Without
    > # this code, an exception is going to be raised, which is not
    > what we
    > # really want. We really want this expression to return nil.
    > def method_missing(method_id, *stuff)
    > return nil
    > end
    > end
    >
    > This has been a popular discussion lately, but I just don't think
    > loading a database library should fundamentally change the language.
    > ActiveRecord doesn't hack NilClass and we seem to do okay with that.
    > Why can't the above example just be coded as:
    >
    > select { |r| r.speed and r.speed > 300 }
    >
    > or:
    >
    > select { |r| r.speed > 300 rescue false }
    >
    > Are Kirbybase users really liking this behavior?
    >
    > James Edward Gray II


    I've never used KirbyBase, but from this it looks like it could just
    catch NoMethodError in #select...? Introducing this new behaviour to nil
    could seriously suck in at least one case I can think of: while coding
    stuff up I often get a nomethoderror for nil telling me I'm off by one
    or have passed silly arguments...

    --
    Ross Bamford -
     
    Ross Bamford, Mar 4, 2006
    #2
    1. Advertising

  3. James Edward Gray II

    Jamey Cribbs Guest

    wrote:

    > Hi --
    >
    > On Sun, 5 Mar 2006, James Edward Gray II wrote:
    >
    >> I'm examining Kirbybase for use it a project and was surprised to
    >> find this bit of code in it:
    >>
    >> #---------------------------------------------------------------------------
    >>
    >> # NilClass
    >> #---------------------------------------------------------------------------
    >>
    >> class NilClass
    >>
    >> def method_missing(method_id, *stuff)
    >> return nil
    >> end
    >> end
    >>
    >> This has been a popular discussion lately, but I just don't think
    >> loading a database library should fundamentally change the language.
    >> ActiveRecord doesn't hack NilClass and we seem to do okay with that.
    >> Why can't the above example just be coded as:
    >>
    >> select { |r| r.speed and r.speed > 300 }
    >>
    >> or:
    >>
    >> select { |r| r.speed > 300 rescue false }

    >
    >
    > Or, depending on circumstances: r.speed.to_i > 300. I would ...


    Thanks very much for the feedback on my overriding
    NilClass#medthod_missing in KirbyBase. I don't think the three examples
    shown above would really be acceptable, because, could you imagine
    having to do this for every query where there was a chance that a
    #method_missing could be thrown? I think that would get old very fast.

    However, the last example does give me an idea. I'm going to take a
    look at the KBTable#select method and see if I can wrap the query
    processing logic in a begin/rescue block. It may be as simple as what
    David shows here, have the rescue return false. The problem I can see
    is when there is an OR condition in the block, i.e.:

    #select { |r| r.speed > 300 or r.range < 900 }

    Now, here's a *very* simplified version of KBTable#select, with a
    proposed adding of a begin/rescue block around the query instead of the
    current redefining of NilClass#method_missing:

    def select(&query_block)
    valid_matches = []
    table_records.each do |table_record|
    begin
    if query_block(table_record)
    valid_matches << table_record
    end
    rescue NoMethodError
    end
    end
    end

    Now, lets say we are looping through the table records and we get to a
    record where :speed is nil and :range is 800. According to the query
    block, this record should qualify as a valid match. But, if I don't
    override NilClass#method_missing to return fasle, but, instead, try to
    catch it with a begin/rescue block like I show in the code above, the
    record will *not* be added to valid matches. The problem with the code
    above is that I can't get granular enough. There is no way to get
    inside the query block and put a begin/rescue around *each* condition
    within the block.

    If I could get enough info about the calling method, when I'm inside
    NilClass#method_missing, then maybe I could conditionally return a false
    only when it was apparent that the #method_missing exception was raised
    in KBTable#select. But, the arguments passed into #method_missing are
    the symbol of the method, in this case :> and an array containing the
    arguments passed to the missing method, in this case [300]; not enough
    info for me to determine if this came from KBTable#select.

    I would be very interested in any suggestions, ideas, or feedback on
    this issue.

    Jamey
     
    Jamey Cribbs, Mar 4, 2006
    #3
  4. James Edward Gray II

    Jamey Cribbs Guest

    Jamey Cribbs wrote:

    > wrote:
    >
    >> Hi --
    >>
    >> On Sun, 5 Mar 2006, James Edward Gray II wrote:
    >>
    >>> I'm examining Kirbybase for use it a project and was surprised to
    >>> find this bit of code in it:
    >>>
    >>> #---------------------------------------------------------------------------
    >>>
    >>> # NilClass
    >>> #---------------------------------------------------------------------------
    >>>
    >>> class NilClass
    >>>
    >>> def method_missing(method_id, *stuff)
    >>> return nil
    >>> end
    >>> end
    >>>
    >>> This has been a popular discussion lately, but I just don't think
    >>> loading a database library should fundamentally change the
    >>> language. ActiveRecord doesn't hack NilClass and we seem to do okay
    >>> with that. Why can't the above example just be coded as:
    >>>
    >>> select { |r| r.speed and r.speed > 300 }
    >>>
    >>> or:
    >>>
    >>> select { |r| r.speed > 300 rescue false }

    >>
    >>
    >>
    >> Or, depending on circumstances: r.speed.to_i > 300. I would ...

    >
    >
    > Thanks very much for the feedback on my overriding
    > NilClass#medthod_missing in KirbyBase. I don't think the three
    > examples shown above would really be acceptable, because, could you
    > imagine having to do this for every query where there was a chance
    > that a #method_missing could be thrown? I think that would get old
    > very fast.
    >
    > However, the last example does give me an idea. I'm going to take a
    > look at the KBTable#select method and see if I can wrap the query
    > processing logic in a begin/rescue block. It may be as simple as what
    > David shows here, have the rescue return false. The problem I can see
    > is when there is an OR condition in the block, i.e.:
    >
    > #select { |r| r.speed > 300 or r.range < 900 }
    >
    > Now, here's a *very* simplified version of KBTable#select, with a
    > proposed adding of a begin/rescue block around the query instead of
    > the current redefining of NilClass#method_missing:
    >
    > def select(&query_block)
    > valid_matches = []
    > table_records.each do |table_record|
    > begin
    > if query_block(table_record)
    > valid_matches << table_record
    > end
    > rescue NoMethodError
    > end
    > end
    > end
    >
    > Now, lets say we are looping through the table records and we get to a
    > record where :speed is nil and :range is 800. According to the query
    > block, this record should qualify as a valid match. But, if I don't
    > override NilClass#method_missing to return fasle, but, instead, try to
    > catch it with a begin/rescue block like I show in the code above, the
    > record will *not* be added to valid matches. The problem with the
    > code above is that I can't get granular enough. There is no way to
    > get inside the query block and put a begin/rescue around *each*
    > condition within the block.
    > If I could get enough info about the calling method, when I'm inside
    > NilClass#method_missing, then maybe I could conditionally return a
    > false only when it was apparent that the #method_missing exception was
    > raised in KBTable#select. But, the arguments passed into
    > #method_missing are the symbol of the method, in this case :> and an
    > array containing the arguments passed to the missing method, in this
    > case [300]; not enough info for me to determine if this came from
    > KBTable#select.
    >
    > I would be very interested in any suggestions, ideas, or feedback on
    > this issue.


    Hey, I think I will just respond to myself with a suggestion. :)

    What has been kicked around when this question has come up before is for
    me to create something like a NULL class and use this to designate a
    null value in the database, instead of using nil. This would take care
    of having to override NilClass#method_missing. It would bring up a few
    other problems, namely, what if someone wants to store the string value
    NULL in a field. But I imagine these could be overcome.

    If this is indeed a really big issue (meaning KirbyBase's overriding of
    NilClass#method_missing), then I could get to work on this. Thoughts?

    Jamey
     
    Jamey Cribbs, Mar 4, 2006
    #4
  5. On 3/4/06, Jamey Cribbs <> wrote:

    > What has been kicked around when this question has come up before is for
    > me to create something like a NULL class and use this to designate a
    > null value in the database, instead of using nil. This would take care
    > of having to override NilClass#method_missing. It would bring up a few
    > other problems, namely, what if someone wants to store the string value
    > NULL in a field. But I imagine these could be overcome.


    I was discussing this with one of the guys from new_haven.rb, Matthew Desma=
    rais
    when we were heading down to NYC.rb

    A NULL Class was the best thing we came up with too... even though
    this might create some issues within KirbyBase that will need to be
    worked around, it'd make this great piece of software much less scary
    to people who might like to use it.
     
    Gregory Brown, Mar 4, 2006
    #5
  6. On Mar 4, 2006, at 11:56 AM, Jamey Cribbs wrote:

    > Thanks very much for the feedback on my overriding
    > NilClass#medthod_missing in KirbyBase. I don't think the three
    > examples shown above would really be acceptable, because, could you
    > imagine having to do this for every query where there was a chance
    > that a #method_missing could be thrown? I think that would get
    > old very fast.


    There are a few problems with this line of thinking, in my opinion:

    1. You change the semantics of the language to get around this.
    Overlooking the dangers of this for now, how is someone even suppose
    to know to write non-standard Ruby when using the Kirbybase library?

    2. If the normal Ruby behavior is bothering a user, they can add the
    one-line hack with the knowledge of the trade-off they are choosing.

    3. It's just too dangerous. It's very possible you break other Ruby
    libraries with a hack like this. We don't want to not be able to use
    Kirbybase for a project because it breaks library XYZ.

    I'm really not trying to be mean. I am very much liking what I have
    seen about Kirbybase, which is why I'm telling you about the barrier
    that is keeping me from using it. ;)

    James Edward Gray II
     
    James Edward Gray II, Mar 4, 2006
    #6
  7. James Edward Gray II

    angus Guest

    [Jamey Cribbs <>, 2006-03-04 18.56 CET]
    > However, the last example does give me an idea. I'm going to take a
    > look at the KBTable#select method and see if I can wrap the query
    > processing logic in a begin/rescue block. It may be as simple as what
    > David shows here, have the rescue return false. The problem I can see
    > is when there is an OR condition in the block, i.e.:
    >
    > #select { |r| r.speed > 300 or r.range < 900 }

    [...]
    > Now, lets say we are looping through the table records and we get to a
    > record where :speed is nil and :range is 800. According to the query
    > block, this record should qualify as a valid match. But, if I don't
    > override NilClass#method_missing to return fasle, but, instead, try to
    > catch it with a begin/rescue block like I show in the code above, the
    > record will *not* be added to valid matches. The problem with the code
    > above is that I can't get granular enough. There is no way to get
    > inside the query block and put a begin/rescue around *each* condition
    > within the block.


    But doesn't NULL always propagate in "database semantics"? I mean, if any
    subexpression is NULL, the whole expression becomes NULL. It's the expected
    behaviour (but maybe not to the users of KirbyBase). In SQL, normally, one
    uses NVL(a, b) (with the meaning 'a.nil? ? b : a') to guard subexpressions
    against NULL.
     
    angus, Mar 4, 2006
    #7
  8. James Edward Gray II

    Dave Burt Guest

    Jamey Cribbs wrote:
    > What has been kicked around when this question has come up before is for
    > me to create something like a NULL class and use this to designate a null
    > value in the database, instead of using nil. This would take care of
    > having to override NilClass#method_missing. It would bring up a few other
    > problems, namely, what if someone wants to store the string value NULL in
    > a field. But I imagine these could be overcome.


    If you define a new NULL class, you have the problem of it being true in
    conditionals. I think it would be difficult to make it work intuitively, and
    impossible to make it as well as the nil.method_missing hack works.

    James Edward Gray II wrote:
    > This has been a popular discussion lately, but I just don't think loading
    > a database library should fundamentally change the language.


    As good a point as that is, I think this is KirbyBase's best option. I think
    the risk of nil.method_missing returning nil breaking something is low, as
    has been argued in the debates on this list (Guy Decoux?). If it did,
    wouldn't we have heard about it by now?

    It does probably demand a prominent warning in the README.

    Cheers,
    Dave
     
    Dave Burt, Mar 5, 2006
    #8
  9. James Edward Gray II

    Jamey Cribbs Guest

    Jamey Cribbs wrote:

    > angus wrote:
    >
    >> But doesn't NULL always propagate in "database semantics"? I mean, if=20
    >> any
    >> subexpression is NULL, the whole expression becomes NULL. It's the=20
    >> expected
    >> behaviour (but maybe not to the users of KirbyBase). In SQL,=20
    >> normally, one
    >> uses NVL(a, b) (with the meaning 'a.nil? ? b : a') to guard=20
    >> subexpressions
    >> against NULL.
    >>
    >>

    > I'm not so sure about that. Here's a link to a page talking about how=20
    > the developer of SQLite decided how to treat NULL:
    >
    > http://www.sqlite.org/nulls.html
    >
    > If I read it correctly, he says that all of the major SQL dbms' treat=20
    > "null OR true" as true. Maybe I'm reading this page wrong, but that=20
    > seems to go against what you are saying.
    >
    > I'm definitely not a database expert, so anyone with knowledge on=20
    > this, please chime in.
    >
    > In the meantime, I'm going to start taking a look at adding a Null=20
    > class (or some such construct) to KirbyBase, to see if I can do away=20
    > with the NilClass#method_missing issue.


    Here's another follow-up to Angus comment about NULL values in OR=20
    expressions that, to me, is evidence that SQL treats the expression=20
    "null OR true" as true. This excerpt is from:

    http://databases.about.com/cs/sql/a/aa042803a.htm

    "The OR operand treats NULL values in a similar fashion. If the other=20
    operand is TRUE, the result of the OR is TRUE (because the real value of=20
    the NULL operand doesn=92t matter.) On the other hand, if the other=20
    operand is either FALSE or NULL, the result of the OR operation is NULL."

    Here's a link to a Microsoft page talking about NULL.

    http://msdn.microsoft.com/library/default.asp?url=3D/library/en-us/acdata=
    /ac_8_qd_02_8pwy.asp

    It says, in the second table, that the result of applying an OR operator=20
    to two Boolean operands, one being NULL, and the other being TRUE, is TRU=
    E.

    Although, to be honest, I don't really care how SQL does it. One reason=20
    I wrote KirbyBase is because I don't like using SQL in my programs and=20
    the thought of being able to express my query in Ruby code was very=20
    attractive.

    I want KirbyBase to follow Matz Principle of Least Surprise motto. To=20
    me, if I have a query that says, "nil > 300 or 800 < 900", I think that=20
    query is true. That, to me follows POLS, but of course, everyone has=20
    different ideas of what is Surprising. :)

    I know James said in an earlier email that the proper Ruby expression,=20
    in order to make sure the query didn't throw an exception is:

    #select { |r| r.speed and r.speed > 300 }

    But, even if that is "proper" Ruby code, I don't want the user to have=20
    to do that for *every* freakin query just because one of the field=20
    values *might* be nil. What if you were testing for three or four=20
    conditions? To cover your ass, you would have to write a query like this:

    #select { |r| (r.speed and r.speed > 300) or (r.range and r.range < 900)=20
    or (r.service_date and r.service_date < Date.today) }

    That's just ugly.

    You should be able to just write:

    #select { |r| r.speed > 300 or r.range < 900 or r.service_date <=20
    Date.today }

    To me, that is POLS. Maybe you don't agree with me. I guess that means=20
    that this is my contribution to "Opinionated Software". :)

    Anyway, I hear ya, James. You want me to quit messin' around with=20
    NilClass. Let me see what I can whip up with a Null class or maybe I can=20
    subclass Nil (I'll call it KBNil, or something) and override the=20
    #method_missing method in the subclass.

    Jamey
     
    Jamey Cribbs, Mar 5, 2006
    #9
  10. James Edward Gray II

    Jamey Cribbs Guest

    Dave Burt wrote:

    >As good a point as that is, I think this is KirbyBase's best option. I think
    >the risk of nil.method_missing returning nil breaking something is low, as
    >has been argued in the debates on this list (Guy Decoux?). If it did,
    >wouldn't we have heard about it by now?
    >
    >It does probably demand a prominent warning in the README.
    >
    >

    Hey, Dave. Here's what I have smack dab in the middle of the README:

    ---------------------------------------------------------------------------------------------------------
    == Warning

    KirbyBase defines #method_missing for NilClass. This might bite you in the
    butt if you override NilClass.method_missing yourself.
    ---------------------------------------------------------------------------------------------------------


    The more I think about this, though, could it be as simple as
    subclassing NilClass, call it KBNil or whatever? Then I could override
    KBNil#method_missing and that wouldn't mess up NilClass. It would be
    fairly easy for me to change KirbyBase to return a KBNil for an empty
    field value instead of nil.

    Thoughts on this?

    Jamey
     
    Jamey Cribbs, Mar 5, 2006
    #10
  11. James Edward Gray II

    Dave Burt Guest

    Jamey Cribbs wrote:
    > Dave Burt wrote:
    >>It does probably demand a prominent warning in the README.

    >
    > Hey, Dave. Here's what I have smack dab in the middle of the README:
    > ...
    > <snip prominent warning>
    > ...
    > The more I think about this, though, could it be as simple as subclassing
    > NilClass, call it KBNil or whatever? Then I could override
    > KBNil#method_missing and that wouldn't mess up NilClass. It would be
    > fairly easy for me to change KirbyBase to return a KBNil for an empty
    > field value instead of nil.


    You can subclass NilClass, but it has no allocator, so you'd have to define
    your own, and such an object still wouldn't be considered false in
    conditionals. There is only one nil, and only one false. So there is no
    point in subclassing NilClass.

    It seems to me that without changing nil.method_missing, you can't have your
    "select do |rec| rec.a < 0 or rec.b < 0 end". You may be able to (re-)define
    nil.method_missing only for the duration it's required, but that may end up
    be more confusing to users.

    Cheers,
    Dave
     
    Dave Burt, Mar 5, 2006
    #11
  12. On Mar 4, 2006, at 8:42 PM, Jamey Cribbs wrote:

    > Dave Burt wrote:
    >
    >> As good a point as that is, I think this is KirbyBase's best
    >> option. I think the risk of nil.method_missing returning nil
    >> breaking something is low, as has been argued in the debates on
    >> this list (Guy Decoux?). If it did, wouldn't we have heard about
    >> it by now?
    >>
    >> It does probably demand a prominent warning in the README.
    >>

    > Hey, Dave. Here's what I have smack dab in the middle of the README:
    >
    > ----------------------------------------------------------------------
    > -----------------------------------
    > == Warning
    >
    > KirbyBase defines #method_missing for NilClass. This might bite
    > you in the
    > butt if you override NilClass.method_missing yourself.
    > ----------------------------------------------------------------------
    > -----------------------------------
    >
    >
    > The more I think about this, though, could it be as simple as
    > subclassing NilClass, call it KBNil or whatever? Then I could
    > override KBNil#method_missing and that wouldn't mess up NilClass.
    > It would be fairly easy for me to change KirbyBase to return a
    > KBNil for an empty field value instead of nil.
    >
    > Thoughts on this?
    >
    > Jamey
    >


    This will probably require some deep magic:
    % irb
    irb(main):001:0> class KBNil < NilClass
    irb(main):002:1> end
    => nil
    irb(main):003:0> k = KBNil.new
    NoMethodError: undefined method `new' for KBNil:Class
    from (irb):3
    irb(main):004:0> k = KBNil.allocate
    TypeError: allocator undefined for KBNil
    from (irb):4:in `allocate'
    from (irb):4

    Undaunted I tried to trick it some more:
    irb(main):005:0> class KBNil < NilClass
    irb(main):006:1> def self.new
    irb(main):007:2> Class.instance_method:)new).bind(self).call
    irb(main):008:2> end
    irb(main):009:1> end
    => nil
    irb(main):010:0> k = KBNil.new
    TypeError: allocator undefined for KBNil
    from (irb):7:in `new'
    from (irb):7:in `new'
    from (irb):10

    Ok, I said let's try the same trick with allocate:

    irb(main):011:0> class KBNil < NilClass
    irb(main):012:1> def self.allocate
    irb(main):013:2> Class.instance_method:)allocate).bind
    (self).call()
    irb(main):014:2> end
    irb(main):015:1> end
    => nil
    irb(main):016:0> k = KBNil.new
    TypeError: allocator undefined for KBNil
    from (irb):7:in `new'
    from (irb):7:in `new'
    from (irb):16

    And lo, it still did not work. At this point I think it will require
    a more advanced rubyist than myself. Either that or a C extension.

    I ran into pretty much the same problem with subclassing FalseClass.

    nil.dup doesn't really work either. So this comes to an issue of
    database semantics vs. ruby semantics. Which is probably part of the
    reason that most DBs do use a custom query language or a variant of SQL.
     
    Logan Capaldo, Mar 5, 2006
    #12
  13. --Apple-Mail-20-8862340
    Content-Transfer-Encoding: 7bit
    Content-Type: text/plain;
    charset=US-ASCII;
    delsp=yes;
    format=flowed


    On Mar 4, 2006, at 9:00 PM, Logan Capaldo wrote:

    > Well based on my intro to db class SQL uses a three-way boolean logic
    >
    > NULL or TRUE = TRUE
    > NULL or FALSE = FALSE
    >
    > NULL and TRUE = NULL
    > NULL and FALSE = FALSE
    >
    > not NULL = NULL
    >
    > Boolean ops involving only TRUE and FALSE work as usual


    Ooops, before someone hits me, I made a mistake in the above NULL or
    FALSE is NULL not FALSE.
    --Apple-Mail-20-8862340--
     
    Logan Capaldo, Mar 5, 2006
    #13
  14. James Edward Gray II

    Trans Guest

    This issue also arises in the Annotation system used by Nitro. The
    solution there was to use NullClass. Unfortuately it does have the TRUE
    conditional issue. I've asked matz and nabu about adding NullClass to
    Ruby core, but they did not feel it was needed. Perhaps they might
    reconsider now that it has come up again?
     
    Trans, Mar 5, 2006
    #14
  15. James Edward Gray II

    Jamey Cribbs Guest

    Dave Burt wrote:

    >You can subclass NilClass, but it has no allocator, so you'd have to define
    >your own, and such an object still wouldn't be considered false in
    >conditionals. There is only one nil, and only one false. So there is no
    >point in subclassing NilClass.
    >
    >
    >

    Yeah, I tried some of the same stuff Logan did in his email and finally
    realized that NilClass won't let you subclass it.

    But, what if I did something like this:

    class KBNil
    def method_missing(a,b)
    nil
    end

    def nil?
    true
    end
    end

    Then, since, nil and false are the only things that don't evaluate to
    true, if you do:

    k = KBNil.new

    puts 'True!' if k > 300 or 800 < 900 # True!

    puts 'False!' unless k > 300 or 800 < 900 # False!

    puts 'False!' unless k =~ /bob/ # False!

    puts 'False!' unless k < Date.today # False!

    k.nil? # true


    I'm just thinking off the top of my head, but what do you think about this?

    Jamey
     
    Jamey Cribbs, Mar 5, 2006
    #15
  16. James Edward Gray II

    Jamey Cribbs Guest

    Jamey Cribbs wrote:

    > Dave Burt wrote:
    >
    >> You can subclass NilClass, but it has no allocator, so you'd have to
    >> define your own, and such an object still wouldn't be considered
    >> false in conditionals. There is only one nil, and only one false. So
    >> there is no point in subclassing NilClass.
    >>
    >>
    >>

    > Yeah, I tried some of the same stuff Logan did in his email and
    > finally realized that NilClass won't let you subclass it.
    >
    > But, what if I did something like this:
    >
    > class KBNil
    > def method_missing(a,b)
    > nil
    > end
    >
    > def nil?
    > true
    > end
    > end
    >
    > Then, since, nil and false are the only things that don't evaluate to
    > true, if you do:
    >
    > k = KBNil.new
    >
    > puts 'True!' if k > 300 or 800 < 900 # True!
    >
    > puts 'False!' unless k > 300 or 800 < 900 # False!


    Oops! That should read:

    puts 'False!' unless k > 300 and 800 < 900 False!

    Jamey
     
    Jamey Cribbs, Mar 5, 2006
    #16
  17. On 3/4/06, Jamey Cribbs <> wrote:

    > But, what if I did something like this:
    >
    > class KBNil
    > def method_missing(a,b)
    > nil
    > end
    >
    > def nil?
    > true
    > end
    > end


    Jamey, I like this. Seems much safer to me.
     
    Gregory Brown, Mar 5, 2006
    #17
  18. On Mar 4, 2006, at 7:34 PM, Jamey Cribbs wrote:

    > #select { |r| (r.speed and r.speed > 300) or (r.range and r.range <
    > 900) or (r.service_date and r.service_date < Date.today) }


    select { |r| r.speed > 300 or r.range < 900 or r.service_date <
    Date.today rescue false }

    > You should be able to just write:
    >
    > #select { |r| r.speed > 300 or r.range < 900 or r.service_date <
    > Date.today }


    I'm great with that goal really, I just don't think changing Ruby
    semantics is the way to get there.

    > Anyway, I hear ya, James. You want me to quit messin' around with
    > NilClass.


    Here's my new idea. What about solving this with default values for
    columns? If speed was defaulting to 0 instead of nil, we wouldn't
    have a problem. That seems to me to be what these example's intend
    anyway.

    Am I crazy?

    James Edward Gray II
     
    James Edward Gray II, Mar 5, 2006
    #18
  19. James Edward Gray II

    Dave Burt Guest

    Jamey Cribbs wrote:
    > k = KBNil.new
    > #...
    > k.nil? # true


    That would be a lie. There can only be one nil.

    Cheers,
    Dave
     
    Dave Burt, Mar 5, 2006
    #19
  20. James Edward Gray II

    Trans Guest

    # :title: NullClass
    #
    # NullClass is essentially NilClass but it differs in one
    # important way. When a method is called against it that it
    # deoesn't have, it will simply return null value rather then
    # raise an error.

    class NullClass #< NilClass
    class << self
    def new
    @null ||= NullClass.allocate
    end
    end
    def inspect ; 'null' ; end
    def nil? ; true ; end
    def null? ; true ; end
    def [](key); nil; end
    def method_missing(sym, *args)
    return nil if sym.to_s[-1,1] == '?'
    self
    end
    end

    module Kernel
    def null
    NullClass.new
    end
    end

    class Object
    def null?
    false
    end
    end
     
    Trans, Mar 5, 2006
    #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. =?Utf-8?B?SG9tYW0=?=

    How to avoid lifecycle hacks?

    =?Utf-8?B?SG9tYW0=?=, Mar 3, 2005, in forum: ASP .Net
    Replies:
    11
    Views:
    640
    =?Utf-8?B?SG9tYW0=?=
    Mar 3, 2005
  2. Eric Pinnell
    Replies:
    5
    Views:
    599
  3. Veritech

    CSS hacks

    Veritech, Jul 15, 2005, in forum: HTML
    Replies:
    2
    Views:
    570
    Veritech
    Jul 16, 2005
  4. Nick Coghlan
    Replies:
    8
    Views:
    405
    Carl Banks
    Mar 10, 2005
  5. Andy Dingley
    Replies:
    7
    Views:
    560
    Andy Dingley
    Mar 19, 2007
Loading...

Share This Page