In response to a comment comment from @UriAgassi on my previous answer previous answer, I've devised this variant that distinguishes between retrieving constraints and solving for unknowns.
The naming convention is:
a=
to set a constrainta
to retrieve a constrainta?
to solve for an unknown
It violates the naming convention that ?
marks a predicate, but works well for this domain-specific language.
require 'cmath'
class QuadraticEquation
attr_accessor :a, :b, :c, :x
def x?
positive = (-b + CMath.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
negative = (-b - CMath.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
[positive, negative]
end
def a?
(-b * x - c) / (x ** 2)
end
def b?
(-a * x ** 2 - c) / x
end
def c?
-a * x ** 2 - b * x
end
end
class RightTriangle
attr_accessor :a, :b, :c
def a?
Math.sqrt(c ** 2 - b ** 2)
end
def b?
Math.sqrt(c ** 2 - a ** 2)
end
def c?
Math.sqrt(a ** 2 + b ** 2)
end
alias :hypotenuse :c
alias :hypotenuse= :c=
alias :hypotenuse? :c?
end
One improvement is that the code above isn't littered with @
sigils. However, the main benefit of disambiguating between retrieving constraints and solving for unknowns can be observed in an over-constrained situation:
irb(main):001:0> require 'formula'
=> true
irb(main):002:0> triangle = RightTriangle.new
=> #<RightTriangle:0x007f90b401f800>
irb(main):003:0> triangle.a, triangle.b, triangle.c = 5, 12, 37
=> [5, 12, 37]
irb(main):004:0> triangle.a?
=> 35.0
irb(main):005:0> triangle.c?
=> 13.0
In response to a comment from @UriAgassi on my previous answer, I've devised this variant that distinguishes between retrieving constraints and solving for unknowns.
The naming convention is:
a=
to set a constrainta
to retrieve a constrainta?
to solve for an unknown
It violates the naming convention that ?
marks a predicate, but works well for this domain-specific language.
require 'cmath'
class QuadraticEquation
attr_accessor :a, :b, :c, :x
def x?
positive = (-b + CMath.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
negative = (-b - CMath.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
[positive, negative]
end
def a?
(-b * x - c) / (x ** 2)
end
def b?
(-a * x ** 2 - c) / x
end
def c?
-a * x ** 2 - b * x
end
end
class RightTriangle
attr_accessor :a, :b, :c
def a?
Math.sqrt(c ** 2 - b ** 2)
end
def b?
Math.sqrt(c ** 2 - a ** 2)
end
def c?
Math.sqrt(a ** 2 + b ** 2)
end
alias :hypotenuse :c
alias :hypotenuse= :c=
alias :hypotenuse? :c?
end
One improvement is that the code above isn't littered with @
sigils. However, the main benefit of disambiguating between retrieving constraints and solving for unknowns can be observed in an over-constrained situation:
irb(main):001:0> require 'formula'
=> true
irb(main):002:0> triangle = RightTriangle.new
=> #<RightTriangle:0x007f90b401f800>
irb(main):003:0> triangle.a, triangle.b, triangle.c = 5, 12, 37
=> [5, 12, 37]
irb(main):004:0> triangle.a?
=> 35.0
irb(main):005:0> triangle.c?
=> 13.0
In response to a comment from @UriAgassi on my previous answer, I've devised this variant that distinguishes between retrieving constraints and solving for unknowns.
The naming convention is:
a=
to set a constrainta
to retrieve a constrainta?
to solve for an unknown
It violates the naming convention that ?
marks a predicate, but works well for this domain-specific language.
require 'cmath'
class QuadraticEquation
attr_accessor :a, :b, :c, :x
def x?
positive = (-b + CMath.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
negative = (-b - CMath.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
[positive, negative]
end
def a?
(-b * x - c) / (x ** 2)
end
def b?
(-a * x ** 2 - c) / x
end
def c?
-a * x ** 2 - b * x
end
end
class RightTriangle
attr_accessor :a, :b, :c
def a?
Math.sqrt(c ** 2 - b ** 2)
end
def b?
Math.sqrt(c ** 2 - a ** 2)
end
def c?
Math.sqrt(a ** 2 + b ** 2)
end
alias :hypotenuse :c
alias :hypotenuse= :c=
alias :hypotenuse? :c?
end
One improvement is that the code above isn't littered with @
sigils. However, the main benefit of disambiguating between retrieving constraints and solving for unknowns can be observed in an over-constrained situation:
irb(main):001:0> require 'formula'
=> true
irb(main):002:0> triangle = RightTriangle.new
=> #<RightTriangle:0x007f90b401f800>
irb(main):003:0> triangle.a, triangle.b, triangle.c = 5, 12, 37
=> [5, 12, 37]
irb(main):004:0> triangle.a?
=> 35.0
irb(main):005:0> triangle.c?
=> 13.0
In response to a comment from @UriAgassi on my previous answer, I've devised this variant that distinguishes between retrieving constraints and solving for unknowns.
The naming convention is:
a=
to set a constrainta
to retrieve a constrainta?
to solve for an unknown
It violates the naming convention that ?
marks a predicate, but works well for this domain-specific language.
require 'cmath'
class QuadraticEquation
attr_accessor :a, :b, :c, :x
def x?
positive = (-b + CMath.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
negative = (-b - CMath.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
[positive, negative]
end
def a?
(-b * x - c) / (x ** 2)
end
def b?
(-a * x ** 2 - c) / x
end
def c?
-a * x ** 2 - b * x
end
end
class RightTriangle
attr_accessor :a, :b, :c
def a?
Math.sqrt(c ** 2 - b ** 2)
end
def b?
Math.sqrt(c ** 2 - a ** 2)
end
def c?
Math.sqrt(a ** 2 + b ** 2)
end
alias :hypotenuse :c
alias :hypotenuse= :c=
alias :hypotenuse? :c?
end
One improvement is that the code above isn't littered with @
sigils. However, the main benefit of disambiguating between retrieving constraints and solving for unknowns can be observed in an over-constrained situation:
irb(main):001:0> require 'formula'
=> true
irb(main):002:0> triangle = RightTriangle.new
=> #<RightTriangle:0x007f90b401f800>
irb(main):003:0> triangle.a, triangle.b, triangle.c = 5, 12, 37
=> [5, 12, 37]
irb(main):004:0> triangle.a?
=> 35.0
irb(main):005:0> triangle.c?
=> 13.0