From 41eafc25990eea41154b913651ec3bf81305b58e Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Sat, 3 Apr 2021 11:22:46 +0200 Subject: [PATCH 1/4] Add return type restrictions to methods of container types --- src/array.cr | 56 ++++++++++++++++++++++----------------------- src/atomic.cr | 18 +++++++-------- src/bit_array.cr | 2 +- src/deque.cr | 20 ++++++++-------- src/enumerable.cr | 54 +++++++++++++++++++++---------------------- src/env.cr | 2 +- src/hash.cr | 36 ++++++++++++++--------------- src/indexable.cr | 20 ++++++++-------- src/set.cr | 30 ++++++++++++------------ src/slice.cr | 24 +++++++++---------- src/static_array.cr | 4 ++-- 11 files changed, 133 insertions(+), 133 deletions(-) diff --git a/src/array.cr b/src/array.cr index b211352044be..0a881e2b2a66 100644 --- a/src/array.cr +++ b/src/array.cr @@ -670,7 +670,7 @@ class Array(T) # a = ["a", "b", "c", "d", "e"] # a.clear # => [] # ``` - def clear + def clear : self @buffer.clear(@size) @size = 0 self @@ -723,7 +723,7 @@ class Array(T) # ary.compact! # ary # => ["a", "b", "c"] # ``` - def compact! + def compact! : self reject! &.nil? end @@ -781,7 +781,7 @@ class Array(T) # a.delete("x") # => nil # a # => ["a", "c"] # ``` - def delete(obj) + def delete(obj) : T? internal_delete { |e| e == obj }[1] end @@ -819,7 +819,7 @@ class Array(T) # a # => ["ant", "dog"] # a.delete_at(99..100) # raises IndexError # ``` - def delete_at(range : Range) + def delete_at(range : Range) : self index, count = Indexable.range_to_index_and_count(range, self.size) || raise IndexError.new delete_at(index, count) end @@ -835,7 +835,7 @@ class Array(T) # a # => ["ant", "dog"] # a.delete_at(99, 1) # raises IndexError # ``` - def delete_at(index : Int, count : Int) + def delete_at(index : Int, count : Int) : self index += size if index < 0 unless 0 <= index <= size raise IndexError.new @@ -1044,7 +1044,7 @@ class Array(T) # [1, 2, 3].first(2) # => [1, 2] # [1, 2, 3].first(4) # => [1, 2, 3] # ``` - def first(n : Int) + def first(n : Int) : Array(T) self[0, n] end @@ -1092,7 +1092,7 @@ class Array(T) # [1, 2, 3].last(2) # => [2, 3] # [1, 2, 3].last(4) # => [1, 2, 3] # ``` - def last(n : Int) + def last(n : Int) : Array(T) if n < @size self[@size - n, n] else @@ -1147,7 +1147,7 @@ class Array(T) # ``` # # See also: `Array#reject!`. - def select!(pattern) + def select!(pattern) : self self.select! { |elem| pattern === elem } end @@ -1176,7 +1176,7 @@ class Array(T) # ``` # # See also: `Array#select!`. - def reject!(pattern) + def reject!(pattern) : self reject! { |elem| pattern === elem } self end @@ -1315,7 +1315,7 @@ class Array(T) end end - def repeated_permutations(size : Int = self.size) + def repeated_permutations(size : Int = self.size) : Array(Array(T)) ary = [] of Array(T) each_repeated_permutation(size) do |a| ary << a @@ -1344,7 +1344,7 @@ class Array(T) # a.pop # => "c" # a # => ["a", "b"] # ``` - def pop + def pop : T pop { raise IndexError.new } end @@ -1389,7 +1389,7 @@ class Array(T) # a.pop(4) # => ["a", "b", "c"] # a # => [] # ``` - def pop(n : Int) + def pop(n : Int) : Array(T) if n < 0 raise ArgumentError.new("Can't pop negative count") end @@ -1404,7 +1404,7 @@ class Array(T) end # Like `pop`, but returns `nil` if `self` is empty. - def pop? + def pop? : T? pop { nil } end @@ -1448,7 +1448,7 @@ class Array(T) # a = ["a"] # a.push("b", "c") # => ["a", "b", "c"] # ``` - def push(*values : T) + def push(*values : T) : self new_size = @size + values.size resize_if_cant_insert(values.size) @@ -1460,7 +1460,7 @@ class Array(T) self end - def replace(other : Array) + def replace(other : Array) : self @size = other.size resize_to_capacity(Math.pw2ceil(@size)) if @size > @capacity @buffer.copy_from(other.to_unsafe, other.size) @@ -1473,7 +1473,7 @@ class Array(T) # a = [1, 2, 3] # a.reverse # => [3, 2, 1] # ``` - def reverse + def reverse : Array(T) Array(T).new(size) { |i| @buffer[size - i - 1] } end @@ -1498,7 +1498,7 @@ class Array(T) # a2 # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] # a3 # => [3, 4, 5, 6, 7, 8, 9, 0, 1, 2] # ``` - def rotate!(n = 1) + def rotate!(n = 1) : self return self if size == 0 n %= size @@ -1542,7 +1542,7 @@ class Array(T) # a.rotate(3) # => [3, 4, 5, 6, 7, 8, 9, 0, 1, 2] # a # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # ``` - def rotate(n = 1) + def rotate(n = 1) : Array(T) return self if size == 0 n %= size return self if n == 0 @@ -1561,7 +1561,7 @@ class Array(T) # a.shift # => "a" # a # => ["b", "c"] # ``` - def shift + def shift : T shift { raise IndexError.new } end @@ -1614,7 +1614,7 @@ class Array(T) # a.shift(4) # => ["a", "b", "c"] # a # => [] # ``` - def shift(n : Int) + def shift(n : Int) : Array(T) if n < 0 raise ArgumentError.new("Can't shift negative count") end @@ -1647,19 +1647,19 @@ class Array(T) # a.shift? # => nil # a # => [] # ``` - def shift? + def shift? : T? shift { nil } end # Returns an array with all the elements in the collection randomized # using the given *random* number generator. - def shuffle(random = Random::DEFAULT) + def shuffle(random = Random::DEFAULT) : Array(T) dup.shuffle!(random) end # Modifies `self` by randomizing the order of elements in the collection # using the given *random* number generator. Returns `self`. - def shuffle!(random = Random::DEFAULT) + def shuffle!(random = Random::DEFAULT) : self @buffer.shuffle!(size, random) self end @@ -1894,7 +1894,7 @@ class Array(T) # a.uniq! # => ["a", "b", "c"] # a # => ["a", "b", "c"] # ``` - def uniq! + def uniq! : self if size <= 1 return self end @@ -1959,7 +1959,7 @@ class Array(T) # a.unshift("c") # => ["c", "a", "b"] # a.unshift(1) # => [1, "c", "a", "b"] # ``` - def unshift(object : T) + def unshift(object : T) : self # If we have no more room left before the beginning of the array # we make the array larger, but point the buffer to start at the middle # of the entire allocated memory. In this way, if more elements are unshift @@ -1980,7 +1980,7 @@ class Array(T) # Prepend multiple values. The same as `unshift`, but takes an arbitrary number # of values to add to the array. Returns `self`. - def unshift(*values : T) + def unshift(*values : T) : self values.reverse_each do |value| unshift(value) end @@ -2060,7 +2060,7 @@ class Array(T) @size == remaining_capacity end - def remaining_capacity + def remaining_capacity : Int32 @capacity - @offset_to_buffer end @@ -2142,7 +2142,7 @@ class Array(T) end # :nodoc: - def index(object, offset : Int = 0) + def index(object, offset : Int = 0) : Int32? # Optimize for the case of looking for a byte in a byte slice if T.is_a?(UInt8.class) && (object.is_a?(UInt8) || (object.is_a?(Int) && 0 <= object < 256)) diff --git a/src/atomic.cr b/src/atomic.cr index 3612803b4b8a..e93d9eb5e9dc 100644 --- a/src/atomic.cr +++ b/src/atomic.cr @@ -52,7 +52,7 @@ struct Atomic(T) # atomic.add(2) # => 1 # atomic.get # => 3 # ``` - def add(value : T) + def add(value : T) : T Ops.atomicrmw(:add, pointerof(@value), value, :sequentially_consistent, false) end @@ -63,7 +63,7 @@ struct Atomic(T) # atomic.sub(2) # => 9 # atomic.get # => 7 # ``` - def sub(value : T) + def sub(value : T) : T Ops.atomicrmw(:sub, pointerof(@value), value, :sequentially_consistent, false) end @@ -74,7 +74,7 @@ struct Atomic(T) # atomic.and(3) # => 5 # atomic.get # => 1 # ``` - def and(value : T) + def and(value : T) : T Ops.atomicrmw(:and, pointerof(@value), value, :sequentially_consistent, false) end @@ -85,7 +85,7 @@ struct Atomic(T) # atomic.nand(3) # => 5 # atomic.get # => -2 # ``` - def nand(value : T) + def nand(value : T) : T Ops.atomicrmw(:nand, pointerof(@value), value, :sequentially_consistent, false) end @@ -96,7 +96,7 @@ struct Atomic(T) # atomic.or(2) # => 5 # atomic.get # => 7 # ``` - def or(value : T) + def or(value : T) : T Ops.atomicrmw(:or, pointerof(@value), value, :sequentially_consistent, false) end @@ -107,7 +107,7 @@ struct Atomic(T) # atomic.xor(3) # => 5 # atomic.get # => 6 # ``` - def xor(value : T) + def xor(value : T) : T Ops.atomicrmw(:xor, pointerof(@value), value, :sequentially_consistent, false) end @@ -172,7 +172,7 @@ struct Atomic(T) # atomic.set(10) # => 10 # atomic.get # => 10 # ``` - def set(value : T) + def set(value : T) : T Ops.store(pointerof(@value), value.as(T), :sequentially_consistent, true) value end @@ -184,11 +184,11 @@ struct Atomic(T) # atomic.lazy_set(10) # => 10 # atomic.get # => 10 # ``` - def lazy_set(@value : T) + def lazy_set(@value : T) : T end # Atomically returns this atomic's value. - def get + def get : T Ops.load(pointerof(@value), :sequentially_consistent, true) end diff --git a/src/bit_array.cr b/src/bit_array.cr index 6c711dcb713d..f435c70840ff 100644 --- a/src/bit_array.cr +++ b/src/bit_array.cr @@ -39,7 +39,7 @@ struct BitArray return LibC.memcmp(@bits, other.@bits, bytesize) == 0 end - def unsafe_fetch(index : Int) + def unsafe_fetch(index : Int) : Bool bit_index, sub_index = index.divmod(32) (@bits[bit_index] & (1 << sub_index)) > 0 end diff --git a/src/deque.cr b/src/deque.cr index 82b8d7358e45..c0f577646489 100644 --- a/src/deque.cr +++ b/src/deque.cr @@ -199,7 +199,7 @@ class Deque(T) # a.delete("b") # => true # a # => Deque{"a", "c"} # ``` - def delete(obj) + def delete(obj) : Bool match = internal_delete { |i| i == obj } !match.nil? end @@ -228,7 +228,7 @@ class Deque(T) # ``` # # See also: `Deque#select`. - def select!(pattern) + def select!(pattern) : self self.select! { |elem| pattern === elem } end @@ -257,7 +257,7 @@ class Deque(T) # ``` # # See also: `Deque#reject`. - def reject!(pattern) + def reject!(pattern) : self reject! { |elem| pattern === elem } self end @@ -288,7 +288,7 @@ class Deque(T) # a.delete_at(1) # => 2 # a # => Deque{1, 3} # ``` - def delete_at(index : Int) + def delete_at(index : Int) : T if index < 0 index += @size end @@ -360,7 +360,7 @@ class Deque(T) # a = Deque{0, 1, 2} # a.insert(1, 7) # => Deque{0, 7, 1, 2} # ``` - def insert(index : Int, value : T) + def insert(index : Int, value : T) : self if index < 0 index += @size + 1 end @@ -429,7 +429,7 @@ class Deque(T) # ``` # Deque{:foo, :bar}.size # => 2 # ``` - def size + def size : Int32 @size end @@ -440,7 +440,7 @@ class Deque(T) # a.pop # => 3 # a # => Deque{1, 2} # ``` - def pop + def pop : T pop { raise IndexError.new } end @@ -460,7 +460,7 @@ class Deque(T) end # Removes and returns the last item, if not empty, otherwise `nil`. - def pop? + def pop? : T? pop { nil } end @@ -556,7 +556,7 @@ class Deque(T) end # Swaps the items at the indices *i* and *j*. - def swap(i, j) + def swap(i, j) : self self[i], self[j] = self[j], self[i] self end @@ -571,7 +571,7 @@ class Deque(T) # a = Deque{1, 2} # a.unshift 0 # => Deque{0, 1, 2} # ``` - def unshift(value : T) + def unshift(value : T) : self increase_capacity if @size >= @capacity @start -= 1 @start += @capacity if @start < 0 diff --git a/src/enumerable.cr b/src/enumerable.cr index 341aec76d73c..6b46394c9738 100644 --- a/src/enumerable.cr +++ b/src/enumerable.cr @@ -57,7 +57,7 @@ module Enumerable(T) # [2, "a", 3].all?(String) # => false # %w[foo bar baz].all?(/o|a/) # => true # ``` - def all?(pattern) + def all?(pattern) : Bool all? { |e| pattern === e } end @@ -67,7 +67,7 @@ module Enumerable(T) # [nil, true, 99].all? # => false # [15].all? # => true # ``` - def all? + def all? : Bool all? &.itself end @@ -92,7 +92,7 @@ module Enumerable(T) # [2, "a", 3].any?(String) # => true # %w[foo bar baz].any?(/a/) # => true # ``` - def any?(pattern) + def any?(pattern) : Bool any? { |e| pattern === e } end @@ -102,7 +102,7 @@ module Enumerable(T) # [nil, true, 99].any? # => true # [nil, false].any? # => false # ``` - def any? + def any? : Bool any? &.itself end @@ -182,7 +182,7 @@ module Enumerable(T) end end - def same_as?(key) + def same_as?(key) : Bool return false unless @initialized return false if key == Alone || key == Drop @key == key @@ -249,7 +249,7 @@ module Enumerable(T) # ``` # [1, 2, 3, 4].count(3) # => 1 # ``` - def count(item) + def count(item) : Int32 count { |e| e == item } end @@ -498,7 +498,7 @@ module Enumerable(T) # ([1, 2, 3]).first # => 1 # ([] of Int32).first # raises Enumerable::EmptyError # ``` - def first + def first : T first { raise Enumerable::EmptyError.new } end @@ -509,7 +509,7 @@ module Enumerable(T) # ([1, 2, 3]).first? # => 1 # ([] of Int32).first? # => nil # ``` - def first? + def first? : T? first { nil } end @@ -613,7 +613,7 @@ module Enumerable(T) # [1, 2, 3].includes?(2) # => true # [1, 2, 3].includes?(5) # => false # ``` - def includes?(obj) + def includes?(obj) : Bool any? { |e| e == obj } end @@ -721,7 +721,7 @@ module Enumerable(T) # ``` # [1, 2, 3, 4, 5].join(", ") # => "1, 2, 3, 4, 5" # ``` - def join(separator = "") + def join(separator = "") : String String.build do |io| join io, separator end @@ -848,12 +848,12 @@ module Enumerable(T) # ``` # # Raises `Enumerable::EmptyError` if the collection is empty. - def max + def max : T max_by &.itself end # Like `max` but returns `nil` if the collection is empty. - def max? + def max? : T? max_by? &.itself end @@ -937,12 +937,12 @@ module Enumerable(T) # ``` # # Raises `Enumerable::EmptyError` if the collection is empty. - def min + def min : T min_by &.itself end # Like `min` but returns `nil` if the collection is empty. - def min? + def min? : T? min_by? &.itself end @@ -1023,12 +1023,12 @@ module Enumerable(T) # ``` # # Raises `Enumerable::EmptyError` if the collection is empty. - def minmax + def minmax : {T, T} minmax_by &.itself end # Like `minmax` but returns `{nil, nil}` if the collection is empty. - def minmax? + def minmax? : {T?, T?} minmax_by? &.itself end @@ -1138,7 +1138,7 @@ module Enumerable(T) # [2, "a", 3].none?(String) # => false # %w[foo bar baz].none?(/e/) # => true # ``` - def none?(pattern) + def none?(pattern) : Bool none? { |e| pattern === e } end @@ -1150,7 +1150,7 @@ module Enumerable(T) # ``` # # It's the opposite of `all?`. - def none? + def none? : Bool none? &.itself end @@ -1178,7 +1178,7 @@ module Enumerable(T) # [2, "a", 3].one?(Int32) # => false # %w[foo bar baz].one?(/oo/) # => true # ``` - def one?(pattern) + def one?(pattern) : Bool one? { |e| pattern === e } end @@ -1191,7 +1191,7 @@ module Enumerable(T) # [1].one? # => true # [false].one? # => false # ``` - def one? + def one? : Bool one? &.itself end @@ -1246,7 +1246,7 @@ module Enumerable(T) # ``` # [1, 3, 2, 5, 4, 6].reject(3..5) # => [1, 2, 6] # ``` - def reject(pattern) + def reject(pattern) : Array(T) reject { |e| pattern === e } end @@ -1262,7 +1262,7 @@ module Enumerable(T) # {1, 2, 3, 4, 5}.sample(2) # => [3, 4] # {1, 2, 3, 4, 5}.sample(2, Random.new(1)) # => [1, 5] # ``` - def sample(n : Int, random = Random::DEFAULT) + def sample(n : Int, random = Random::DEFAULT) : Array(T) raise ArgumentError.new("Can't sample negative number of elements") if n < 0 # Unweighted reservoir sampling: @@ -1298,7 +1298,7 @@ module Enumerable(T) # a.sample # => 1 # a.sample(Random.new(1)) # => 3 # ``` - def sample(random = Random::DEFAULT) + def sample(random = Random::DEFAULT) : T value = uninitialized T found = false @@ -1347,7 +1347,7 @@ module Enumerable(T) # [1, 3, 2, 5, 4, 6].select(3..5) # => [3, 5, 4] # ["Alice", "Bob"].select(/^A/) # => ["Alice"] # ``` - def select(pattern) + def select(pattern) : Array(T) self.select { |elem| pattern === elem } end @@ -1356,7 +1356,7 @@ module Enumerable(T) # ``` # [1, 2, 3, 4].size # => 4 # ``` - def size + def size : Int32 count { true } end @@ -1366,7 +1366,7 @@ module Enumerable(T) # ([] of Int32).empty? # => true # ([1]).empty? # => false # ``` - def empty? + def empty? : Bool each { return false } true end @@ -1587,7 +1587,7 @@ module Enumerable(T) # If *count* is bigger than the number of elements in the collection, # returns as many as possible. This include the case of calling it over # an empty collection, in which case it returns an empty array. - def first(count : Int) + def first(count : Int) : Array(T) raise ArgumentError.new("Attempt to take negative size") if count < 0 ary = Array(T).new(count) diff --git a/src/env.cr b/src/env.cr index 0640b057c9ae..a2d5d035d238 100644 --- a/src/env.cr +++ b/src/env.cr @@ -56,7 +56,7 @@ module ENV # Retrieves a value corresponding to the given *key*. Return the second argument's value # if the *key* does not exist. - def self.fetch(key, default) + def self.fetch(key, default) : String? fetch(key) { default } end diff --git a/src/hash.cr b/src/hash.cr index 788720e962b1..3b426d80a15c 100644 --- a/src/hash.cr +++ b/src/hash.cr @@ -1093,7 +1093,7 @@ class Hash(K, V) # h.has_key?("foo") # => true # h.has_key?("bar") # => false # ``` - def has_key?(key) + def has_key?(key) : Bool !!find_entry(key) end @@ -1104,7 +1104,7 @@ class Hash(K, V) # h.has_value?("foo") # => false # h.has_value?("bar") # => true # ``` - def has_value?(val) + def has_value?(val) : Bool each_value do |value| return true if value == val end @@ -1154,7 +1154,7 @@ class Hash(K, V) # hash.key_for("qux") # => "baz" # hash.key_for("foobar") # raises KeyError (Missing hash key for value: foobar) # ``` - def key_for(value) + def key_for(value) : K key_for(value) { raise KeyError.new "Missing hash key for value: #{value}" } end @@ -1166,7 +1166,7 @@ class Hash(K, V) # hash.key_for?("qux") # => "baz" # hash.key_for?("foobar") # => nil # ``` - def key_for?(value) + def key_for?(value) : K? key_for(value) { nil } end @@ -1217,7 +1217,7 @@ class Hash(K, V) # h = {"foo" => "bar"} # h.empty? # => false # ``` - def empty? + def empty? : Bool @size == 0 end @@ -1448,7 +1448,7 @@ class Hash(K, V) # ``` # {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.reject("a", "c") # => {"b" => 2, "d" => 4} # ``` - def reject(*keys) + def reject(*keys) : Hash(K, V) hash = self.dup hash.reject!(*keys) end @@ -1459,12 +1459,12 @@ class Hash(K, V) # h = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.reject!("a", "c") # h # => {"b" => 2, "d" => 4} # ``` - def reject!(keys : Array | Tuple) + def reject!(keys : Array | Tuple) : self keys.each { |k| delete(k) } self end - def reject!(*keys) + def reject!(*keys) : self reject!(keys) end @@ -1475,14 +1475,14 @@ class Hash(K, V) # {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select("a", "c") # => {"a" => 1, "c" => 3} # {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select(["a", "c"]) # => {"a" => 1, "c" => 3} # ``` - def select(keys : Array | Tuple) + def select(keys : Array | Tuple) : Hash(K, V) hash = {} of K => V keys.each { |k| hash[k] = self[k] if has_key?(k) } hash end # :ditto: - def select(*keys) + def select(*keys) : Hash(K, V) self.select(keys) end @@ -1495,13 +1495,13 @@ class Hash(K, V) # h1 == h2 == h3 # => true # h1 # => {"a" => 1, "c" => 3} # ``` - def select!(keys : Array | Tuple) + def select!(keys : Array | Tuple) : self each { |k, v| delete(k) unless keys.includes?(k) } self end # :ditto: - def select!(*keys) + def select!(*keys) : self select!(keys) end @@ -1523,7 +1523,7 @@ class Hash(K, V) # hash = {"hello" => "world", "foo" => nil} # hash.compact! # => {"hello" => "world"} # ``` - def compact! + def compact! : self reject! { |key, value| value.nil? } end @@ -1597,7 +1597,7 @@ class Hash(K, V) # hash.clear # hash.first_key? # => nil # ``` - def first_key? + def first_key? : K? first_entry?.try &.key end @@ -1680,7 +1680,7 @@ class Hash(K, V) # hash = {} of String => String # hash.shift? # => nil # ``` - def shift? + def shift? : {K, V}? shift { nil } end @@ -1861,7 +1861,7 @@ class Hash(K, V) end # Returns `self`. - def to_h + def to_h : self self end @@ -1880,7 +1880,7 @@ class Hash(K, V) # {"foo" => "bar"}.invert # => {"bar" => "foo"} # {"foo" => "bar", "baz" => "bar"}.invert # => {"bar" => "baz"} # ``` - def invert + def invert : Hash(V, K) hash = Hash(V, K).new(initial_capacity: @size) self.each do |k, v| hash[v] = k @@ -1900,7 +1900,7 @@ class Hash(K, V) new(0_u32, key, value) end - def deleted? + def deleted? : Bool @hash == 0_u32 end diff --git a/src/indexable.cr b/src/indexable.cr index 4603fff68ada..3020333486e3 100644 --- a/src/indexable.cr +++ b/src/indexable.cr @@ -324,7 +324,7 @@ module Indexable(T) # all of the elements in this indexable are strings: the total string # bytesize to return can be computed before creating the final string, # which performs better because there's no need to do reallocations. - def join(separator : String | Char | Number = "") + def join(separator : String | Char | Number = "") : String return "" if empty? {% if T == String %} @@ -388,7 +388,7 @@ module Indexable(T) # ``` # {1, 2, 3}.to_a # => [1, 2, 3] # ``` - def to_a + def to_a : Array(T) ary = Array(T).new(size) each { |e| ary << e } ary @@ -400,7 +400,7 @@ module Indexable(T) # ([] of Int32).empty? # => true # ([1]).empty? # => false # ``` - def empty? + def empty? : Bool size == 0 end @@ -483,7 +483,7 @@ module Indexable(T) # ([1, 2, 3]).last # => 3 # ([] of Int32).last # raises IndexError # ``` - def last + def last : T last { raise IndexError.new } end @@ -503,7 +503,7 @@ module Indexable(T) # ([1, 2, 3]).last? # => 3 # ([] of Int32).last? # => nil # ``` - def last? + def last? : T? last { nil } end @@ -529,7 +529,7 @@ module Indexable(T) # [1, 2, 3, 2, 3].rindex(2) # => 3 # [1, 2, 3, 2, 3].rindex(2, offset: 2) # => 1 # ``` - def rindex(value, offset = size - 1) + def rindex(value, offset = size - 1) : Int32? rindex(offset) { |elem| elem == value } end @@ -570,7 +570,7 @@ module Indexable(T) end # :nodoc: - def sample(n : Int, random = Random::DEFAULT) + def sample(n : Int, random = Random::DEFAULT) : Array(T) return super unless n == 1 if empty? @@ -604,7 +604,7 @@ module Indexable(T) end # :nodoc: - def self.range_to_index_and_count(range, collection_size) + def self.range_to_index_and_count(range, collection_size) : {Int32, Int32}? start_index = range.begin if start_index.nil? start_index = 0 @@ -639,7 +639,7 @@ module Indexable(T) # a.permutations(0) # => [[]] # a.permutations(4) # => [] # ``` - def permutations(size : Int = self.size) + def permutations(size : Int = self.size) : Array(Array(T)) ary = [] of Array(T) each_permutation(size) do |a| ary << a @@ -783,7 +783,7 @@ module Indexable(T) CombinationIterator(self, T).new(self, size.to_i, check_reuse(reuse, size)) end - def repeated_combinations(size : Int = self.size) + def repeated_combinations(size : Int = self.size) : Array(Array(T)) ary = [] of Array(T) each_repeated_combination(size) do |a| ary << a diff --git a/src/set.cr b/src/set.cr index 17bad6dd0712..82d37261c327 100644 --- a/src/set.cr +++ b/src/set.cr @@ -76,7 +76,7 @@ struct Set(T) # Returns `true` of this Set is comparing objects by `object_id`. # # See `compare_by_identity`. - def compare_by_identity? + def compare_by_identity? : Bool @hash.compare_by_identity? end @@ -106,7 +106,7 @@ struct Set(T) # s.add? 8 # => true # s.add? 8 # => false # ``` - def add?(object : T) + def add?(object : T) : Bool @hash.put(object, nil) { return true } false end @@ -120,7 +120,7 @@ struct Set(T) # ``` # # See also: `#|` to merge two sets and return a new one. - def concat(elems) + def concat(elems) : self elems.each { |elem| self << elem } self end @@ -132,7 +132,7 @@ struct Set(T) # s.includes? 5 # => true # s.includes? 9 # => false # ``` - def includes?(object) + def includes?(object) : Bool @hash.has_key?(object) end @@ -156,7 +156,7 @@ struct Set(T) # s = Set{1, 5} # s.size # => 2 # ``` - def size + def size : Int32 @hash.size end @@ -168,7 +168,7 @@ struct Set(T) # s.clear # s.size # => 0 # ``` - def clear + def clear : self @hash.clear self end @@ -181,7 +181,7 @@ struct Set(T) # s << 3 # s.empty? # => false # ``` - def empty? + def empty? : Bool @hash.empty? end @@ -401,7 +401,7 @@ struct Set(T) # Set{1, 2, 3}.intersects? Set{4, 5} # => false # Set{1, 2, 3}.intersects? Set{3, 4} # => true # ``` - def intersects?(other : Set) + def intersects?(other : Set) : Bool if size < other.size any? { |o| other.includes?(o) } else @@ -425,7 +425,7 @@ struct Set(T) # Set{1, 5}.subset_of? Set{1, 3, 5} # => true # Set{1, 3, 5}.subset_of? Set{1, 3, 5} # => true # ``` - def subset_of?(other : Set) + def subset_of?(other : Set) : Bool return false if other.size < size all? { |value| other.includes?(value) } end @@ -439,7 +439,7 @@ struct Set(T) # Set{1, 5}.proper_subset_of? Set{1, 3, 5} # => true # Set{1, 3, 5}.proper_subset_of? Set{1, 3, 5} # => false # ``` - def proper_subset_of?(other : Set) + def proper_subset_of?(other : Set) : Bool return false if other.size <= size all? { |value| other.includes?(value) } end @@ -453,7 +453,7 @@ struct Set(T) # Set{1, 3, 5}.superset_of? Set{1, 5} # => true # Set{1, 3, 5}.superset_of? Set{1, 3, 5} # => true # ``` - def superset_of?(other : Set) + def superset_of?(other : Set) : Bool other.subset_of?(self) end @@ -466,24 +466,24 @@ struct Set(T) # Set{1, 3, 5}.proper_superset_of? Set{1, 5} # => true # Set{1, 3, 5}.proper_superset_of? Set{1, 3, 5} # => false # ``` - def proper_superset_of?(other : Set) + def proper_superset_of?(other : Set) : Bool other.proper_subset_of?(self) end # :nodoc: - def object_id + def object_id : UInt64 @hash.object_id end # :nodoc: - def same?(other : Set) + def same?(other : Set) : Bool @hash.same?(other.@hash) end end module Enumerable # Returns a new `Set` with each unique element in the enumerable. - def to_set + def to_set : Set(T) Set.new(self) end end diff --git a/src/slice.cr b/src/slice.cr index 3b3edec8de45..525acdf40bda 100644 --- a/src/slice.cr +++ b/src/slice.cr @@ -150,7 +150,7 @@ struct Slice(T) # slice = Slice(UInt8).empty # slice.size # => 0 # ``` - def self.empty + def self.empty : self new(Pointer(T).null, 0) end @@ -163,7 +163,7 @@ struct Slice(T) # slice2 = slice + 2 # slice2 # => Slice[12, 13, 14] # ``` - def +(offset : Int) + def +(offset : Int) : Slice(T) check_size(offset) Slice.new(@pointer + offset, @size - offset, read_only: @read_only) @@ -206,7 +206,7 @@ struct Slice(T) # slice[1, 3]? # => Slice[11, 12, 13] # slice[1, 33]? # => nil # ``` - def []?(start : Int, count : Int) + def []?(start : Int, count : Int) : Slice(T)? return unless 0 <= start <= @size return unless 0 <= count <= @size - start @@ -225,7 +225,7 @@ struct Slice(T) # slice[1, 3] # => Slice[11, 12, 13] # slice[1, 33] # raises IndexError # ``` - def [](start : Int, count : Int) + def [](start : Int, count : Int) : Slice(T) self[start, count]? || raise IndexError.new end @@ -264,18 +264,18 @@ struct Slice(T) # slice[1..3] # => Slice[11, 12, 13] # slice[1..33] # raises IndexError # ``` - def [](range : Range) + def [](range : Range) : Slice(T) start, count = Indexable.range_to_index_and_count(range, size) || raise IndexError.new self[start, count] end @[AlwaysInline] - def unsafe_fetch(index : Int) + def unsafe_fetch(index : Int) : T @pointer[index] end # Reverses in-place all the elements of `self`. - def reverse! + def reverse! : self check_writable return self if size <= 1 @@ -435,7 +435,7 @@ struct Slice(T) # slice = UInt8.slice(97, 62, 63, 8, 255) # slice.hexstring # => "613e3f08ff" # ``` - def hexstring + def hexstring : String self.as(Slice(UInt8)) str_size = size * 2 @@ -467,7 +467,7 @@ struct Slice(T) # slice = UInt8.slice(97, 62, 63, 8, 255) # slice.hexdump # => "00000000 61 3e 3f 08 ff a>?.." # ``` - def hexdump + def hexdump : String self.as(Slice(UInt8)) return "" if empty? @@ -533,7 +533,7 @@ struct Slice(T) ((c < 10 ? 48_u8 : 87_u8) + c) end - def bytesize + def bytesize : Int32 sizeof(T) * size end @@ -588,7 +588,7 @@ struct Slice(T) {% end %} end - def to_slice + def to_slice : self self end @@ -739,7 +739,7 @@ struct Slice(T) end # :nodoc: - def fast_index(object, offset) + def fast_index(object, offset) : Int32? offset += size if offset < 0 if 0 <= offset < size result = LibC.memchr(to_unsafe + offset, object, size - offset) diff --git a/src/static_array.cr b/src/static_array.cr index 31a1a9fa3eae..1da825815365 100644 --- a/src/static_array.cr +++ b/src/static_array.cr @@ -156,7 +156,7 @@ struct StaticArray(T, N) # array = StaticArray(Int32, 3).new { |i| i + 1 } # array.size # => 3 # ``` - def size + def size : Int32 N end @@ -265,7 +265,7 @@ struct StaticArray(T, N) # slice[0] = 3 # array # => StaticArray[3, 2, 2] # ``` - def to_slice + def to_slice : Slice(T) Slice.new(to_unsafe, size) end From 370c515790b356c11d85f778b506d4c57b92c306 Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Sat, 10 Apr 2021 23:36:30 +0200 Subject: [PATCH 2/4] This annotation was not backwards compatible --- src/indexable.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/indexable.cr b/src/indexable.cr index 3020333486e3..103f49d5093d 100644 --- a/src/indexable.cr +++ b/src/indexable.cr @@ -604,7 +604,7 @@ module Indexable(T) end # :nodoc: - def self.range_to_index_and_count(range, collection_size) : {Int32, Int32}? + def self.range_to_index_and_count(range, collection_size) start_index = range.begin if start_index.nil? start_index = 0 From 6542882fc3caab84ad9b3b1a47f3f69b255cb235 Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Sun, 11 Apr 2021 02:34:32 +0200 Subject: [PATCH 3/4] More --- src/array.cr | 2 +- src/bit_array.cr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/array.cr b/src/array.cr index 0a881e2b2a66..0d8efe89f14a 100644 --- a/src/array.cr +++ b/src/array.cr @@ -614,7 +614,7 @@ class Array(T) # a[6..10]? # => nil # a[6..]? # => nil # ``` - def []?(range : Range) + def []?(range : Range) : Array(T)? self[*Indexable.range_to_index_and_count(range, size) || return nil]? end diff --git a/src/bit_array.cr b/src/bit_array.cr index f435c70840ff..e3a1f44c9f57 100644 --- a/src/bit_array.cr +++ b/src/bit_array.cr @@ -84,7 +84,7 @@ struct BitArray # ba[5..10] # => BitArray[] # ba[-2...-1] # => BitArray[0] # ``` - def [](range : Range) + def [](range : Range) : BitArray self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new] end @@ -109,7 +109,7 @@ struct BitArray # ba[1, 2] # => BitArray[01] # ba[5, 1] # => BitArray[] # ``` - def [](start : Int, count : Int) + def [](start : Int, count : Int) : BitArray raise ArgumentError.new "Negative count: #{count}" if count < 0 if start == size From dea11d99c1d3b558bf98ed8cd28fb93a91814e4c Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Fri, 4 Jun 2021 19:35:13 +0200 Subject: [PATCH 4/4] Replace now-clashing `self` annotations --- src/array.cr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/array.cr b/src/array.cr index b8639c696c80..301b93edd000 100644 --- a/src/array.cr +++ b/src/array.cr @@ -637,7 +637,7 @@ class Array(T) # a[-2..1] # => [] # a[3..-4] # => [] # ``` - def [](range : Range) : self + def [](range : Range) : Array(T) self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new] end @@ -648,7 +648,7 @@ class Array(T) # a[6..10]? # => nil # a[6..]? # => nil # ``` - def []?(range : Range) : self | Nil + def []?(range : Range) : Array(T)? self[*Indexable.range_to_index_and_count(range, size) || return nil]? end @@ -668,12 +668,12 @@ class Array(T) # a[5, 1] # => [] # a[6, 1] # raises IndexError # ``` - def [](start : Int, count : Int) : self + def [](start : Int, count : Int) : Array(T) self[start, count]? || raise IndexError.new end # Like `#[](Int, Int)` but returns `nil` if the *start* index is out of range. - def []?(start : Int, count : Int) : self | Nil + def []?(start : Int, count : Int) : Array(T)? raise ArgumentError.new "Negative count: #{count}" if count < 0 return Array(T).new if start == size