Patching Float within a scope

I have the need for things like nil + 12.0 to return nil in the way that
some software packages propagate NaN and other oddities.

In my code I have this sort of thing which solves the problem.

class Float
  alias old_plus +
  def +(other); other ? old_plus(other) : other; end
end

class NilClass
  def +(_other); self; end
end

Except that the patch is now permanent and will affect all parts of the
application. If I were to image this I would like to write something like:

# Here nil + 12.0 will throw an exception

magic.do
  alias Float + new_float_plus
  alias NilClass + new_nil_plus

  # This will now run without an exception and output nil
  puts nil + 12.0
end

# Here again nil + 12.0 will throw an exception

Basically I want to patch some classes, like Float and NilClass, run some
code and then revert the patches in the middle of some code.

Any ideas?

I have the need for things like nil + 12.0 to return nil in the way that some software packages propagate NaN and other oddities.

I would make a module method like so:

module Oddities
  extend self

  def sum(*args)
    return nil if args.include? nil
    args.sum
  end
end

Oddities.sum nil, 12.0 => nil
Oddities.sum 10, 12.0, 6 => 28.0

Of course you can name your module whatever you want. You can also do it as a mixin:

class MyClass
  include Oddities

  def some_method
    sum(@a, @b)
  end
end

I have the need for things like nil + 12.0 to return nil in the way that some software packages propagate NaN and other oddities.

[…]

Basically I want to patch some classes, like Float and NilClass, run some code and then revert the patches in the middle of some code.

There is no easy way to do this*, and I think most Ruby people would say that it was inadvisable. You will be fighting the language all the way if you try it.

I generally try to avoid propagating nil all through my code precisely because of the problems it causes. Really you are better off catching that nil value and dealing with it in one place, rather than having to deal with it in all the places it could later turn up.

Here's a weird idea: if you really have a need for this, why not make your own nil class specifically for values that need this functionality? That way you wouldn't have to worry about the rest of ruby being effected by your monkey patching?

[ *_possibly_ refinements might work for you, but I have yet to make them work for me. ]

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

It's still an experimental feature, but refinements sound like what you're
after:

https://ruby-doc.org/core-2.1.1/doc/syntax/refinements_rdoc.html

···

On 27 April 2017 at 14:02, Peter Hickman <peterhickman386@googlemail.com> wrote:

I have the need for things like nil + 12.0 to return nil in the way that
some software packages propagate NaN and other oddities.

In my code I have this sort of thing which solves the problem.

class Float
  alias old_plus +
  def +(other); other ? old_plus(other) : other; end
end

class NilClass
  def +(_other); self; end
end

Except that the patch is now permanent and will affect all parts of the
application. If I were to image this I would like to write something like:

# Here nil + 12.0 will throw an exception

magic.do
  alias Float + new_float_plus
  alias NilClass + new_nil_plus

  # This will now run without an exception and output nil
  puts nil + 12.0
end

# Here again nil + 12.0 will throw an exception

Basically I want to patch some classes, like Float and NilClass, run some
code and then revert the patches in the middle of some code.

Any ideas?

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

I generally try to avoid propagating nil all through my code precisely
because of the problems it causes. Really you are better off catching that
nil value and dealing with it in one place, rather than having to deal with
it in all the places it could later turn up.

The problem with this approach is that the nil needs to propagate through
the equations, bailing on the first exception is not viable - tried it.
Currently I would have to wrap nearly 2,000 calculations in rescue blocks.
Not impossible as the final code comes from a code generator but means that
the code would become totally unreadable (not that 2,000 lines of code are
that easy to read).

Patching Float and NilClass is the cleanest solution so far, the next most
would be to grab the syntax tree and render "nil + 12.0" as "my_add(nil,
12.0)" where my_add is a method that checks the arguments and behaves
accordingly.

Here's a weird idea: if you really have a need for this, why not make your
own nil class specifically for values that need this functionality?

Actually that sounds like a really good idea :slight_smile:

I will give it a go (but will that cope with "12.0 + nil" ?)

···

On 27 April 2017 at 14:14, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

I will give it a go (but will that cope with "12.0 + nil" ?)

See Dan Fitzpatrick’s answer. In short, yes; you can now patch Float etc safe In the knowledge that you are only effecting your own weird nil class.

The only buggeration is that you can’t subclass operators like + in Ruby so you may have to resort to `MyNil.add 12.0`?

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

Why not just guard it?

answer = nil && nil + 12.0

···

On 28 Apr. 2017 12:25 am, "Andy Jones" <Andy.Jones@jameshall.co.uk> wrote:

>>>>

I will give it a go (but will that cope with "12.0 + nil" ?)

<<<<

