JoshCheek / seeing_is_believing

Displays the results of every line of code in your file
1.3k stars 54 forks source link

Multiline error messages should start on their own line #133

Open JoshCheek opened 6 years ago

JoshCheek commented 6 years ago

Here I wound up adding a newline to the beginning of the error message, but really, multiline errors (or possibly all errors?) should begin on their own line, rather than trying to put them inline with the error class. (in the example, the expectation is wrong, I made it wrong in order to test the failure case feedback before turing my examples into tests and refactoring the code)

def each(num_positions, num_insertions, &block)
  return if num_positions == 0 || num_insertions == 0

  # if num_positions == 1 # => false, true, false, false
  #   num_positions  # => 1
  #   num_insertions # => 1
  #   1.times do |i|
  #     block.call [i] * num_insertions
  #   end
  #   return
  # end

  if num_insertions == 1 # => false, true, true
    num_positions.times do |i|
      block.call [i]
    end
    return
  end

  num_positions.times do |i|
    each i+1, num_insertions-1 do |sub_answers|
      block.call [i, *sub_answers]
    end
  end
end

at_exit do
  assert 2, 2, [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 2]] # => RuntimeError: \nExpected: [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 2]]\nActual:   [[0, 0], [1, 0], [1, 1]]
end

def assert(pos, ins, expected)
  actual = to_enum(:each, pos, ins).to_a
  return true if actual == expected
  raise RuntimeError, "\nExpected: #{expected.inspect}\nActual:   #{actual.inspect}", caller
end

# => :assert

# !> program.rb:28:in `block in <main>':  (RuntimeError)
# !> Expected: [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 2]]
# !> Actual:   [[0, 0], [1, 0], [1, 1]]

# ~> RuntimeError
# ~> 
# ~> Expected: [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 2]]
# ~> Actual:   [[0, 0], [1, 0], [1, 1]]
# ~>
# ~> program.rb:28:in `block in <main>'
__END__

# .X | 0
# X. | 1
each 2, 1 do |nums|
  nums # => [0], [1]
end

# .XX | 0
# X.X | 1
# XX. | 2
each 3, 1 do |nums|
  nums # => [0], [1], [2]
end

# .. | 0,0
each 1, 2 do |nums|
  nums # => [0, 0]
end

# ..X | 0,0
# .X. | 1,0
# X.. | 1,1
each 2, 2 do |nums|
  nums # => [1, 0]
end

return
# ..XX | 0,0
# .X.X | 1,0
# X..X | 1,1
# .XX. | 2,0
# X.X. | 2,1
# XX.. | 2,2
each 3, 2 do |nums|
  nums # => 
end

__END__
(1)(8)(0) 6 8 0   | 0,0,0
(1)(8) 6 (0) 8 0  | 1,0,0
(1) 6 (8)(0) 8 0  | 1,1,0
6 (1)(8)(0) 8 0   | 1,1,1
(1)(8) 6 8 (0) 0  | 2,0,0
(1) 6 (8) 8 (0) 0 | 2,1,0
6 (1)(8) 8 (0) 0  | 2,1,1
(1) 6 8 (8)(0) 0  | 2,2,0
6 (1) 8 (8)(0) 0  | 2,2,1
6 8 (1)(8)(0) 0   | 2,2,2
JoshCheek commented 6 years ago

This is where I was going with it:

def each(num_positions, num_insertions)
  if num_insertions <= 0
    yield []
    return
  end
  num_positions.times do |p|
    each(p+1, num_insertions-1) { |rest| yield [p, *rest] }
  end
end

at_exit do
  assert 1, 1, [[0]]                                            # => true
  assert 1, 2, [[0, 0]]                                         # => true
  assert 2, 1, [[0], [1]]                                       # => true
  assert 2, 2, [[0, 0], [1, 0], [1, 1]]                         # => true
  assert 3, 1, [[0], [1], [2]]                                  # => true
  assert 3, 2, [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 2]] # => true
end

def assert(pos, ins, expected)
  actual = to_enum(:each, pos, ins).to_a
  return true if actual == expected
  raise RuntimeError, "\nExpected: #{expected.inspect}\nActual:   #{actual.inspect}", caller
end

bitmoji