rfunk 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: c539b96a759a551a6d9fbb57f06415dc09d0cb26
4
+ data.tar.gz: b5f8bb018a680fcfff0efcc0b18f9e32f4ba4dd5
5
+ SHA512:
6
+ metadata.gz: 292cf72c0c5f89b49d368453f5183b0063da281ee86531832d07c61183336fb2dae11604a463f4efd19b7671e5e61ec0df9eb2a923152a15d09b6692e9bd82b2
7
+ data.tar.gz: 4b0b4dae55ee2f40a9a9a79f336a3f8cec5711058d55bec443b0be45e3afecde0ac45cb4053800e95e5820918a67d6a35bcf8ac82d6ef436873de71b61ebe33b
@@ -0,0 +1,72 @@
1
+ module RFunk
2
+ module Attribute
3
+ ATTRIBUTES_VARIABLE_NAME = '@attributes'
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ def initialize(options = {})
10
+ attributes = self.class.instance_variable_get(ATTRIBUTES_VARIABLE_NAME)
11
+
12
+ options.each { |key, value|
13
+ raise_not_found(key, attributes)
14
+
15
+ type = attributes[key]
16
+
17
+ raise_expected_type(key, value, type)
18
+
19
+ self.instance_variable_set(variable_name(key), value)
20
+ }
21
+ end
22
+
23
+ module ClassMethods
24
+ def attribute(name, type)
25
+ add_attribute(name, type)
26
+
27
+ self.send :define_method, name do |value = nil|
28
+ if value
29
+ raise_expected_type(name, value, type)
30
+ create_immutable(variable_name(name), value)
31
+ else
32
+ Option(self.instance_variable_get(variable_name(name)))
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def add_attribute(name, type)
40
+ attributes = self.instance_variable_get(ATTRIBUTES_VARIABLE_NAME) || {}
41
+ attributes[name] = type
42
+ self.instance_variable_set(ATTRIBUTES_VARIABLE_NAME, attributes)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def variable_name(name)
49
+ "@#{name}"
50
+ end
51
+
52
+ def create_immutable(variable_name, value)
53
+ self.class.new.tap { |object|
54
+ self.instance_variables.select { |v| v != variable_name }.each { |v|
55
+ previous_value = self.instance_variable_get(v)
56
+ object.instance_variable_set(v, previous_value)
57
+ }
58
+
59
+ object.instance_variable_set(variable_name, value)
60
+ object.deep_freeze
61
+ }
62
+ end
63
+
64
+ def raise_expected_type(name, value, type)
65
+ raise TypeError, "Expected a type of '#{type}' for attribute '#{name}'" unless value.instance_of?(type)
66
+ end
67
+
68
+ def raise_not_found(key, attributes)
69
+ raise RFunk::NotFoundError, "Attribute with name '#{key}' does not exist. The only available attributes are '#{attributes}'" unless attributes.key?(key)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,29 @@
1
+ module RFunk
2
+ def Either(value)
3
+ if lambda?(value)
4
+ either_with_lambda(value)
5
+ else
6
+ either_with_value(value)
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def lambda?(value)
13
+ value.respond_to?(:lambda?) and value.lambda?
14
+ end
15
+
16
+ def either_with_lambda(lambda)
17
+ RFunk::Success(lambda.call)
18
+ rescue => e
19
+ RFunk::Failure(e)
20
+ end
21
+
22
+ def either_with_value(value)
23
+ if value
24
+ RFunk::Success(value)
25
+ else
26
+ RFunk::Failure(value)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ module RFunk
2
+ class Failure < Value
3
+ def success?
4
+ false
5
+ end
6
+
7
+ def failure?
8
+ true
9
+ end
10
+
11
+ def or(value)
12
+ Failure(value)
13
+ end
14
+ end
15
+
16
+ def Failure(value)
17
+ Failure.new(value)
18
+ end
19
+ end
data/lib/rfunk/lazy.rb ADDED
@@ -0,0 +1,25 @@
1
+ module RFunk
2
+ class Lazy
3
+ def initialize(lambda)
4
+ @lambda = lambda
5
+ @created = false
6
+ end
7
+
8
+ def value
9
+ Option(@value ||= lambda.call.tap { self.created = true })
10
+ end
11
+
12
+ def created?
13
+ created
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :lambda
19
+ attr_accessor :created
20
+ end
21
+
22
+ def Lazy(lambda)
23
+ Lazy.new(lambda)
24
+ end
25
+ end
data/lib/rfunk/none.rb ADDED
@@ -0,0 +1,21 @@
1
+ module RFunk
2
+ class None
3
+ include Singleton
4
+
5
+ def value(default = nil)
6
+ Option(default)
7
+ end
8
+
9
+ def or(other)
10
+ Option(other)
11
+ end
12
+
13
+ def method_missing(method, *arguments, &block)
14
+ self
15
+ end
16
+ end
17
+
18
+ def None(value = nil)
19
+ Option(value)
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ module RFunk
2
+ class NotFoundError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,15 @@
1
+ module RFunk
2
+ def Option(value)
3
+ if nothing?(value)
4
+ None.instance
5
+ else
6
+ Some.new(value)
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def nothing?(value)
13
+ value.nil? || (value.respond_to?(:empty?) && value.empty?) || value.is_a?(None)
14
+ end
15
+ end
data/lib/rfunk/some.rb ADDED
@@ -0,0 +1,25 @@
1
+ module RFunk
2
+ class Some
3
+ attr_reader :value
4
+
5
+ def initialize(value)
6
+ @value = value
7
+ end
8
+
9
+ def or(_)
10
+ self
11
+ end
12
+
13
+ def method_missing(method, *arguments, &block)
14
+ Option(value.__send__(method, *arguments, &block))
15
+ end
16
+
17
+ def ==(other)
18
+ other.value == value
19
+ end
20
+ end
21
+
22
+ def Some(value)
23
+ Option(value)
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ module RFunk
2
+ class Success < Value
3
+ def success?
4
+ true
5
+ end
6
+
7
+ def failure?
8
+ false
9
+ end
10
+
11
+ def or(_)
12
+ self
13
+ end
14
+ end
15
+
16
+ def Success(value)
17
+ Success.new(value)
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ module RFunk
2
+ class Value
3
+ def initialize(value)
4
+ @value = value
5
+ end
6
+
7
+ def result
8
+ case value
9
+ when Some, None
10
+ value
11
+ else
12
+ Option(value)
13
+ end
14
+ end
15
+
16
+ def ==(other)
17
+ other.result == result
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :value
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module RFunk
2
+ VERSION = '0.1.0'
3
+ end
data/lib/rfunk.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'singleton'
2
+ require 'ice_nine'
3
+ require 'ice_nine/core_ext/object'
4
+
5
+ require 'rfunk/attribute'
6
+ require 'rfunk/option'
7
+ require 'rfunk/none'
8
+ require 'rfunk/some'
9
+ require 'rfunk/not_found_error'
10
+ require 'rfunk/lazy'
11
+ require 'rfunk/value'
12
+ require 'rfunk/failure'
13
+ require 'rfunk/success'
14
+ require 'rfunk/either'
15
+
16
+ include RFunk
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rfunk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alex Falkowski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ice_nine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.11.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.11.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.1.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 10.1.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-given
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.5.4
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.5.4
55
+ description: See https://github.com/alexfalkowski/rfunk/blob/master/README.md
56
+ email:
57
+ - alexrfalkowski@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - lib/rfunk.rb
63
+ - lib/rfunk/attribute.rb
64
+ - lib/rfunk/either.rb
65
+ - lib/rfunk/failure.rb
66
+ - lib/rfunk/lazy.rb
67
+ - lib/rfunk/none.rb
68
+ - lib/rfunk/not_found_error.rb
69
+ - lib/rfunk/option.rb
70
+ - lib/rfunk/some.rb
71
+ - lib/rfunk/success.rb
72
+ - lib/rfunk/value.rb
73
+ - lib/rfunk/version.rb
74
+ homepage: https://github.com/alexfalkowski/rfunk
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.2.2
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Functional Programming in Ruby
98
+ test_files: []