Skip to content

Instantly share code, notes, and snippets.

@corbanbrook
Created October 28, 2009 00:14
Show Gist options
  • Save corbanbrook/220101 to your computer and use it in GitHub Desktop.
Save corbanbrook/220101 to your computer and use it in GitHub Desktop.
N-Dimensional list comprehension
# N-Dimensional list comprehension
module Kernel
def list &block
Comprehension::List.new &block
end
end
module Comprehension
class List
def initialize &block
@result = []
@expression = block if block_given?
@variables = Object.new
# creates a basic struct pattern
def @variables.add_to_scope sym
metaclass = class << self; self; end
metaclass.send :attr_accessor, sym
end
def @variables.set sym, value
self.send "#{sym}=".to_sym, value
end
end
def for ranges, &condition
first_range = ranges.values.first.to_a
if ranges.length > 1
@matrix = first_range.product(*ranges.values[1...ranges.length].collect { |r| r.to_a })
else
@matrix = first_range.product
end
ranges.keys.each { |sym| @variables.add_to_scope sym }
@matrix.each do |tuple|
ranges.keys.each_with_index do |sym, i|
@variables.set sym, tuple[i]
end
if block_given?
@result << @variables.instance_eval(&@expression) if @variables.instance_eval(&condition)
else
@result << @variables.instance_eval(&@expression)
end
end
@result
end
end
end
p list { x * y }.for(:x => 0...3, :y => 0...3) { x != 0 and y != 0 })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment