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
on 2012-12-27 19:40
on 2012-12-27 19:50
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 2012-12-27 19:54
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 2012-12-27 19:57
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. > > 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 2012-12-27 19:58
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 2012-12-27 20:11
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.
on 2012-12-27 23:33
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 2012-12-28 00:35
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
on 2012-12-28 01:05
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
on 2012-12-28 05:22
> 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
on 2012-12-28 05:34
I've seen a similar solution as well. I've just monkey patched string with the float conversion.
on 2012-12-28 05:41
> 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.
on 2012-12-28 12:36
On Fri, Dec 28, 2012 at 5:41 AM, Damin M. Gonzlez <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. 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 2012-12-28 12:41
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. 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 2012-12-28 14:01
> 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.
on 2012-12-28 15:13
On Fri, Dec 28, 2012 at 2:01 PM, Damin M. Gonzlez <lists@ruby-forum.com> wrote: > 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 2012-12-28 18:11
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 2013-01-02 09:56
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.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.