Numeric?

I've found a bit of an annoyance trying to find out if a number is numeric
or not. I thought it would probably be a simple string method but I found
far more contrived solutions like regex matches. Eventually I settled on
monkey patching string with a Numeric? method using Float(self)! = nil
rescue false.

Is there a better way to go about this? If not, can we get something added
to the core?

Thanks for your time,

Brandon

You might be better off to ask yourself why you need the type checking
anyway. If you have a method designed to handle an argument that might be a
string or an integer you might be trying to do two different things.

If you're sure you want the integer you could just to_i the input.

···

On Dec 27, 2012 10:40 AM, "Brandon Weaver" <keystonelemur@gmail.com> wrote:

I've found a bit of an annoyance trying to find out if a number is numeric
or not. I thought it would probably be a simple string method but I found
far more contrived solutions like regex matches. Eventually I settled on
monkey patching string with a Numeric? method using Float(self)! = nil
rescue false.

Is there a better way to go about this? If not, can we get something added
to the core?

Thanks for your time,

Brandon

Float(string) is your best bet. Why is this inadequate? Are you trying to
decide if a string "looks like a number" but don't want to work with it as
a number after that?

···

On Thu, Dec 27, 2012 at 10:40 AM, Brandon Weaver <keystonelemur@gmail.com>wrote:

I've found a bit of an annoyance trying to find out if a number is numeric
or not. I thought it would probably be a simple string method but I found
far more contrived solutions like regex matches. Eventually I settled on
monkey patching string with a Numeric? method using Float(self)! = nil
rescue false.

Is there a better way to go about this? If not, can we get something added
to the core?

Thanks for your time,

Brandon

--
Tony Arcieri

I think we need more information, the return values are fixeds? what are
they?

···

--
Posted via http://www.ruby-forum.com/.

A common example:

while new_sock = sock.accept
  Thread.new(new_sock) do |s|
     ... do stuff with 's'
  end
end

If you just use new_sock directly within the thread, then its value may
change before you use it, because if a new incoming connection arrives
the outer loop will reassign a new value to it.

···

--
Posted via http://www.ruby-forum.com/.

Problem all strings will convert to integers.

"fred".to_i => 0
"69skiddoo".to_i => 69
"".to_i => 0

I suspect that these would not be considered numbers.

···

On 27 December 2012 18:50, Jonan Scheffler <jonanscheffler@gmail.com> wrote:

You might be better off to ask yourself why you need the type checking
anyway. If you have a method designed to handle an argument that might be a
string or an integer you might be trying to do two different things.

If you're sure you want the integer you could just to_i the input.

I can't control null returns on certain statements considering it retrieves
data from live devices. If a live device is down it returns null or
similar. There are enough different devices that report different variants
of null that in order to be more flexible, numeric is my most viable
option.

···

On Dec 27, 2012 12:54 PM, "Tony Arcieri" <tony.arcieri@gmail.com> wrote:

Float(string) is your best bet. Why is this inadequate? Are you trying to
decide if a string "looks like a number" but don't want to work with it as
a number after that?

On Thu, Dec 27, 2012 at 10:40 AM, Brandon Weaver <keystonelemur@gmail.com>wrote:

I've found a bit of an annoyance trying to find out if a number is
numeric or not. I thought it would probably be a simple string method but I
found far more contrived solutions like regex matches. Eventually I settled
on monkey patching string with a Numeric? method using Float(self)! = nil
rescue false.

Is there a better way to go about this? If not, can we get something
added to the core?

Thanks for your time,

Brandon

--
Tony Arcieri

Sorry, I wasn't very clear. I was typing most of that from my Phone.

I'm writing scripts for a wireless ISP, and we use several different types
of antennas. They're monitored in several different ways,
SSH/Telnet/SNMP/etc. Annoyingly they all return different values for null,
but they're always string based, so a numeric evaluation will quickly yield
whether the device is working or down. I could write a more correct
solution in the sense that it's less of a hack with individual classes for
every antenna, but the goal is that if we ever get a new type of equipment
that it will take minimal coding to get a framework up and running for it.

The main concept here is making the code as DRY as possible, and to
abstract the testing as far from the hardware as possible so as to give
more general statistics for the entire network. I'm not particularly good
at articulating this one.

One such example is min, max, and avg for multiple fields such as Signal to
Noise, Retransmit, and etc. I used instance_variable_get to dynamically
evaluate fields. There are ways in which I could probably use more of
Enumerator, and I still need to sort that out some more.

···

On Thu, Dec 27, 2012 at 4:13 PM, Damián M. González <lists@ruby-forum.com>wrote:

I think we need more information, the return values are fixeds? what are
they?

--
Posted via http://www.ruby-forum.com/\.

Trust me, I wish there was a cleaner way to handle this instead of this
inelegant hack I have to make.

To clarify, I work at a WISP that has several different brands of antennas.
In order to have an effective and DRY solution, I have to be very abstract.
Unfortunatelly the way null or empty is reported is only consistently a
string, making numeric as clean as I can get.

If anyone has a better idea I would love to hear it. I come from a C
background so I still have some bleeding effects from the transfer.

Sorry, I wasn't very clear. I was typing most of that from my Phone.

I'm writing scripts for a wireless ISP, and we use several different types
of antennas. They're monitored in several different ways,
SSH/Telnet/SNMP/etc. Annoyingly they all return different values for null,
but they're always string based, so a numeric evaluation will quickly yield
whether the device is working or down. I could write a more correct solution
in the sense that it's less of a hack with individual classes for every
antenna, but the goal is that if we ever get a new type of equipment that it
will take minimal coding to get a framework up and running for it.

What's wrong then to use Float() as suggested?

begin
  f = Float(from_device)
  printf "Read value %20.5f\n", f
rescue ArgumentError => e
  # not a float
end

An alternative would be to convert non numeric values to nil - if you
want safe null handling:

f = Float(from_device) rescue nil

One such example is min, max, and avg for multiple fields such as Signal to
Noise, Retransmit, and etc. I used instance_variable_get to dynamically
evaluate fields. There are ways in which I could probably use more of
Enumerator, and I still need to sort that out some more.

You could use Structs and then:

irb(main):001:0> S=Struct.new :a, :b, :c
=> S
irb(main):002:0> S.members
=> [:a, :b, :c]
irb(main):003:0> S.new.members
=> [:a, :b, :c]
irb(main):004:0> s = S.new 1,2,3
=> #<struct S a=1, b=2, c=3>
irb(main):005:0> s.members
=> [:a, :b, :c]
irb(main):006:0> s.each_pair {|k,v| printf "%p=%p\n", k, v}
:a=1
:b=2
:c=3
=> #<struct S a=1, b=2, c=3>

Kind regards

robert

···

On Thu, Dec 27, 2012 at 11:32 PM, Brandon Weaver <keystonelemur@gmail.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Problem all strings will convert to integers.

"fred".to_i => 0
"69skiddoo".to_i => 69
"".to_i => 0

I suspect that these would not be considered numbers.

In these cases, I just double convert i.e.

irb(main):016:0> buffer = 'fred'
=> "fred"
irb(main):017:0> buffer.to_i.to_s == buffer
=> false

And then
irb(main):001:0> buffer = '42'
=> "42"
irb(main):002:0> buffer.to_i.to_s == buffer
=> true

···

--
Posted via http://www.ruby-forum.com/\.

I've already sorted them into classes and objects, so instance variables
are created for every antenna and other such things.

···

On Thu, Dec 27, 2012 at 5:27 PM, Robert Klemme <shortcutter@googlemail.com>wrote:

