Hypothetical example of nested methods in Ruby. Really just intended to be an example, the actual syntax and implications would need more thought than I've put into it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# hypothetical implementation of nested methods | |
module Tetris | |
extend self | |
def add_block(board, block_definition, x, y=nil) | |
block_height = block_definition.height_for_rotation(0) | |
y ||= board.height + block_height | |
is_within_board_width! | |
is_not_below_board! | |
board.dup { |new_board| new_board.current_block = block_placed_on_board } | |
def is_within_board_width! | |
board_bounds = 0...board.width | |
return if board_bounds.include? x | |
raise ArgumentError, "#{x.inspect} not in board width: #{board_bounds.inspect}" | |
end | |
def is_not_below_board! | |
return unless (y - block_height + 1) < 0 | |
raise ArgumentError, "#{y.inspect} for block of height #{block_height} goes below the bottom of the board." | |
end | |
def block_placed_on_board | |
BlockOnBoard.new do |block| | |
block.block_definition = block_definition | |
block.rotation = 0 | |
block.x = x | |
block.y = y | |
end | |
end | |
end | |
end | |
Tetris.instance_methods.include? :add_block # => true | |
Tetris.instance_methods.include? :block_on_board # => false | |
Tetris.instance_method(:block_on_board).nested_methods # => [:is_within_board_width!, :is_not_below_board!, :block_placed_on_board] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is how this would currently be done (there's a number of ways, this is actually just one of them) | |
module Tetris | |
class AddBlock | |
def self.call(*args) | |
new(*args).call | |
end | |
def initialize(board, block_definition, x, y=nil) | |
self.board = board | |
self.block_definition = block_definition | |
self.x = x | |
self.block_height = block_definition.height_for_rotation(0) | |
self.y = y || (board.height + block_height) | |
end | |
def call | |
is_within_board_width! | |
is_not_below_board! | |
board.dup { |new_board| new_board.current_block = block_placed_on_board } | |
end | |
private | |
attr_accessor :board, :block_definition, :block_height, :x, :y | |
def is_within_board_width! | |
board_bounds = 0...board.width | |
return if board_bounds.include? x | |
raise ArgumentError, "#{x.inspect} not in board width: #{board_bounds.inspect}" | |
end | |
def is_not_below_board! | |
return unless (y - block_height + 1) < 0 | |
raise ArgumentError, "#{y.inspect} for block of height #{block_height} goes below the bottom of the board." | |
end | |
def block_placed_on_board | |
BlockOnBoard.new do |block| | |
block.block_definition = block_definition | |
block.rotation = 0 | |
block.x = x | |
block.y = y | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment