<commit_before>module Dry
  module Types
    class Struct
      class << self
        attr_reader :constructor
      end

      def self.inherited(klass)
        super

        klass.instance_variable_set('@equalizer', Equalizer.new)
        klass.send(:include, klass.equalizer)

        unless klass == Value
          klass.instance_variable_set('@constructor', Types['coercible.hash'])
          Types.register_class(klass)
        end

        klass.attributes({}) unless equal?(Struct)
      end

      def self.equalizer
        @equalizer
      end

      def self.attribute(name, type)
        attributes(name => type)
      end

      def self.attributes(new_schema)
        prev_schema = schema

        @schema = prev_schema.merge(new_schema)
        @constructor = Types['coercible.hash'].public_send(constructor_type, schema)

        attr_reader(*(new_schema.keys - prev_schema.keys))
        equalizer.instance_variable_get('@keys').concat(schema.keys).uniq!

        self
      end

      def self.constructor_type(type = :strict)
        @constructor_type ||= type
      end

      def self.schema
        super_schema = superclass.respond_to?(:schema) ? superclass.schema : {}
        super_schema.merge(@schema || {})
      end

      def self.new(attributes = {})
        if attributes.is_a?(self)
          attributes
        else
          super(constructor[attributes])
        end
      rescue SchemaError, SchemaKeyError => e
        raise StructError, "[#{self}.new] #{e.message}"
      end

      def initialize(attributes)
        attributes.each { |key, value| instance_variable_set("@#{key}", value) }
      end

      def [](name)
        public_send(name)
      end

      def to_hash
        self.class.schema.keys.each_with_object({}) { |key, result|
          value = self[key]
          result[key] = value.respond_to?(:to_hash) ? value.to_hash : value
        }
      end
      alias_method :to_h, :to_hash
    end
  end
end
<commit_msg>Refactor attr_reader call in Struct.attributes<commit_after>module Dry
  module Types
    class Struct
      class << self
        attr_reader :constructor
      end

      def self.inherited(klass)
        super

        klass.instance_variable_set('@equalizer', Equalizer.new)
        klass.send(:include, klass.equalizer)

        unless klass == Value
          klass.instance_variable_set('@constructor', Types['coercible.hash'])
          Types.register_class(klass)
        end

        klass.attributes({}) unless equal?(Struct)
      end

      def self.equalizer
        @equalizer
      end

      def self.attribute(name, type)
        attributes(name => type)
      end

      def self.attributes(new_schema)
        prev_schema = schema

        @schema = prev_schema.merge(new_schema)
        @constructor = Types['coercible.hash'].public_send(constructor_type, schema)

        attr_reader(*new_schema.keys)
        equalizer.instance_variable_get('@keys').concat(schema.keys).uniq!

        self
      end

      def self.constructor_type(type = :strict)
        @constructor_type ||= type
      end

      def self.schema
        super_schema = superclass.respond_to?(:schema) ? superclass.schema : {}
        super_schema.merge(@schema || {})
      end

      def self.new(attributes = {})
        if attributes.is_a?(self)
          attributes
        else
          super(constructor[attributes])
        end
      rescue SchemaError, SchemaKeyError => e
        raise StructError, "[#{self}.new] #{e.message}"
      end

      def initialize(attributes)
        attributes.each { |key, value| instance_variable_set("@#{key}", value) }
      end

      def [](name)
        public_send(name)
      end

      def to_hash
        self.class.schema.keys.each_with_object({}) { |key, result|
          value = self[key]
          result[key] = value.respond_to?(:to_hash) ? value.to_hash : value
        }
      end
      alias_method :to_h, :to_hash
    end
  end
end

{'fraction_non_alphanumeric': 0.10524987380111055, 'fraction_numerical': 0.0, 'mean_word_length': 2.2063106796116503, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6924153', 'n_tokens_mistral': 1149, 'n_tokens_neox': 1144, 'n_words': 229}