On Thu, Dec 27, 2012 at 11:32 PM, Brandon Weaver > <keystonelemur@gmail.com> wrote:
> Sorry, I wasn't very clear. I was typing most of that from my Phone.
>
> I'm writing scripts for a wireless ISP, and we use several different
types
> of antennas. They're monitored in several different ways,
> SSH/Telnet/SNMP/etc. Annoyingly they all return different values for
null,
> but they're always string based, so a numeric evaluation will quickly
yield
> whether the device is working or down. I could write a more correct
solution
> in the sense that it's less of a hack with individual classes for every
> antenna, but the goal is that if we ever get a new type of equipment
that it
> will take minimal coding to get a framework up and running for it.

What's wrong then to use Float() as suggested?

begin
  f = Float(from_device)
  printf "Read value %20.5f\n", f
rescue ArgumentError => e
  # not a float
end

An alternative would be to convert non numeric values to nil - if you
want safe null handling:

f = Float(from_device) rescue nil

> One such example is min, max, and avg for multiple fields such as Signal
to
> Noise, Retransmit, and etc. I used instance_variable_get to dynamically
> evaluate fields. There are ways in which I could probably use more of
> Enumerator, and I still need to sort that out some more.

You could use Structs and then:

irb(main):001:0> S=Struct.new :a, :b, :c
=> S
irb(main):002:0> S.members
=> [:a, :b, :c]
irb(main):003:0> S.new.members
=> [:a, :b, :c]
irb(main):004:0> s = S.new 1,2,3
=> #<struct S a=1, b=2, c=3>
irb(main):005:0> s.members
=> [:a, :b, :c]
irb(main):006:0> s.each_pair {|k,v| printf "%p=%p\n", k, v}
:a=1
:b=2
:c=3
=> #<struct S a=1, b=2, c=3>

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

I've seen a similar solution as well. I've just monkey patched string with
the float conversion.

···

On Thu, Dec 27, 2012 at 10:22 PM, Grant Schoep <lists@ruby-forum.com> wrote:

> Problem all strings will convert to integers.
>
> "fred".to_i => 0
> "69skiddoo".to_i => 69
> "".to_i => 0
>
> I suspect that these would not be considered numbers.

In these cases, I just double convert i.e.

irb(main):016:0> buffer = 'fred'
=> "fred"
irb(main):017:0> buffer.to_i.to_s == buffer
=> false

And then
irb(main):001:0> buffer = '42'
=> "42"
irb(main):002:0> buffer.to_i.to_s == buffer
=> true

--
Posted via http://www.ruby-forum.com/\.

In these cases, I just double convert i.e.

irb(main):016:0> buffer = 'fred'
=> "fred"
irb(main):017:0> buffer.to_i.to_s == buffer
=> false

Have to say that that's very cleaver. Very good solution.

···

--
Posted via http://www.ruby-forum.com/\.

Sorry to disagree. There are more clever solutions:

Use an Integer and deal with the exception.

1. immediately

irb(main):001:0> buffer = 'fred'
=> "fred"
irb(main):002:0> i = Integer(buffer)
ArgumentError: invalid value for Integer(): "fred"
        from (irb):2:in `Integer'
        from (irb):2
        from /usr/bin/irb:12:in `<main>'
irb(main):003:0> begin; i = Integer(buffer); puts "int"; rescue
ArgumentError; puts "no int"; end
no int
=> nil

2. by converting the value to nil if it is not a number

irb(main):004:0> j = Integer(buffer) rescue nil
=> nil
irb(main):005:0> if j; puts "int"; else puts "no int"; end
no int
=> nil

Kind regards

robert

···

On Fri, Dec 28, 2012 at 5:41 AM, Damián M. González <lists@ruby-forum.com> wrote:

In these cases, I just double convert i.e.

irb(main):016:0> buffer = 'fred'
=> "fred"
irb(main):017:0> buffer.to_i.to_s == buffer
=> false

Have to say that that's very cleaver. Very good solution.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

