Runtime assertions for Ruby literal.fun
ruby
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

Literal::Array#product

Closes #188

+119 -1
+5
lib/literal.rb
··· 22 22 autoload :Struct, "literal/struct" 23 23 autoload :Type, "literal/type" 24 24 autoload :Types, "literal/types" 25 + autoload :Tuple, "literal/tuple" 25 26 26 27 # Errors 27 28 autoload :Error, "literal/errors/error" ··· 46 47 47 48 def self.Hash(key_type, value_type) 48 49 Literal::Hash::Generic.new(key_type, value_type) 50 + end 51 + 52 + def self.Tuple(*types) 53 + Literal::Tuple::Generic.new(*types) 49 54 end 50 55 51 56 def self.check(actual:, expected:)
+31 -1
lib/literal/array.rb
··· 23 23 def >=(other) 24 24 case other 25 25 when Literal::Array::Generic 26 - @type >= other.type 26 + Literal.subtype?(other.type, of: @type) 27 27 else 28 28 false 29 29 end ··· 403 403 404 404 def pop(...) 405 405 @__value__.pop(...) 406 + end 407 + 408 + def product(*others, &) 409 + if block_given? 410 + @__value__.product( 411 + *others.map do |other| 412 + case other 413 + when Array 414 + other 415 + when Literal::Array 416 + other.__value__ 417 + end 418 + end, & 419 + ) 420 + 421 + self 422 + elsif others.all?(Literal::Array) 423 + tuple_type = Literal::Tuple( 424 + @__type__, 425 + *others.map(&:__type__) 426 + ) 427 + 428 + values = @__value__.product(*others.map(&:__value__)).map do |tuple_values| 429 + tuple_type.new(*tuple_values) 430 + end 431 + 432 + Literal::Array(tuple_type).new(*values) 433 + else 434 + @__value__.product(*others) 435 + end 406 436 end 407 437 408 438 def push(*value)
+60
lib/literal/tuple.rb
··· 1 + # frozen_string_literal: true 2 + 3 + class Literal::Tuple 4 + class Generic 5 + include Literal::Type 6 + 7 + def initialize(*types) 8 + @types = types 9 + end 10 + 11 + attr_reader :types 12 + 13 + def ===(other) 14 + return false unless Literal::Tuple === other 15 + types = @types 16 + other_types = other.__types__ 17 + 18 + return false unless types.size == other_types.size 19 + 20 + i, len = 0, types.size 21 + while i < len 22 + return false unless Literal.subtype?(other_types[i], of: types[i]) 23 + i += 1 24 + end 25 + 26 + true 27 + end 28 + 29 + def >=(other) 30 + case other 31 + when Literal::Tuple::Generic 32 + types = @types 33 + other_types = other.types 34 + 35 + return false unless types.size == other_types.size 36 + 37 + i, len = 0, types.size 38 + while i < len 39 + return false unless Literal.subtype?(other_types[i], of: types[i]) 40 + i += 1 41 + end 42 + 43 + true 44 + else 45 + false 46 + end 47 + end 48 + 49 + def new(*values) 50 + Literal::Tuple.new(values, @types) 51 + end 52 + end 53 + 54 + def initialize(values, types) 55 + @__values__ = values 56 + @__types__ = types 57 + end 58 + 59 + attr_reader :__values__, :__types__ 60 + end
+23
test/array.test.rb
··· 626 626 assert array.equal?(result) 627 627 expect(result.to_a) == [2, 5, 3, 1, 4] 628 628 end 629 + 630 + test "#product with block" do 631 + a = Literal::Array(Integer).new(1, 2) 632 + b = Literal::Array(String).new("a", "b") 633 + 634 + yielded = [] 635 + 636 + result = a.product(b) { |x, y| yielded << [x, y] } 637 + 638 + assert result.equal?(a) 639 + expect(yielded) == [[1, "a"], [1, "b"], [2, "a"], [2, "b"]] 640 + end 641 + 642 + test "#product with another Literal::Array" do 643 + a = Literal::Array(Integer).new(1, 2) 644 + b = Literal::Array(String).new("a", "b") 645 + 646 + result = a.product(b) 647 + 648 + assert Literal::Array(Literal::Tuple(Integer, String)) === result 649 + expect(result.size) == 4 650 + expect(result.first.__values__) == [1, "a"] 651 + end