unknown 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8a0d9af42a8cc29ebd2ee7c2d7c9bbe5e4ec87b6
4
+ data.tar.gz: db5fec80667071a7d564ed8d2ee7ecb0bfd12c30
5
+ SHA512:
6
+ metadata.gz: fcba3d4796d3f42ece4c9d2feeb34fd5e92169a10495c73dddc49347a24e20f1d9ce473eaf96b5cb727f64a6f4f1b5523c86c7545be3d0c0b81bf276017d43d2
7
+ data.tar.gz: c5766b1e3b32ce524d220acb7aab25a4b0f8dce7a2d95e087c96a105d0706324fcdc520e1e7fd9bcbd929e223cb4b3dc527e648fc2fcda505cd30af8dcf6b773
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.1.2
5
+ - 2.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in unknown.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,18 @@
1
+ # vim: set filetype=ruby
2
+ guard :rspec, cmd: "bundle exec rspec" do
3
+ require "guard/rspec/dsl"
4
+ dsl = Guard::RSpec::Dsl.new(self)
5
+
6
+ # Feel free to open issues for suggestions and improvements
7
+
8
+ # RSpec files
9
+ rspec = dsl.rspec
10
+ watch(rspec.spec_helper) { rspec.spec_dir }
11
+ watch(rspec.spec_support) { rspec.spec_dir }
12
+ watch(rspec.spec_files)
13
+
14
+ # Ruby files
15
+ ruby = dsl.ruby
16
+ dsl.watch_spec_files_for(ruby.lib_files)
17
+
18
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Kevin Olbrich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # Unknown
2
+
3
+ Unknown is a class representing a Numeric that is unknown. By using
4
+ this class to represent unknown values instead of nil it is possible to
5
+ avoid doing nil checks in your functions.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'unknown'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install unknown
22
+
23
+ ## Usage
24
+
25
+ Before using Unknown
26
+
27
+ # nil checking of arguments
28
+ def population(a,k,t)
29
+ fail "a is missing" unless a
30
+ fail "k is missing" unless k
31
+ fail "t is missing" unless t
32
+ a*Math.exp(-k*t)
33
+ end
34
+
35
+ population(20, 30, nil) #=> Exception "t is missing"
36
+
37
+ #
38
+
39
+
40
+ After using Unknown
41
+
42
+ require 'unknown'
43
+
44
+ def population(a=Unknown,k=Unknown,t=Unknown)
45
+ a*Math.exp(-k*t)
46
+ end
47
+
48
+ population(20,30,Unknown) # => Unknown
49
+
50
+
51
+ ## Development
52
+
53
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
54
+
55
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
56
+
57
+ ## Contributing
58
+
59
+ 1. Fork it ( https://github.com/[my-github-username]/unknown/fork )
60
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
61
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
62
+ 4. Push to the branch (`git push origin my-new-feature`)
63
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ rescue LoadError
7
+ end
8
+
9
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "unknown"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/bmi.rb ADDED
@@ -0,0 +1,57 @@
1
+ class Patient
2
+ attr_accessor :height
3
+ attr_accessor :weight
4
+ attr_accessor :name
5
+ def initialize(_name, _height, _weight)
6
+ @name = _name
7
+ @height = _height
8
+ @weight = _weight
9
+ # this might also raise an exception if height or weight were required
10
+ # fail ArgumentError, 'height is required' unless height
11
+ end
12
+
13
+ # Note the need for nil checks in the event that the height or weight is unknown
14
+ def bmi
15
+ return unless height && weight
16
+ ( weight.to_f / ( (height.to_f)**2 ) ) * 703.0
17
+ end
18
+
19
+ # Note the need for nil checks in the event that the height or weight is unknown
20
+ def bsa
21
+ return unless height && weight
22
+ Math.sqrt( height.to_f * weight.to_f / 3131.0 )
23
+ end
24
+ end
25
+
26
+ class PatientWithDefaults < Patient
27
+ def initialize(_name, _height = nil, _weight = nil)
28
+ @name = _name
29
+ @height = _height || 72
30
+ @weight = _weight || 200
31
+ end
32
+ end
33
+
34
+ # Presentation
35
+ # nils in the initializers for unknown values. A common convention, but
36
+ # not as intention revealing as it could be
37
+ patients = [
38
+ Patient.new('Bob', 72, 200),
39
+ Patient.new('Tom', 65, nil),
40
+ Patient.new('Sam', nil, 225),
41
+ Patient.new('Jim', nil, nil),
42
+ PatientWithDefaults.new('Terry')
43
+ ]
44
+
45
+ # Note the need for nil checks here to handle cases where values are unknown
46
+ puts
47
+ puts "Name Height (in) Weight (lbs) BMI BSA"
48
+ puts "==============================================================================="
49
+ patients.each do |patient|
50
+ puts [
51
+ "#{patient.name}",
52
+ "#{patient.height || "Unknown" }",
53
+ "#{patient.weight || "Unknown" }",
54
+ "#{ patient.bmi ? sprintf('%0.2f',patient.bmi) : "Unknown" }",
55
+ "#{ patient.bsa ? sprintf('%0.2f',patient.bsa) : "Unknown" }"
56
+ ].map { |x| x.ljust(15) }.join
57
+ end
data/bmi_unknown.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'unknown'
2
+
3
+ class Patient
4
+ attr_accessor :height
5
+ attr_accessor :weight
6
+ attr_accessor :name
7
+ def initialize(_name, _height = Unknown, _weight = Unknown)
8
+ @name = _name
9
+ # It's pretty obvious from these initializers when they are Unknown and when they aren't
10
+ @height = _height || Unknown
11
+ @weight = _weight || Unknown
12
+ # if height & weight are required then throw an exception
13
+ # fail ArgumentError, 'height is required' if _height.unknown?
14
+ end
15
+
16
+ # No nil checks for height and weight, just the relevant formula
17
+ def bmi
18
+ ( weight.to_f / ( (height.to_f)**2 ) ) * 703.0
19
+ end
20
+
21
+ # No nil checks for height and weight, just the relevant formula
22
+ def bsa
23
+ Math.sqrt( height.to_f * weight.to_f / 3131.0 )
24
+ end
25
+ end
26
+
27
+ class PatientWithDefaults < Patient
28
+ def initialize(_name, _height = Unknown, _weight = Unknown)
29
+ @name = _name
30
+ @height = _height.if_unknown? { 72 }
31
+ @weight = _weight.if_unknown? { 200 }
32
+ end
33
+ end
34
+
35
+ # Data
36
+ patients = [
37
+ Patient.new('Bob', 72, 200),
38
+ Patient.new('Tom', 65, Unknown),
39
+ Patient.new('Sam', Unknown, 225),
40
+ Patient.new('Jim', Unknown, Unknown),
41
+ PatientWithDefaults.new('Terry')
42
+ ]
43
+
44
+ # Presentation
45
+ # Note that it is not necessary to do any nil checking in the output.
46
+ puts
47
+ puts "Name Height (in) Weight (lbs) BMI BSA"
48
+ puts "==============================================================================="
49
+ patients.each do |patient|
50
+ puts [
51
+ "#{patient.name}",
52
+ "#{patient.height}",
53
+ "#{patient.weight}",
54
+ "#{patient.bmi.if_known? {|x| sprintf('%0.2f', x)}}",
55
+ "#{patient.bsa.if_known? {|x| sprintf('%0.2f', x)}}"
56
+ ].map { |x| x.ljust(15) }.join
57
+ end
data/lib/unknown.rb ADDED
@@ -0,0 +1,86 @@
1
+ require "unknown/version"
2
+ require 'unknown/extensions/numeric'
3
+ require 'unknown/extensions/complex'
4
+ require 'unknown/extensions/math'
5
+
6
+ # A numeric class that encapsulates the idea of an unknown number.
7
+ # Any math operation that includes an unknown is also Unknown
8
+ # this allows complex math functions to run without throwing execptions
9
+ # but the end result will be unknown if any of the values in the formula are also Unknown
10
+ class UnknownClass < Numeric
11
+ def unknown?
12
+ true
13
+ end
14
+
15
+ def if_unknown?(value=nil, &block)
16
+ if block_given?
17
+ yield
18
+ else
19
+ value
20
+ end
21
+ end
22
+
23
+ def if_known?(&block)
24
+ self
25
+ end
26
+
27
+ def inspect(*_)
28
+ "Unknown"
29
+ end
30
+ alias_method :to_s, :inspect
31
+
32
+ def coerce(_)
33
+ [self, self]
34
+ end
35
+
36
+ def round(_=nil)
37
+ self
38
+ end
39
+
40
+ def divmod(_)
41
+ [self, self]
42
+ end
43
+
44
+ # arity 1
45
+ %w(* / + - ** fdiv modulo quo remainder).each do |meth|
46
+ define_method(meth.to_sym) do |_|
47
+ self
48
+ end
49
+ end
50
+
51
+ # arity 0
52
+ %w(
53
+ +@
54
+ -@
55
+ abs
56
+ abs2
57
+ angle
58
+ arg
59
+ ceil
60
+ conj
61
+ conjugate
62
+ denominator
63
+ floor
64
+ i
65
+ imag
66
+ imaginary
67
+ magnitude
68
+ numerator
69
+ phase
70
+ to_c
71
+ to_f
72
+ to_i
73
+ to_r
74
+ truncate
75
+ ).each do |meth|
76
+ define_method(meth.to_sym) do
77
+ self
78
+ end
79
+ end
80
+
81
+ def <=>(_)
82
+ nil
83
+ end
84
+ end
85
+
86
+ Unknown = ::UnknownClass.new
@@ -0,0 +1,5 @@
1
+ class Complex < Numeric
2
+ def unknown?
3
+ real.unknown? || imaginary.unknown?
4
+ end
5
+ end
@@ -0,0 +1,49 @@
1
+ module Math
2
+ # arity 1
3
+ %w(
4
+ acos
5
+ acosh
6
+ asin
7
+ asinh
8
+ atan
9
+ atanh
10
+ cbrt
11
+ cos
12
+ cosh
13
+ erf
14
+ erfc
15
+ exp
16
+ gamma
17
+ log
18
+ log2
19
+ sin
20
+ sinh
21
+ sqrt
22
+ tan
23
+ tanh
24
+ ).each do |original_method|
25
+ method_without_unknown = "#{original_method}_without_unknown".to_sym
26
+ alias_method(method_without_unknown, original_method.to_sym)
27
+ define_method(original_method.to_sym) do |arg|
28
+ return Unknown if arg.unknown?
29
+ send(method_without_unknown, arg)
30
+ end
31
+ module_function method_without_unknown
32
+ module_function original_method.to_sym
33
+ end
34
+
35
+ # arity 2
36
+ %w(
37
+ hypot
38
+ atan2
39
+ ).each do |original_method|
40
+ method_without_unknown = "#{original_method}_without_unknown".to_sym
41
+ alias_method method_without_unknown, original_method.to_sym
42
+ define_method(original_method.to_sym) do |arg1,arg2|
43
+ return Unknown if arg1.unknown? || arg2.unknown?
44
+ send(method_without_unknown, arg1, arg2)
45
+ end
46
+ module_function method_without_unknown
47
+ module_function original_method.to_sym
48
+ end
49
+ end
@@ -0,0 +1,18 @@
1
+ class Numeric
2
+ def unknown?
3
+ false
4
+ end
5
+
6
+ def known?
7
+ !unknown?
8
+ end
9
+
10
+ def if_unknown?
11
+ self
12
+ end
13
+
14
+ def if_known?(&block)
15
+ yield self
16
+ end
17
+
18
+ end
@@ -0,0 +1,3 @@
1
+ class UnknownClass < Numeric
2
+ VERSION = "0.1.0"
3
+ end
data/unknown.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'unknown/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "unknown"
8
+ spec.version = UnknownClass::VERSION
9
+ spec.authors = ["Kevin Olbrich"]
10
+ spec.email = ["kevin.olbrich@gmail.com"]
11
+
12
+ spec.summary = %q{Handles doing math with unknown values}
13
+ spec.description = %q{Handles doing math with unknown values so you can avoid doing nil checks on formulas}
14
+ spec.homepage = "https://github.com/olbrich/unknown"
15
+
16
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
+ # delete this section to allow pushing this gem to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "guard-rspec"
32
+ spec.add_development_dependency "codeclimate-test-reporter"
33
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unknown
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Olbrich
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: codeclimate-test-reporter
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Handles doing math with unknown values so you can avoid doing nil checks
70
+ on formulas
71
+ email:
72
+ - kevin.olbrich@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - ".travis.yml"
80
+ - Gemfile
81
+ - Guardfile
82
+ - LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - bin/console
86
+ - bin/setup
87
+ - bmi.rb
88
+ - bmi_unknown.rb
89
+ - lib/unknown.rb
90
+ - lib/unknown/extensions/complex.rb
91
+ - lib/unknown/extensions/math.rb
92
+ - lib/unknown/extensions/numeric.rb
93
+ - lib/unknown/version.rb
94
+ - unknown.gemspec
95
+ homepage: https://github.com/olbrich/unknown
96
+ licenses: []
97
+ metadata:
98
+ allowed_push_host: https://rubygems.org
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.2.2
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Handles doing math with unknown values
119
+ test_files: []
120
+ has_rdoc: