emanlib 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1325271b5892d5c0195b9169f09416790ea4887f680e194afb2445f33bb57b75
4
- data.tar.gz: effa861c1070d969e2ab86287c101ba90bcd52ad9f82cceb87616d79f3b5a554
3
+ metadata.gz: 7c865695d10014ad5b2b967418ec8e4ea65165e9549590f7380c4f21e27b50b0
4
+ data.tar.gz: 00dda6a97a260530b29a932d883377b9f8877820d15b5605bce7582cd422ac72
5
5
  SHA512:
6
- metadata.gz: 2a5248da79b6d73c42c62932c9a2473d10dee603aa9c40ba880cbe708f5ae450d1fa0861805c507051fa5dd3d777031dbfecd6a2120ac0fe688bc5743ee0eaf5
7
- data.tar.gz: 77a89f7f87e7003134b581f272c4892f61c3cc861371cc7758b21a022463caa8468064b16adafd88b0d70f7b0bf1d431290b90bfe2dda22c16d6ff619d3d0389
6
+ metadata.gz: fc5e5219826053c84b0e007cf3e59dc5f72d6f483384ed5515f7938b5c3efb9fab39e77109adafe5b18a58fe17c65913d8951a4b4478b27445a93451a9f79851
7
+ data.tar.gz: bf1123ccc076eaa6c657c28fbc47aff2c4f0e23a749625b02ec33433e7605b5e9262fcd0ff3bdf43e67c56e026a5c75c01d881f938c7517923f22024efe4283e
data/lib/emanlib.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require_relative "patch/define"
2
+ require_relative "patch/enum"
2
3
  require_relative "patch/foobar"
3
4
  require_relative "patch/lambda"
4
5
 
@@ -6,10 +7,10 @@ module EmanLib
6
7
  # The identity Lambda object (`_`).
7
8
  # Store in a short variable, and use it as a building block for anonymous functions.
8
9
  #
9
- # _ = EmanLib.LAMBDA
10
+ # _ = EmanLib._
10
11
  # [1, 2, 3].map(&_.succ) => [2, 3, 4]
11
12
  # [[1, 2], [3, 4]].map(&(_ + _).lift) => [3, 7]
12
- LAMBDA = Lambda.new
13
+ _ = Lambda.new
13
14
 
14
15
  # Helper method to create definitions.
15
16
  # A convenient shorthand for `Object.new.define(...)`.
@@ -21,7 +22,11 @@ module EmanLib
21
22
  # @see [Object#define]
22
23
  #
23
24
  # @example
24
- # point = let(x: 10, y: 20)
25
+ # person = let(name: "Rio", age: 37)
26
+ # puts person.name # => "Rio"
27
+ # puts person.age # => 37
28
+ #
29
+ # point = let **{x: 10, y: 20}
25
30
  # puts point.x # => 10
26
31
  #
27
32
  # settings = let do
@@ -31,22 +36,20 @@ module EmanLib
31
36
  # end
32
37
  # puts settings.theme # => "dark"
33
38
  #
34
- # complex_data = let([[:id, "item1"]], name: "Test Item") do
39
+ # complex_data = let([[:id, 42]], name: "Xed") do
35
40
  # details = { color: "red", size: "large" }
36
- # binding
41
+ # binding # Required
37
42
  # end
38
43
  #
39
- # puts complex_data.id # => "item1"
40
- # puts complex_data.name # => "Test Item"
44
+ # puts complex_data.id # => 42
45
+ # puts complex_data.name # => "Xed"
41
46
  # puts complex_data.details.color # => "red"
42
47
  def let(*args, &block)
43
48
  Object.new.define(*args, &block)
44
49
  end
45
50
 
46
- module_function :let
47
-
48
51
  # Support for using a `_` as the second operand with operators.
49
- # WARN: This method will MODIFY the standard library classes.
52
+ # WARN: This method WILL MODIFY the standard library classes.
50
53
  # In particular, the operators: `- * / % ** & | ^ << >> <=> == === != > < >= <=`
51
54
  # in the classes: `Integer, Float, Rational, Complex, Array, String, Hash, Range, Set`
52
55
  def support_lambda
@@ -69,5 +72,5 @@ module EmanLib
69
72
  end
70
73
  end
71
74
 
72
- module_function :support_lambda
75
+ module_function :let, :support_lambda
73
76
  end
