Sth. wrong with File.file? (or with me)

H

Hal Fulton

Gavin said:
if a.notnil?
...
end

:)


You put a smiley, but in all seriousness I've thought of this.
(Actually I'd use nonnil? or nnil?)

In fact, when I'm writing code that no one else will see,
<admission type="shameful"/> I sometime use methods like these:

a1 = []
a2 = [1,2,3]
s1 = ""
s2 = "a string"
h1 = {}
h2 = {1=>2, 2=>4}

a1.null? # true
a1.nnull? # false
a2.null? # false
a2.nnull? # true

s1.null? # true
h1.null? # true

# And so on...

See below, and let the flamefest begin.


Hal


class Array
def null?
! empty?
end
end

class String
def null?
! empty?
end
end

class Hash
def null?
! empty?
end
end

class Fixnum
def null?
self == 0
end
end

class File
def null? # now a little fun
size == 0
end
end

# And now even more fun

class Nil
def null?
true
end
def nnil? # for symmetry
false
end
end

# And the most fun of all, our beloved nnull?

class Object
def null
false # until overridden
end
def nnull?
! null? # inherited by everyone
end
end
 
J

Joel VanderWerf

Hal said:
class Array
def null?
! empty?
end
end

class String
def null?
! empty?
end
end

class Hash
def null?
! empty?
end
end

class Fixnum
def null?
self == 0
end
end

class File
def null? # now a little fun
size == 0
end
end

# And now even more fun

class Nil
def null?
true
end
def nnil? # for symmetry
false
end
end

# And the most fun of all, our beloved nnull?

class Object
def null
false # until overridden
end
def nnull?
! null? # inherited by everyone
end
end

Why not just define #empty? for Fixum, File, NilClass, and Object, and
then define nonempty? instead of (argh, can't... make... self... type...
this...) nnull? ?

The possibility of confusion between nil and null is too great (for me
at least).
 
H

Hal Fulton

Joel said:
Why not just define #empty? for Fixum, File, NilClass, and Object, and
then define nonempty? instead of (argh, can't... make... self... type...
this...) nnull? ?

Yes, nnull? is a pretty ugly name, isn't it? But I dislike long names
such as non_null, not_null, non_empty, aint_null, etc.

Actually, I like "null" better than "empty" -- just a meaningless opinion.

And by the way, my original purpose in defining null? was to use it for
the "nil_or_empty?" that people sometimes use.
The possibility of confusion between nil and null is too great (for me
at least).

And they're quite distinct in my mind -- another meaningless opinion
of mine.


Hal
 
G

Gavin Sinclair

You put a smiley, but in all seriousness I've thought of this.
(Actually I'd use nonnil? or nnil?)

Smiley shmiley:

require 'extensions/object'

if a.notnil?
...
elsif b.nonnil?
...
end

It strictly concerns 'nil', though -- no concept of emptiness is
entertained.

Gavin
 
T

trans. (T. Onoma)

|
| require 'extensions/object'
|
| if a.notnil?
| ...
| elsif b.nonnil?
| ...
| end

What's wrong with:

if not a.nil?
...
end

T.
 
L

Logan Capaldo

What's wrong with:

if not a.nil?
...
end

T.

Flow I guess. If I am reading source, it feels better to say "if a is
not nil" as opposed to "if it is not true that a is nil"
 
D

David A. Black

Hi --

Yes, nnull? is a pretty ugly name, isn't it? But I dislike long names
such as non_null, not_null, non_empty, aint_null, etc.

How about ull? :)


David
 
D

David A. Black

Hi --

|
| require 'extensions/object'
|
| if a.notnil?
| ...
| elsif b.nonnil?
| ...
| end

What's wrong with:

if not a.nil?
...
end

It looks good to me. Also:

unless a.nil?
...
end

although I know some people don't like the unless/else sequence that
might follow on that.


David
 
H

Hal Fulton

trans. (T. Onoma) said:
|
| require 'extensions/object'
|
| if a.notnil?
| ...
| elsif b.nonnil?
| ...
| end

What's wrong with:

if not a.nil?
...
end

Nothing, really. I'd ordinarily use that, especially in public.

It's a minor bit of (my personal) psychology, really. I'd rather
ask what something IS rather than what it ISN'T.

In the same way, we could say and 'if not a' -- but there is
something a little clearer about 'a.nil?' instead.

It's (distantly) like the line of code I wrote which said:

upload unless unchanged

and people commented, Why wouldn't you say:

upload if changed

And I could really only say: Well, that's how I think.

When I code an if, I usually code the "expected" or "normal" case
as the first branch, and the rest as the "else" part.

Similarly when I use unless, it's usually when a case is (expected
to be) rare or exceptional.

