Best way to call Integer on temporary?

I like to use Float, Integer and String to typecast data from user. It
raises an exception if the value was invalid for some reason.

However, it doesn't easily support optional values, e.g. Integer(nil)
fails too. So, I end up writing code like:

result = (tmp = x[:foo]) ? Integer(tmp) : nil

But that seems really ugly.

Is there a better way without just writing my own wrapper all the
time? It would be nice to write something like x[:foo]&.to_i, but that
doesn't raise an exception for invalid input, only returns 0 which
makes it hard to tell the difference between invalid input and "0".

Thanks
Samuel

It seems like you might have reached the level of complexity which might justify a separate function: say, validate_int(foo) which either returns an integer or raises an exception. (Or, which might be better, throws a signal; arguably a validation fail isn't actually an exception in your application, but an expected event.)

Don't think of it of having to write a wrapper each time. Think of it as making your code clearer, easier to debug. After all, which is better ---

    result = (tmp = x[:foo]) ? Integer(tmp) : nil

or:

    result = validate_int x[:foo]

?

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer&gt;

···

-----Original Message-----
From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of Samuel
Williams
Sent: 22 February 2017 1:28 am
To: ruby-talk ML
Subject: Best way to call Integer on temporary?

I like to use Float, Integer and String to typecast data from user. It
raises an exception if the value was invalid for some reason.

However, it doesn't easily support optional values, e.g. Integer(nil)
fails too. So, I end up writing code like:

result = (tmp = x[:foo]) ? Integer(tmp) : nil

But that seems really ugly.

Is there a better way without just writing my own wrapper all the
time? It would be nice to write something like x[:foo]&.to_i, but that
doesn't raise an exception for invalid input, only returns 0 which
makes it hard to tell the difference between invalid input and "0".

Perhaps something like Integer? which would pass through nil.

From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of

Samuel

Williams
Sent: 22 February 2017 1:28 am
To: ruby-talk ML
Subject: Best way to call Integer on temporary?

I like to use Float, Integer and String to typecast data from user. It
raises an exception if the value was invalid for some reason.

However, it doesn't easily support optional values, e.g. Integer(nil)
fails too. So, I end up writing code like:

result = (tmp = x[:foo]) ? Integer(tmp) : nil

But that seems really ugly.

Is there a better way without just writing my own wrapper all the
time? It would be nice to write something like x[:foo]&.to_i, but that
doesn't raise an exception for invalid input, only returns 0 which
makes it hard to tell the difference between invalid input and "0".

It seems like you might have reached the level of complexity which might
justify a separate function: say, validate_int(foo) which either returns an
integer or raises an exception. (Or, which might be better, throws a
signal; arguably a validation fail isn't actually an exception in your
application, but an expected event.)

Don't think of it of having to write a wrapper each time. Think of it as
making your code clearer, easier to debug. After all, which is better ---

    result = (tmp = x[:foo]) ? Integer(tmp) : nil

or:

    result = validate_int x[:foo]

?

Yeah, if it's just the three functions, and you're reusing them enough, it
makes sense to wrap them up nicely.

If it were just a one off, and if #self took a block, you could do this:

    x[:foo]&.self{|i| Integer(i) }

Right now you could get there with #tap and a hack:

    x[:foo]&.tap{|i| break Integer(i) }

(I think - untested because I'm on my phone)

Cheers

···

On 22 Feb 2017 18:36, "Andy Jones" <Andy.Jones@jameshall.co.uk> wrote:

-----Original Message-----

Since you will often replace the value with a default value anyway, you can do

foo = Integer(x[:foo] || 0)

or more explicitly

FOO_DEFAULT = 0
# ...
foo = Integer(x[:foo] || FOO_DEFAULT)

Kind regards

robert

···

On Wed, Feb 22, 2017 at 2:28 AM, Samuel Williams <space.ship.traveller@gmail.com> wrote:

I like to use Float, Integer and String to typecast data from user. It
raises an exception if the value was invalid for some reason.

However, it doesn't easily support optional values, e.g. Integer(nil)
fails too. So, I end up writing code like:

result = (tmp = x[:foo]) ? Integer(tmp) : nil

But that seems really ugly.

Is there a better way without just writing my own wrapper all the
time? It would be nice to write something like x[:foo]&.to_i, but that
doesn't raise an exception for invalid input, only returns 0 which
makes it hard to tell the difference between invalid input and "0".

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/

if you like exceptions, then you also like rescuing.

you may start with the shorter modifier form of rescuing,
eg,

result = Integer foo rescue bar

kind regards
--botp

···

On Wed, Feb 22, 2017 at 9:28 AM, Samuel Williams <space.ship.traveller@gmail.com> wrote:

I like to use Float, Integer and String to typecast data from user. It
raises an exception if the value was invalid for some reason.

To quote Brian Kernighan, "Everyone knows that debugging is twice as hard
as writing a program in the first place. So if you're as clever as you can
be when you write it, how will you ever debug it?"

Leam

···

On Wed, Feb 22, 2017 at 6:41 AM, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

>>>>
Yeah, if it's just the three functions, and you're reusing them enough, it
makes sense to wrap them up nicely.
<<<<

From my point of view it makes sense to do it even if you aren't reusing
them much.

I know I will have to look at this code six months later and make sense of
it. I won't remember a lot about the code at that point.

Anything I can do now to help out six-months-later me (bearing in mind
that debugging is *much* harder than coding) is a win.

--
Mind on a Mission <http://leamhall.blogspot.com/&gt;

Yeah, if it's just the three functions, and you're reusing them enough, it makes sense to wrap them up nicely.

I know I will have to look at this code six months later and make sense of it. I won't remember a lot about the code at that point.

Anything I can do now to help out six-months-later me (bearing in mind that debugging is *much* harder than coding) is a win.

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer&gt;

···

From my point of view it makes sense to do it even if you aren't reusing them much.

Interesting discussion, thanks for the ideas.

I don't think that cuts it because you still want to see an exception
if the input is ill formed. At least I would.

Kind regards

robert

···

On Sun, Feb 26, 2017 at 8:25 AM, botp <botpena@gmail.com> wrote:

On Wed, Feb 22, 2017 at 9:28 AM, Samuel Williams > <space.ship.traveller@gmail.com> wrote:

I like to use Float, Integer and String to typecast data from user. It
raises an exception if the value was invalid for some reason.

if you like exceptions, then you also like rescuing.

you may start with the shorter modifier form of rescuing,
eg,

result = Integer foo rescue bar

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/

Thinking a bit more about this there is a different approach: since
OptionParser does support type safe conversions you could also do this
during command line argument parsing:

irb(main):009:0> options = {foo: 0}
=> {:foo=>0}
irb(main):010:0> OptionParser.new {|o| o.on("--foo=VAL",
Integer){|v|options[:foo]=v}}.parse %w{--foo 77}
=>
irb(main):011:0> options
=> {:foo=>77}
irb(main):012:0> OptionParser.new {|o| o.on("--foo=VAL",
Integer){|v|options[:foo]=v}}.parse %w{--foo ab}
OptionParser::InvalidArgument: invalid argument: --foo ab
from (irb):12
from /usr/bin/irb:11:in `<main>'

Kind regards

robert

···

On Sun, Feb 26, 2017 at 1:53 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

On Sun, Feb 26, 2017 at 8:25 AM, botp <botpena@gmail.com> wrote:

On Wed, Feb 22, 2017 at 9:28 AM, Samuel Williams >> <space.ship.traveller@gmail.com> wrote:

I like to use Float, Integer and String to typecast data from user. It
raises an exception if the value was invalid for some reason.

if you like exceptions, then you also like rescuing.

you may start with the shorter modifier form of rescuing,
eg,

result = Integer foo rescue bar

I don't think that cuts it because you still want to see an exception
if the input is ill formed. At least I would.

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/