Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Created February 11, 2014 00:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/8927406 to your computer and use it in GitHub Desktop.
Save JoshCheek/8927406 to your computer and use it in GitHub Desktop.
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.
# 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 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