Because the file would "normally" be changed, the "unless" part was
an exception to the rule.

This is that kind of thing. It's all in my head.


Hal
 
A

Austin Ziegler

Personal taste! May be I am fond of wired taste !!
Sorry for trying to share my wired taste with you.

Perhaps it is a matter of taste -- but is this sufficient reason to
want a change to the language? Again, I differentiate between your
proposal for #true? and #false? and the #iftrue mechanisms, as your
mechanism:

if a.true?

doesn't really buy anything over

if a == true

for tests of true-value. Wouldn't it be more OO to actually do:

a.iftrue { things-to-do-if-true }.iffalse { things-to-do-if-false }

rather than simply what you've suggested?
well, we need to know first before using something.
If you are going to use #true?, you need to know what it does.
I am saying this, for your reply about work with others.
We really don't have Object#true? in ruby. If you see #true? in my code,
you got to look around my code to see what it does?
Same way, If I work with you, you might have some new
opinion/idea/concept that I am not familiar with. In that case, I will
have to do the same.

Mmmm. I donno. I don't think that you'd find anyone else using the
#true?/#false? mechanism you said. Most other folks would use
unfamiliar ideas, not unfamiliar and unintuitive syntax. To me, it is
*not* immediately obvious that #true? and #false? would test against
== true and == false.

-austin
 
J

Jean-Hugues ROBERT

Thanks. EOM.
Jean-Hugues ROBERT wrote:

[snip]
As a conclusion, I think that the status quo
is the best solution. Instead of a hard to
understand true?/false?, let's keep an explicit
xxx == true when value matters instead of
truthness.

I agree, and well said.

Hal
 
J

Jean-Hugues ROBERT

Hi There,

Style matters. Personal style matters too. In order
to make my code more readable (to those who don't
know my style) I put system wide changes to Ruby classes
in a file named "rcr.rb". This file implements "my little
darling ruby change requests".

So, if I were to implement true?/false? (which I am not
going to do), I would put the implementation in my rcr.ruby
file.

FWIW.

Yours,

JeanHuguesRobert

PS: There is a copy of my rcr.rb at the end of this
msg.
EOM


Personal taste! May be I am fond of wired taste !!
Sorry for trying to share my wired taste with you.


well, we need to know first before using something.
If you are going to use #true?, you need to know what it does.
I am saying this, for your reply about work with others.
We really don't have Object#true? in ruby. If you see #true? in my code,
you got to look around my code to see what it does?
Same way, If I work with you, you might have some new
opinion/idea/concept that I am not familiar with. In that case, I will
have to do the same.


Mohammad


# rcr.rb
# Ruby Change Requests. Define changes to standard classes.
#
# 04/05/10, JHR, created from earlier work
# 04/05/11, JHR, class Binding methods + Proc##binding()
# 04/06/13, JHR, Binding.of_caller(), thanks to Florian Gross.
#
# (C) See at the end

# What you get when converting an Hash into an Array, see Hash##to_a().
# It is an array of [k,v].
class HashAsArray < Array

def to_h()
h = Hash.new()
each do |(k,v)| h[k] = v end
h
end

end

# What you get when converting an Array into a Hash, see Array##to_h()
# It is a Hash with keys that are integer indexes (from 0 up to size of hash).
class ArrayAsHash < Hash

def to_a()
super().sort_by { |(k,v)| k }.collect { |(k,v)| v }
# ToDo: There must be a faster solution to do that.
end

end

# Have Hash.to_a() return an HashAsArray instead of an Array.
# Besides the class there are no other difference.
class Hash

alias ruby_to_a to_a unless defined? ruby_to_a

