From: Caleb Clausen Date: 2008-11-03T22:59:07+09:00 Subject: Re: [ANN] RubyMacros 0.1.0 Released On 11/3/08, ara.t.howard wrote: > i wouldn't strictly agree with your analysis, but i do agree that it's > very hard to do so. the key is having a context or marker which > allows the method to be safely used on all objects, this is what tagz > does for html/xml generation to avoid this - basically methods called > on any 'self' have easy access to the caller. for instance > > class Object > def LikeRegexp > LikeRegexpObject.new(self) > end > ed > > LikeRegexp.match ..... Ok, maybe I'm just being really dense here, but how does that help with setting the caller's $~? LikeRegexpObject has a reference to its caller's self (clever trick for that, yet again), which surely is useful for mucking with the caller's instance variables.... but locals? Binding.of_caller solves this, of course. > is one workaround. i do clearly see the value of being inside an > object though. however, is the implication that all macros are global? At the moment, yes. I want to have macros be scoped (statically) to the class or module they are defined in. (And then maybe a facility to import them to another class....) But for now, all macros are effectively globals. The lack of scoping is one of the reasons I consider the current implementation a toy. > def __DIR__ > filename = caller[0][/^(.*):/, 1] > File.expand_path(File.dirname(filename)) > end Whoa. Good one. I guess you don't need a macro for that.... :( >> Another recent request was a 'with' keyword, which operates like >> instance_eval, but only changes the default receiver for code in the >> block passed in, and not self as seen by instance variables. I have an >> implementation of this as well (in the example directory of >> RubyMacros), but for various reasons I'm unsatisfied with it right >> now, so I'd rather not post it. >> > > > def with &block > scope = Scope.new > > instance_variables.each do |ivar| > scope.instance_variable_set ivar, instance_variable_get(ivar) > end > > scope.instance_eval &block > end > > hacky? yes. but it works well enough for ActionView... This looks like its the implements the complement of my with; instance variables of the current self are available in the block, but methods on the current self aren't. So now you'll no doubt come up with a clever implementation of the other semantics, knocking down another of my use cases.... Maybe I'll even have a crack at it myself: def with(oldobj,&block) #UNTESTED obj=oldobj.class.allocate .... #some magic to forward obj's method calls to oldobj obj.instance_eval &block end I still like the macro better, tho. > well now that's something everyone can agree on! seriously, the > project looks super interesting - just trying to think of a real use > case. iterate, from lisp. > hrrrrm. could we possibly use it to skin the > > self.ivar = value > > problem? As Pit Capitain pointed out, once you have parse trees, it's fairly easy to rewrite them in whatever way you want. This feature should definitely be possible as a macro. The trick is to get it to control the syntax tree at a high enough level....