See Dan Fitzpatrick’s answer. In short, yes; you can now patch Float etc
safe In the knowledge that you are only effecting your own weird nil class.

The only buggeration is that you can’t subclass operators like + in Ruby
so you may have to resort to `MyNil.add 12.0`?

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

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

Why not just guard it?

answer = nil && nil + 12.0

Perhaps I am being dense, but I don’t think that does what you think it does:

    %: irb
    irb(main):001:0> nil && nil + 12.0
    => nil
    irb(main):002:0> nil && 2.0 + 12.0
    => nil

It rather looks as if it returns nil under all circumstances?

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

Probably precedence.

    nil && (nil + 12.0)

?

Cheers

Why not just guard it?

answer = nil && nil + 12.0

Perhaps I am being dense, but I don’t think that does what you think it
does:

    %: irb
    irb(main):001:0> nil && nil + 12.0
    => nil
    irb(main):002:0> nil && 2.0 + 12.0
    => nil

It rather looks as if it returns nil under all circumstances?

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

···

On 5 May 2017 20:48, "Andy Jones" <Andy.Jones@jameshall.co.uk> wrote:

Probably precedence.

    nil && (nil + 12.0)

?

No, the result is the same.

    irb(main):001:0> nil && (nil + 12.0)
    => nil
    irb(main):002:0> nil && (2.0 + 12.0)
    => nil

The problem is that because of short-cut evaluation, if the LHS of the && is nil, the result of the entire expression always going to be nil.

That’s why, when the RHS would result in an error, the error doesn’t happen – because the RHS will *never* happen. Ruby already has the answer to the expression and doesn’t bother looking further.

If this worked then there would have been no need to introduce the lonely operator, &.

···

From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of Matthew Kerwin
Sent: 06 May 2017 00:44
To: ruby-talk ML
Subject: RE: Patching Float within a scope

Probably precedence.

    nil && (nil + 12.0)

?

Cheers

On 5 May 2017 20:48, "Andy Jones" <Andy.Jones@jameshall.co.uk<mailto:Andy.Jones@jameshall.co.uk>> wrote:

Why not just guard it?

answer = nil && nil + 12.0

Perhaps I am being dense, but I don’t think that does what you think it does:

    %: irb
    irb(main):001:0> nil && nil + 12.0
    => nil
    irb(main):002:0> nil && 2.0 + 12.0
    => nil

It rather looks as if it returns nil under all circumstances?

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

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org<mailto:ruby-talk-request@ruby-lang.org>?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

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

nil && 2.0 + 12.0

It should be:

    2.0 && 2.0 + 12.0

···

On 8 May 2017 17:34, "Andy Jones" <Andy.Jones@jameshall.co.uk> wrote:

It should be:
    2.0 && 2.0 + 12.0

Ah! Yes, that works.

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

The intent was to return nil when the first value was nil.
That was the op's issue.
If one of the values was nil, she/he wanted nil.

Nil && anything_else will always return nil, and I will not evaluate the
second clause.

···

On 8 May 2017 6:51 pm, "Andy Jones" <Andy.Jones@jameshall.co.uk> wrote:

>>>>>>>>
It should be:
    2.0 && 2.0 + 12.0
<<<<<<<<<

Ah! Yes, that works.

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

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

The intent was to return nil when the first value was nil.
That was the op's issue.
If one of the values was nil, she/he wanted nil.

Nil && anything_else will always return nil, and I will not evaluate the
second clause.

>>>>>>>>
It should be:
    2.0 && 2.0 + 12.0
<<<<<<<<<

Ah! Yes, that works.

People are intent on not understanding, aren't they.

    def nil_add_12 f
      f && f + 12.0
    end

Generalised to two parameters:

    def nil_add a, b
      a && b && a + b
    end

The only quirk is the way they handle `false`.

This is not tested, but it may be possible to do this, too:

    f&.+ b

Cheers

···

On 15 May 2017 19:32, "Nomadic Sprite" <nomadic.sprite01@gmail.com> wrote:
On 8 May 2017 6:51 pm, "Andy Jones" <Andy.Jones@jameshall.co.uk> wrote:

I feel we are making things too complicated because solutions do not
integrate with Ruby's math well. I think OP should override
NilClass#coerce to proper integrate with Ruby's math handling. Then
implement +, -, * and / for NilClass.

class NilClass
  def coerce; [nil, nil] end

  def +(x) nil end
  def -(x) nil end
  def *(x) nil end
  def /(x) nil end
  def %(x) nil end
  def divmod(x) [nil,nil] end
end

Cheers

robert

PS: unfortunately the blog post I did years ago about extending Ruby's
math with new classes is no longer online. I'll try to dig it up and
make it accessible somewhere else.

···

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