# Returns an array of [key,value] pairs.
# Please note that h.to_a().to_h() == h for most purposes.
def to_a()
HashAsArray.new().replace( ruby_to_a())
end

# Returns self. Much like Array##to_a() does.
def to_h()
self
end

# Returns a new Hash updated with members from the other hash.
def +( other )
self.dup().update( other)
end

# Returns a new Hash updated with members from the other hash.
def |( other )
self.dup().update( other)
end

end

# Have Array.to_h() return an ArrayAsHash.
# Please note that aa.to_h().to_a() == aa, which was the initial intend.
class Array
def to_h()
h = ArrayAsHash.new()
each_index do |ii| h[ii] = self[ii] end
return h
end

end

class Symbol
# I often interchange Strings and Symbol in my code.
def intern()
self
end

end

class Continuation

# Thanks to Florian Gross in ruby-talk ML msg 103312.
def self.create( *args, &block )
cc = nil;
result = callcc { |c|
cc = c;
block.call( cc) if block and args.empty?
}
result ||= args
return *[cc, *result]
end
end

# By default class Binding has no methods at all !
class Binding

# Evaluate a Ruby source code string in the binding context.
def eval( str )
Kernel.eval( str, self)
end

# Returns the value of self in the binding context.
def self()
eval( "self")
end

# Returns the local variables defined in the binding context.
def local_variables()
eval( "local_variables")
end

# Returns the Method that was active, if any, when the binding was created
#def method() ...???...

# Returns the Proc that was active, if any, when the binding was created
#def proc() ... ??? ...

# Returns the call stack, same format as Kernel##caller()
def caller( skip = 0 )
eval( "caller( #{skip})")
end

# Returns the value of some variable.
def []( x )
eval( x.to_s())
end

# Set the value of some lvalue.
def []=( l, v )
eval( "proc {|v| #{l} = v").call( v)
end

# Returns the nature of something, nil if that thing is not defined.
def defined?( x )
eval( "defined? #{x}")
end

# Thanks to Florian Gross in ruby-talk ML msg 103312.
# This method returns the binding of the method that called your
# method. Don't use it when you're not inside a method.
#
# It's used like this:
# def inc_counter
# Binding.of_caller do |binding|
# eval("counter += 1", binding)
# end
# end
# counter = 0
# 2.times { inc_counter }
# counter # => 2
#
# You will have to put the whole rest of your method into the
# block that you pass into this method. If you don't do this
# an Exception will be raised. Because of the way that this is
# implemented it has to be done this way.
def self.of_caller( &block )
old_critical = Thread.critical
Thread.critical = true
count = 0
cc, result, error = Continuation.create( nil, nil)
error.call if error
tracer = lambda do |*args|
type, context = args[0], args[4]
if type == "return"
count += 1
# First this method and then calling one will return --
# the trace event of the second event gets the context
# of the method which called the method that called this
# method.
if count == 2
# It would be nice if we could restore the trace_func
# that was set before we swapped in our own one, but
# this is impossible without overloading set_trace_func
# in current Ruby.
set_trace_func( nil)
cc.call( eval( "binding", context), nil)
end
elsif type != "line"
set_trace_func(nil)
error_msg = "Binding.of_caller used in non-method context or " +
"trailing statements of method using it aren't in the block."
cc.call( nil, lambda { raise( ArgumentError, error_msg ) })
end
end
unless result
set_trace_func( tracer)
return nil
else
Thread.critical = old_critical
yield result
end
end

end

class Proc
# Partial evaluation in Ruby. Return a new proc that invokes This
# proc with some of the first parameters pre-initialized.
# Sheme language inspired I think.
# Thanks to Mauricio Fernández
def curry( proc, *args )
prod do | *a |
proc.call( *(args + a))
end
end

# lvalue able
def []=( *args )
self[*args]
end

# Return the proc's binding
def binding()
eval( "binding", self)
end
end

# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is The Rever Reversible Reason.
#
# The Initial Developer of the Original Code is
# Jean-Hugues ROBERT (born dec 25 1965 in Nimes, France).
# Portions created by the Initial Developer are Copyright (C) 2002-2004
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# ***** END LICENSE BLOCK *****
 