data/lib/patch/enum.rb ADDED
@@ -0,0 +1,120 @@
1
+ module EmanLib
2
+ # The Enum module provides a factory method `[]` to dynamically create
3
+ # simple, lightweight enum-like classes. These classes allow defining a set of
4
+ # named constants with associated numeric values.
5
+ #
6
+ # Enums are defined by passing symbols, strings, or hashes to the `[]` method.
7
+ #
8
+ # Usage examples:
9
+ # OS = Enum[:Arch, :BSD] # OS.Arch => 0, OS.BSD => 1
10
+ # Bool = Enum[nil: 1, :t 10] # Bool.nil => 1, Bool.t => 10
11
+ # Way = Enum["↑", { ↓: 50 }, :→ ] # Way.↑ => 0, Way.↓ => 50, Way.→ => 51
12
+ # Pet = Enum[:Dog, :Cat] { |v| 0.5 * v } # Pet.Dog => 0.0, Pet.Cat => 0.5
13
+ #
14
+ # The generated enum class provides:
15
+ # * Class methods to access each constant's value (e.g., `Lvl.MID`).
16
+ # * An `each` class method to iterate over value-name pairs.
17
+ # * A `to_h` class method to get a hash of name-value pairs.
18
+ # * A `consts` class method to get an array of constant names (as symbols).
19
+ # * A `values` class method to get an array of constant values.
20
+ module Enum
21
+ def self.[](*args, &block)
22
+ # At least one argument should be provided
23
+ raise ArgumentError, "Enums must have at least one constant" if args.empty?
24
+
25
+ # Initialize tracking variables
26
+ pairs = {}
27
+ current = 0
28
+
29
+ args.flatten!(1)
30
+
31
+ # Process all arguments to extract name-value pairs
32
+ args.each do |arg|
33
+ current = case arg
34
+ when Symbol, String
35
+ # Single enum value - assign current value and increment
36
+ pairs[arg.to_sym] = current
37
+ current + 1
38
+ when Hash
39
+ # Hash with explicit key-value mapping
40
+ arg.each do |key, value|
41
+ unless key.is_a?(Symbol) || key.is_a?(String)
42
+ raise ArgumentError, "Enum names must be Symbol|String: #{key.inspect}"
43
+ end
44
+ raise ArgumentError, "Enum values must be Numeric: #{value.inspect}" unless value.is_a?(Numeric)
45
+ pairs[key.to_sym] = value
46
+ current = value + 1
47
+ end
48
+
49
+ current
50
+ else
51
+ raise ArgumentError, "Invalid enum argument: #{arg.inspect}"
52
+ end
53
+ end
54
+
55
+ # Apply block transformation if provided
56
+ if block_given?
57
+ values = Set.new
58
+ pairs.each do |name, value|
59
+ result = block.call(value, name)
60
+
61
+ # Make sure block result is Numeric
62
+ unless result.is_a?(Numeric)
63
+ raise ArgumentError, "Block must return a Numeric, got #{result.class}: #{result.inspect}"
64
+ end
65
+
66
+ # Check that result is unique
67
+ if values.include?(result)
68
+ raise ArgumentError, "Block must return unique values, duplicate: #{result}"
69
+ end
70
+
71
+ values.add(result)
72
+ pairs[name] = result
73
+ end
74
+ end
75
+
76
+ # Create enum class and include this module
77
+ klass = Class.new
78
+ klass.include(Enum)
79
+
80
+ # Store enums data for instance methods
81
+ klass.instance_variable_set(:@pairs, pairs.freeze)
82
+
83
+ # Define getter methods for each constant
84
+ pairs.each do |name, value|
85
+ begin
86
+ klass.define_singleton_method(name) { value }
87
+ rescue => e
88
+ raise ArgumentError, "Invalid const name '#{name}': #{e.message}"
89
+ end
90
+ end
91
+
92
+ klass.define_method(:initialize) do
93
+ raise RuntimeError, "Enums are not meant to be instantiated"
94
+ end
95
+
96
+ # Define utility methods directly on the class
97
+ klass.define_singleton_method(:to_h) do
98
+ @pairs.dup
99
+ end
100
+
101
+ klass.define_singleton_method(:consts) do
102
+ @pairs.keys
103
+ end
104
+
105
+ klass.define_singleton_method(:values) do
106
+ @pairs.values
107
+ end
108
+
109
+ klass.define_singleton_method(:each) do |&block|
110
+ return enum_for(:each) unless block
111
+
112
+ @pairs.each do |name, value|
113
+ block.call(value, name)
114
+ end
115
+ end
116
+
117
+ klass
118
+ end
119
+ end
120
+ end
data/lib/patch/foobar.rb CHANGED
@@ -121,22 +121,24 @@ class Object
121
121
  end
122
122
 
123
123
  # Asserts a condition about `self`.
124
- # If a block is given, it asserts that the block, when called with `self`, returns a truthy value.
124
+ # If a block is given, it asserts that the block returns a truthy value.
125
+ # The block is passed `self` as an argument.
125
126
  # If no block is given, it asserts that `n === self` is true.
126
127
  # If the assertion fails, it performs a non-local exit by `raise`.
127
128
  #
128
- # @param `n` ([Object]) The object to compare with `self` if no block is given. Defaults to `self`.
129
+ # @param `n` ([Object]) The object to compare with `self` if no block is given.
129
130
  # @param `error` ([Class]) The class of error to raise if the assertion fails.
130
- # Defaults to `StandardError`.
131
+ # @param `message` (String?) An optional message to include in the raised error.
131
132
  # @yield [self] Optional block whose truthiness is asserted.
132
133
  # @return [self] The original object if assertion passes.
133
134
  # @throw `error` (or a related symbol) if the assertion fails.
134
135
  #
135
136
  # @example
136
137
  # 5.assert(Integer) # Passes
137
- # "string".assert(error: ArgumentError) { |s| s.length > 5 } # Passes
138
- def assert(n = self, error: StandardError)
139
- tap { (block_given? ? yield(self) : (n === self)) || raise(error) }
138
+ # "string".assert(error: ArgumentError) { |s| s.size > 5 } # Passes
139
+ # "".assert(message: "String too short") {|s| s.size > 5 } # Raises error with message
140
+ def assert(n = self, error: StandardError, message: nil)
141
+ tap { (block_given? ? yield(self) : (n === self)) || (message ? raise(error, message) : raise(error)) }
140
142
  end
141
143
 
142
144
  # Prints the `inspect` representation of `self` to standard output.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emanlib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - emanrdesu
@@ -18,6 +18,7 @@ extra_rdoc_files: []
18
18
  files:
19
19
  - lib/emanlib.rb
20
20
  - lib/patch/define.rb
21
+ - lib/patch/enum.rb
21
22
  - lib/patch/foobar.rb
22
23
  - lib/patch/lambda.rb
23
24
  homepage: https://github.com/emanrdesu/lib