G
George Moschovitis
Hello everyone,
one of the features of the LISP family of languages that is missing from
Ruby are macros. I think they are useful on a lot of occasions so
I would like to see Ruby support macros in the future.
However i think it is quite easy to emulate some form of macro
functionality in Ruby. Here is some simple code:
macros.rb:
----------
$__macros__ = {}
$__required__ = {}
module Kernel
alias_method ld_require, :require
def require(path)
return if $__required__[path]
source = open(path) { |f|
f.sysread(f.stat().size())
}
# parse macro
source.gsub!(/defmacro\s*\/(.*?)\/\s(.*?)endmacro/m) {
$__macros__[Regexp.new($1)] = $2 ; ""
}
# expand macros
$__macros__.each { |match, replace|
source.gsub!(match, replace)
}
$__required__[path] = true
eval(source)
end
end
require "test1.rb"
require "test2.rb"
test1.rb:
---------
defmacro /my_macro\((.*)\)/
begin
my_function(\1)
rescue => ex
puts ex
end
endmacro
# php style foreach
defmacro /foreach\s*\((.*)\s*as(.*)\)/
for \2 in \1
endmacro
def my_function(str)
puts str
end
class TestClass
def another_test
words = %w{ simple test }
foreach(words as word)
puts k
end
end
end
test2.rb:
---------
value = "Hello World!"
my_macro(value)
numbers = [1, 2, 3, 4]
foreach (numbers as i)
puts i
end
a = TestClass.new
a.another_test()
Once again i was suprised to find out that Ruby is so powerful!
However I would like to hear your opinion on this code. Is there any
problem I have overlooked? Is there a better implementation? Could this
be better designed?
If anyone finds it usefull I could create a small package with
doc+examples and upload it to RAA.
have fun,
George Moschovitis
one of the features of the LISP family of languages that is missing from
Ruby are macros. I think they are useful on a lot of occasions so
I would like to see Ruby support macros in the future.
However i think it is quite easy to emulate some form of macro
functionality in Ruby. Here is some simple code:
macros.rb:
----------
$__macros__ = {}
$__required__ = {}
module Kernel
alias_method ld_require, :require
def require(path)
return if $__required__[path]
source = open(path) { |f|
f.sysread(f.stat().size())
}
# parse macro
source.gsub!(/defmacro\s*\/(.*?)\/\s(.*?)endmacro/m) {
$__macros__[Regexp.new($1)] = $2 ; ""
}
# expand macros
$__macros__.each { |match, replace|
source.gsub!(match, replace)
}
$__required__[path] = true
eval(source)
end
end
require "test1.rb"
require "test2.rb"
test1.rb:
---------
defmacro /my_macro\((.*)\)/
begin
my_function(\1)
rescue => ex
puts ex
end
endmacro
# php style foreach
defmacro /foreach\s*\((.*)\s*as(.*)\)/
for \2 in \1
endmacro
def my_function(str)
puts str
end
class TestClass
def another_test
words = %w{ simple test }
foreach(words as word)
puts k
end
end
end
test2.rb:
---------
value = "Hello World!"
my_macro(value)
numbers = [1, 2, 3, 4]
foreach (numbers as i)
puts i
end
a = TestClass.new
a.another_test()
Once again i was suprised to find out that Ruby is so powerful!
However I would like to hear your opinion on this code. Is there any
problem I have overlooked? Is there a better implementation? Could this
be better designed?
If anyone finds it usefull I could create a small package with
doc+examples and upload it to RAA.
have fun,
George Moschovitis