M

Mohammad Khan

Hi There,

Style matters. Personal style matters too. In order
to make my code more readable (to those who don't
know my style) I put system wide changes to Ruby classes
in a file named "rcr.rb". This file implements "my little
darling ruby change requests".

So, if I were to implement true?/false? (which I am not
going to do), I would put the implementation in my rcr.ruby
file.

FWIW.

Yours,

JeanHuguesRobert

PS: There is a copy of my rcr.rb at the end of this
msg.
EOM

Hi Jean,

I do the same. I fact I was doing it for a while.

Thanks,
Mohammad

Personal taste! May be I am fond of wired taste !!
Sorry for trying to share my wired taste with you.


well, we need to know first before using something.
If you are going to use #true?, you need to know what it does.
I am saying this, for your reply about work with others.
We really don't have Object#true? in ruby. If you see #true? in my code,
you got to look around my code to see what it does?
Same way, If I work with you, you might have some new
opinion/idea/concept that I am not familiar with. In that case, I will
have to do the same.


Mohammad


# rcr.rb
# Ruby Change Requests. Define changes to standard classes.
#
# 04/05/10, JHR, created from earlier work
# 04/05/11, JHR, class Binding methods + Proc##binding()
# 04/06/13, JHR, Binding.of_caller(), thanks to Florian Gross.
#
# (C) See at the end

# What you get when converting an Hash into an Array, see Hash##to_a().
# It is an array of [k,v].
class HashAsArray < Array

def to_h()
h = Hash.new()
each do |(k,v)| h[k] = v end
h
end

end

# What you get when converting an Array into a Hash, see Array##to_h()
# It is a Hash with keys that are integer indexes (from 0 up to size of hash).
class ArrayAsHash < Hash

def to_a()
super().sort_by { |(k,v)| k }.collect { |(k,v)| v }
# ToDo: There must be a faster solution to do that.
end

end

# Have Hash.to_a() return an HashAsArray instead of an Array.
# Besides the class there are no other difference.
class Hash

alias ruby_to_a to_a unless defined? ruby_to_a

# Returns an array of [key,value] pairs.
# Please note that h.to_a().to_h() == h for most purposes.
def to_a()
HashAsArray.new().replace( ruby_to_a())
end

# Returns self. Much like Array##to_a() does.
def to_h()
self
end

# Returns a new Hash updated with members from the other hash.
def +( other )
self.dup().update( other)
end

# Returns a new Hash updated with members from the other hash.
def |( other )
self.dup().update( other)
end

end

# Have Array.to_h() return an ArrayAsHash.
# Please note that aa.to_h().to_a() == aa, which was the initial intend.
class Array
def to_h()
h = ArrayAsHash.new()
each_index do |ii| h[ii] = self[ii] end
return h
end

end

class Symbol
# I often interchange Strings and Symbol in my code.
def intern()
self
end

end

class Continuation

# Thanks to Florian Gross in ruby-talk ML msg 103312.
def self.create( *args, &block )
cc = nil;
result = callcc { |c|
cc = c;
block.call( cc) if block and args.empty?
}
result ||= args
return *[cc, *result]
end
end

# By default class Binding has no methods at all !
class Binding

# Evaluate a Ruby source code string in the binding context.
def eval( str )
Kernel.eval( str, self)
end

# Returns the value of self in the binding context.
def self()
eval( "self")
end

# Returns the local variables defined in the binding context.
def local_variables()
eval( "local_variables")
end

# Returns the Method that was active, if any, when the binding was created
#def method() ...???...

# Returns the Proc that was active, if any, when the binding was created
#def proc() ... ??? ...

# Returns the call stack, same format as Kernel##caller()
def caller( skip = 0 )
eval( "caller( #{skip})")
end

# Returns the value of some variable.
def []( x )
eval( x.to_s())
end

# Set the value of some lvalue.
def []=( l, v )
eval( "proc {|v| #{l} = v").call( v)
end

# Returns the nature of something, nil if that thing is not defined.
def defined?( x )
eval( "defined? #{x}")
end

