Skip to content

Commit

Permalink
Adding initial metaprogramming koans
Browse files Browse the repository at this point in the history
  • Loading branch information
sathish316 committed Aug 28, 2011
1 parent d1494a6 commit e4dff77
Show file tree
Hide file tree
Showing 21 changed files with 1,132 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist
.project_env.rc
.path_progress
*.rbc
.idea
3 changes: 0 additions & 3 deletions koans/path_to_enlightenment.rb

This file was deleted.

File renamed without changes.
62 changes: 62 additions & 0 deletions src/about_binding.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require File.expand_path(File.dirname(__FILE__) + '/edgecase')

class AboutBinding < EdgeCase::Koan

class Foo
def initialize
@ivar = 22
end

def bar(param)
lvar = 11
binding
end
end

def test_binding_binds_method_parameters
binding = Foo.new.bar(99)
assert_equal 99, eval("param", binding)
end

def test_binding_binds_local_vars
binding = Foo.new.bar(99)
assert_equal 11, eval("lvar", binding)
end

def test_binding_binds_instance_vars
binding = Foo.new.bar(99)
assert_equal 22, eval("@ivar", binding)
end

def test_binding_binds_blocks
binding = Foo.new.bar(99) { 33 }
assert_equal 33, eval("yield", binding)
end

def test_binding_binds_self
foo = Foo.new
binding = foo.bar(99)
assert_equal foo, eval("self", binding)
end

def n_times(n)
lambda {|value| n * value}
end

def test_lambda_binds_to_the_surrounding_context
two_times = n_times(2)
assert_equal 6, two_times.call(3)
end

def count_with_increment(start, inc)
lambda { start += inc}
end

def test_lambda_remembers_state_of_bound_variables
counter = count_with_increment(7, 3)
assert_equal 10, counter.call
assert_equal 13, counter.call
assert_equal 16, counter.call
end

end
60 changes: 60 additions & 0 deletions src/about_blocks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require File.expand_path(File.dirname(__FILE__) + '/edgecase')

class AboutBlocks < EdgeCase::Koan

def test_calling_a_lambda
l = lambda {|a| a + 1}
assert_equal 100, l.call(99)
end

def test_calling_a_proc
p = Proc.new {|a| a + 1}
assert_equal 100, p.call(99)
end

def convert(&block)
block
end

def test_block_is_proc
b = convert {|a| a + 1}
assert_equal Proc, b.class
assert_equal 100, b.call(99)
end

def test_proc_takes_fewer_or_more_arguments
p = Proc.new {|a, b, c| a.to_i + b.to_i + c.to_i}
assert_equal 3 , p.call(1,2)
assert_equal 6, p.call(1,2,3,4)
end

def test_lambda_does_not_take_fewer_or_more_arguments
l = lambda {|a, b, c| a.to_i + b.to_i + c.to_i}
assert_raises(ArgumentError) do
l.call(1, 2)
end

assert_raises(ArgumentError) do
l.call(1,2,3,4)
end
end

def method(lambda_or_proc)
lambda_or_proc.call
:from_method
end

def test_return_inside_lambda_returns_from_the_lambda
l = lambda { return :from_lambda }
result = method(l)
assert_equal :from_method, result
end

def test_return_inside_proc_returns_from_the_context
p = Proc.new { return :from_proc }
result = method(p)
# The execution never reaches this line because Proc returns
# outside the test method
assert_equal __, p.call
end
end
53 changes: 53 additions & 0 deletions src/about_class_as_constant.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require File.expand_path(File.dirname(__FILE__) + '/edgecase')

class AboutClassAsConstant < EdgeCase::Koan

class Foo
def say_hello
"Hi"
end
end

def test_defined_tells_if_a_class_is_defined_or_not
assert_not_nil defined?(Foo)
assert_nil defined?(Bar)
end

def test_class_is_a_constant
assert_equal "constant", defined?(Foo)
end

def test_class_constant_can_be_assigned_to_var
my_class = Foo
assert_equal "Hi", my_class.new.say_hello
end

@@return_value_of_class =
class Baz
def say_hi
"Hello"
end
99
end

def test_class_definitions_are_active
assert_equal 99, @@return_value_of_class
end

@@self_inside_a_class =
class Baz
def say_hi
"Hi"
end
self
end

def test_self_inside_class_is_class_itself
assert_equal Baz, @@self_inside_a_class
end

def test_class_is_an_object_of_type_class_and_can_be_created_dynamically
cls = Class.new
assert_match /Class/, cls.to_s
end
end
27 changes: 27 additions & 0 deletions src/about_class_inheritance.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require File.expand_path(File.dirname(__FILE__) + '/edgecase')

class AboutClassInheritance < EdgeCase::Koan

def test_singleton_class_can_be_used_to_define_singleton_methods
animal = "cat"
class << animal
def speak
"miaow"
end
end
assert_equal "miaow", animal.speak
end

class Foo
class << self
def say_hello
"Hello"
end
end
end

def test_singleton_class_can_be_used_to_define_class_methods
assert_equal "Hello", Foo.say_hello
end

end
23 changes: 23 additions & 0 deletions src/about_class_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require File.expand_path(File.dirname(__FILE__) + '/edgecase')

class AboutClassMethods < EdgeCase::Koan

class Foo
def self.say_hello
"Hello"
end
end

def test_class_is_an_instance_of_class_Class
assert_equal true, Foo.class == Class
end

def test_class_methods_are_just_singleton_methods_on_the_class
assert_equal "Hello", Foo.say_hello
end

def test_classes_are_not_special_and_are_just_like_other_objects
assert_equal true, Foo.is_a?(Object)
assert_equal true, Foo.superclass == Object
end
end
87 changes: 87 additions & 0 deletions src/about_define_method.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
require File.expand_path(File.dirname(__FILE__) + '/edgecase')

class AboutDefineMethod < EdgeCase::Koan

class Example
def start
def stop
:stopped
end
:started
end
end

def test_methods_can_define_other_methods
o = Example.new
assert_raises(NoMethodError) do
o.stop
end

o.start

assert_equal :stopped, o.stop
end

class Example
def foo
def foo
:new_value
end
:first_value
end
end

def test_methods_can_redefine_themselves
o = Example.new
assert_equal :first_value, o.foo
assert_equal :new_value, o.foo
end

class Multiplier
def self.create_multiplier(n)
define_method "times_#{n}" do |val|
val * n
end
end

10.times {|i| create_multiplier(i) }
end

def test_define_method_creates_methods_dynamically
m = Multiplier.new
assert_equal 30, m.times_3(10)
assert_equal 60, m.times_6(10)
assert_equal 90, m.times_9(10)
end

module Accessor
def my_writer(name)
ivar_name = "@#{name}"
define_method "#{name}=" do |value|
#Write code here to set value of ivar
instance_variable_set(ivar_name, value)
end
end

def my_reader(name)
ivar_name = "@#{name}"
define_method name do
#Write code here to get value of ivar
instance_variable_get(ivar_name)
end
end
end

class Cat
extend Accessor
my_writer :name
my_reader :name
end

def test_instance_variable_set_and_instance_variable_get_can_be_used_to_access_ivars
cat = Cat.new
cat.name = 'Fred'
assert_equal 'Fred', cat.name
end
end

Loading

0 comments on commit e4dff77

Please sign in to comment.