The more I think about it the more I do believe it is responsibility
of the "driver" (i.e. the bit that fetches the data) to return _proper
data_. In this case it would mean: do not return numbers as strings.
If values are invalid return a special value for that; this value
could be nil or one or more symbols depending on how many states need
to be represented.

The using code should expect data properly typed so it can do its business.

Another thought: if you create instance variables on the fly for
sensors then a Hash is probably a better alternative. You could use a
specific class as values which encapsulates the data along with meta
data (valid, available, taken at...). Example

SensorData = Struct.new :name, :value, :taken_at do
  def valid?
    value # nil is invalid
  end
end

Kind regards

robert

···

On Fri, Dec 28, 2012 at 1:00 AM, Brandon Weaver <keystonelemur@gmail.com> wrote:

I've already sorted them into classes and objects, so instance variables are
created for every antenna and other such things.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

The more I think about it the more I do believe it is responsibility
of the "driver" (i.e. the bit that fetches the data) to return _proper
data_. In this case it would mean: do not return numbers as strings.
If values are invalid return a special value for that; this value
could be nil or one or more symbols depending on how many states need
to be represented.

The using code should expect data properly typed so it can do its
business.

Yes that ensure a proper work, but he says that at any time can enter a
new antenna, and he wants to quickly put it working, so what we know is
that all the null values are returned as strings. Perhaps just the null
values are always returned as strings, the others values meaby are
returned as Fixnums, so he wants to handle strings.

···

--
Posted via http://www.ruby-forum.com/\.

The more I think about it the more I do believe it is responsibility
of the "driver" (i.e. the bit that fetches the data) to return _proper
data_. In this case it would mean: do not return numbers as strings.
If values are invalid return a special value for that; this value
could be nil or one or more symbols depending on how many states need
to be represented.

The using code should expect data properly typed so it can do its
business.

Yes that ensure a proper work, but he says that at any time can enter a
new antenna, and he wants to quickly put it working,

And where is the problem with my approach? Does it prevent getting
new devices to work quickly?

so what we know is
that all the null values are returned as strings. Perhaps just the null
values are always returned as strings, the others values meaby are
returned as Fixnums, so he wants to handle strings.

I'd rather not speculate but hear Brandon's comment on this. Also,
even if what you say is true it still does not prevent the "driver"
layer to convert "null" strings into nil or something other meaningful
value.

Cheers

robert

···

On Fri, Dec 28, 2012 at 2:01 PM, Damián M. González <lists@ruby-forum.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

It uses ssh and SNMP to retrieve data. They return different strings, all
some variation of null, if the antenna is unreachable from the Au. I
decided to opt out of a multi conditional approach to every possible
variation of the word null.

···

On Dec 28, 2012 8:13 AM, "Robert Klemme" <shortcutter@googlemail.com> wrote:

On Fri, Dec 28, 2012 at 2:01 PM, Damián M. González > <lists@ruby-forum.com> wrote:
>> The more I think about it the more I do believe it is responsibility
>> of the "driver" (i.e. the bit that fetches the data) to return _proper
>> data_. In this case it would mean: do not return numbers as strings.
>> If values are invalid return a special value for that; this value
>> could be nil or one or more symbols depending on how many states need
>> to be represented.
>>
>> The using code should expect data properly typed so it can do its
>> business.
>
> Yes that ensure a proper work, but he says that at any time can enter a
> new antenna, and he wants to quickly put it working,

And where is the problem with my approach? Does it prevent getting
new devices to work quickly?

> so what we know is
> that all the null values are returned as strings. Perhaps just the null
> values are always returned as strings, the others values meaby are
> returned as Fixnums, so he wants to handle strings.

I'd rather not speculate but hear Brandon's comment on this. Also,
even if what you say is true it still does not prevent the "driver"
layer to convert "null" strings into nil or something other meaningful
value.

Cheers

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

The world at large really needs to discover YAML.