# Thanks to Florian Gross in ruby-talk ML msg 103312.
# This method returns the binding of the method that called your
# method. Don't use it when you're not inside a method.
#
# It's used like this:
# def inc_counter
# Binding.of_caller do |binding|
# eval("counter += 1", binding)
# end
# end
# counter = 0
# 2.times { inc_counter }
# counter # => 2
#
# You will have to put the whole rest of your method into the
# block that you pass into this method. If you don't do this
# an Exception will be raised. Because of the way that this is
# implemented it has to be done this way.
def self.of_caller( &block )
old_critical = Thread.critical
Thread.critical = true
count = 0
cc, result, error = Continuation.create( nil, nil)
error.call if error
tracer = lambda do |*args|
type, context = args[0], args[4]
if type == "return"
count += 1
# First this method and then calling one will return --
# the trace event of the second event gets the context
# of the method which called the method that called this
# method.
if count == 2
# It would be nice if we could restore the trace_func
# that was set before we swapped in our own one, but
# this is impossible without overloading set_trace_func
# in current Ruby.
set_trace_func( nil)
cc.call( eval( "binding", context), nil)
end
elsif type != "line"
set_trace_func(nil)
error_msg = "Binding.of_caller used in non-method context or " +
"trailing statements of method using it aren't in the block."
cc.call( nil, lambda { raise( ArgumentError, error_msg ) })
end
end
unless result
set_trace_func( tracer)
return nil
else
Thread.critical = old_critical
yield result
end
end

end

class Proc
# Partial evaluation in Ruby. Return a new proc that invokes This
# proc with some of the first parameters pre-initialized.
# Sheme language inspired I think.
# Thanks to Mauricio Fernández
def curry( proc, *args )
prod do | *a |
proc.call( *(args + a))
end
end

# lvalue able
def []=( *args )
self[*args]
end

# Return the proc's binding
def binding()
eval( "binding", self)
end
end

# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is The Rever Reversible Reason.
#
# The Initial Developer of the Original Code is
# Jean-Hugues ROBERT (born dec 25 1965 in Nimes, France).
# Portions created by the Initial Developer are Copyright (C) 2002-2004
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# ***** END LICENSE BLOCK *****
 
M

Mohammad Khan

Perhaps it is a matter of taste -- but is this sufficient reason to
want a change to the language?
Answer is Yes.
If you find something good to you, you will want to share it others.
After share it with others, you might learn that your idea it not as
good as it were to you.

Well, I have learned many of us did not like this #true? and #false?
idea. But I still like it.
Again, I differentiate between your
proposal for #true? and #false? and the #iftrue mechanisms, as your
mechanism:



if a.true?

doesn't really buy anything over

if a == true

for tests of true-value. Wouldn't it be more OO to actually do:

a.iftrue { things-to-do-if-true }.iffalse { things-to-do-if-false }

rather than simply what you've suggested?


Mmmm. I donno. I don't think that you'd find anyone else using the
#true?/#false? mechanism you said. Most other folks would use
unfamiliar ideas, not unfamiliar and unintuitive syntax. To me, it is
*not* immediately obvious that #true? and #false? would test against
== true and == false.

-austin

Sometimes new things are unfamiliar, even existing thing can be
unfamiliar. Unfamiliar doesn't mean wrong. There is no way around other
than learn to be familiar with them.
Here is an example,
In ruby there have many methods that names end with '!' like, collect!,
compact!. I was so used to that '!' means its return the object after
'affect' and without '!' return the part of the object that was
affected. I hope, you guys understood me. English is not my primary
language.
I wrote a script by using Array#delete. I and one of co-worker were
working together. When he saw my code, he said it should be #delete!.
BTW, we are coding in Ruby for about two years. when I wrote that line,
I also wrote '#delete!' ! But after ran my script first time I got to
look at my 'Programming Ruby' book.


Mohammad
 
M

Michael DeHaan

"In ruby there have many methods that names end with '!' like, collect!,
compact!. I was so used to that '!' means its return the object after
'affect' and without '!' return the part of the object that was
affected."

The exclamation actually means the operation is destructive and
forever changes the contents of the calling object. It doesn't have
anything to do with the return codes. It's a very nice convention.

Here is a good example:
http://www.rubycentral.com/book/ref_c_string.html#String.chomp

In this case, both examples would return the same string, but one
would change the string it was called against.
 
M

Mohammad Khan

"In ruby there have many methods that names end with '!' like, collect!,
compact!. I was so used to that '!' means its return the object after
'affect' and without '!' return the part of the object that was
affected."

The exclamation actually means the operation is destructive and
forever changes the contents of the calling object. It doesn't have
anything to do with the return codes. It's a very nice convention.

Here is a good example:
http://www.rubycentral.com/book/ref_c_string.html#String.chomp

In this case, both examples would return the same string, but one
would change the string it was called against.

Thanks for your nice explanation on exclamatory sign.
And Sorry for my poor English.

See the example below, I was confused with Array#delete! and
Array#delete. Bottom line is, if there have something unfamiliar, I will
have to learn it to make it familiar. There is no other way around.

[mkhan@localhost bin]$ irb
irb(main):001:0> arr = [1, 2, 2, 2, 3, 4]
=> [1, 2, 2, 2, 3, 4]
irb(main):002:0> str = "string"
=> "string"
irb(main):004:0> p arr
[1, 2, 2, 2, 3, 4]
=> nil
irb(main):005:0> p str
"string"
=> nil
irb(main):006:0> arr.delete(2)
=> 2
irb(main):008:0> str.delete("r")
=> "sting"
irb(main):009:0> p arr
[1, 3, 4]
=> nil
irb(main):010:0> p str
"string"
=> nil
irb(main):011:0> str.delete!("r")
=> "sting"
irb(main):012:0> arr.delete!(2)
NoMethodError: undefined method `delete!' for [1, 3, 4]:Array
from (irb):12
irb(main):013:0> p str
"sting"
=> nil
irb(main):014:0> p arr
[1, 3, 4]
=> nil
irb(main):015:0>

Mohammad
 
D

David A. Black

Hi --

"In ruby there have many methods that names end with '!' like, collect!,
compact!. I was so used to that '!' means its return the object after
'affect' and without '!' return the part of the object that was
affected."

The exclamation actually means the operation is destructive and
forever changes the contents of the calling object. It doesn't have
anything to do with the return codes. It's a very nice convention.

Bang (!) methods don't have to be destructive; the ! basically means
"dangerous operation -- be careful!" So there can be non-destructive
methods with ! (like exit!), and destructive methods without it (like
Array#pop). A lot of destructive methods are also bang-methods, but
there's no direct correlation.

What this means, in Matz's words, is: "Every bang method has non-bang
(i.e. safer) counterpart. You can totally forget about bang methods
at first."


David
 
M

Mohammad Khan

Hi --



Bang (!) methods don't have to be destructive; the ! basically means
"dangerous operation -- be careful!" So there can be non-destructive
methods with ! (like exit!), and destructive methods without it (like
Array#pop). A lot of destructive methods are also bang-methods, but
there's no direct correlation.

What this means, in Matz's words, is: "Every bang method has non-bang
(i.e. safer) counterpart. You can totally forget about bang methods
at first."


David

Thanks, for your explanation, David.
I have learned it after a confusion about Array#delete
 
T

Tim Sutherland

Hal Fulton wrote: said:
You put a smiley, but in all seriousness I've thought of this.
(Actually I'd use nonnil? or nnil?)

In fact, when I'm writing code that no one else will see,
<admission type="shameful"/> I sometime use methods like these:

a1 = []
a2 = [1,2,3]
s1 = ""
s2 = "a string"
h1 = {}
h2 = {1=>2, 2=>4}

a1.null? # true
a1.nnull? # false
a2.null? # false
a2.nnull? # true

s1.null? # true
h1.null? # true

# And so on...

See below, and let the flamefest begin.
[...]

nil.nil? # true
nil.nnil? # false
nil.nnnil? # true
nil.nnnnil? # false

class Object
def method_missing(name, *args)
if name.to_s =~ /^n*nil\?$/
name.to_s.size % 2 == 0 ? nil? : !nil?
else
super
end
end
end
 

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
474,161
Messages
2,570,892
Members
47,427
Latest member
HildredDic

Latest Threads

Top