lib/defi/method.rb in defi-3.0.0 vs lib/defi/method.rb in defi-3.0.1

- old
+ new

@@ -1,98 +1,104 @@ # frozen_string_literal: true module Defi # Represents a method to be applied against an object. - # This class encapsulates the method name, its arguments, keyword arguments, - # and an optional block, enabling dynamic method invocation. + # Encapsulates method name, arguments, keyword arguments and blocks + # for dynamic method invocation with proper error handling. class Method < ::BasicObject # Initialize a new Method object. # - # @param name [Symbol] The name of the method. - # @param args [Array] Any arguments of the method. - # @param opts [Hash] Any keyword arguments of the method. - # @param block [Proc] Any block argument of the method. - # @raise [ArgumentError] If the name is not a symbol. + # @param name [Symbol] The method name + # @param args [Array] Positional arguments + # @param opts [Hash] Keyword arguments + # @param block [Proc] Optional block + # + # @raise [ArgumentError] If name is not a Symbol, raises with the actual class received def initialize(name, *args, **opts, &block) - raise ::ArgumentError, name.class.inspect unless name.is_a?(::Symbol) + raise ::ArgumentError, "Method name must be a Symbol, got: #{name.class}" unless name.is_a?(::Symbol) @name = name @args = args @opts = opts @block = block end # Applies the method to the given object. # - # @example - # add = Defi::Method.new(:+, 1) - # add.to(2).call # => 3 + # @param object [#object_id] Target object for method invocation + # @return [Defi::Value] Result wrapper containing return value or exception # - # @param object [#object_id] The object to method. - # @return [Defi::Value] The actual value, to raise or to return. + # @example Basic arithmetic + # Defi::Method.new(:+, 1).to(2).call # => 3 + # + # @example Block usage + # Defi::Method.new(:map) { |x| x * 2 }.to([1, 2, 3]).call # => [2, 4, 6] + # + # @example Error handling + # result = Defi::Method.new(:undefined).to(42) + # result.raised? # => true def to(object) Value.new { object.public_send(@name, *@args, **@opts, &@block) } end - # Returns a hash containing the method's properties. - # - # @return [Hash] The properties of the method. + # @return [Hash] Method properties def to_h { name: @name, args: @args, opts: @opts, block: @block } end - # rubocop:disable Metrics/AbcSize - # rubocop:disable Metrics/CyclomaticComplexity - - # Returns a string representation of the method. + # @return [String] Human-readable representation # # @example - # add = Defi::Method.new(:+, 1) - # add.to_s # => ".+(1)" + # Defi::Method.new(:+, 1).inspect + # # => "Defi(name: :+, args: [1], opts: {}, block: nil)" + def inspect + "Defi(" \ + "name: #{@name.inspect}, " \ + "args: #{@args.inspect}, " \ + "opts: #{@opts.inspect}, " \ + "block: #{@block.nil? ? "nil" : "<Proc>"})" + end + + # @return [String] String representation of the method call # - # @return [String] The string representation of the method. + # @example + # Defi::Method.new(:+, 1).to_s # => ".+(1)" + # Defi::Method.new(:map) { |x| x }.to_s # => ".map(<Proc>)" def to_s - string = ".#{@name}" - return string if @args.empty? && @opts.empty? && @block.nil? + return ".#{@name}" if no_arguments? - stringified_args = @args.inspect[1..-2] - stringified_opts = @opts.inspect[1..-2] - stringified_block = "<Proc>" unless @block.nil? + ".#{@name}(#{stringified_arguments})" + end - stringified_items = [] - stringified_items << stringified_args unless @args.empty? - stringified_items << stringified_opts unless @opts.empty? - stringified_items << stringified_block unless @block.nil? + private - "#{string}(#{stringified_items.join(", ")})" + def no_arguments? + @args.empty? && @opts.empty? && @block.nil? end - # rubocop:enable Metrics/AbcSize - # rubocop:enable Metrics/CyclomaticComplexity + def stringified_arguments + [ + args_string, + opts_string, + block_string + ].compact.join(", ") + end - # Returns a human-readable representation of the method. - # - # @example - # add = Defi::Method.new(:+, 1) - # add.inspect # => "Defi(name: :+, args: [1], opts: {}, block: nil)" - # - # @return [String] The human-readable representation of the method. - def inspect - inspected_name = @name.inspect - inspected_args = @args.inspect - inspected_opts = @opts.inspect - inspected_block = @block.nil? ? "nil" : "<Proc>" + def args_string + @args.inspect[1..-2] unless @args.empty? + end - "Defi(" \ - "name: #{inspected_name}, " \ - "args: #{inspected_args}, " \ - "opts: #{inspected_opts}, " \ - "block: #{inspected_block})" + def opts_string + @opts.inspect[1..-2] unless @opts.empty? + end + + def block_string + "<Proc>" if @block end end end require_relative "value"