# Proc metaprogramming tricks?

**URL:** <https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282>\
**Category:** Ruby\
**Created:** [October 19, 2008, 7:01pm UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282 "2008-10-19T19:01:42Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![asetzler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@asetzler](https://www.ruby-forum.com/u/asetzler)\
**Post date:** [October 19, 2008, 7:01pm UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282/1 "2008-10-19T19:01:42Z")

</div>

Hi,

I’m building a DSL and trying some weird syntax structures. My DSL  
should look like this.

class Root  
def dsl(&block)  
instance\_eval(&block)  
end  
end

class C  
#…  
end

#DSL

dsl {  
met1

class C1 \< C  
#…  
end

met2  
}

Is there a way that the class C1 won’t be defined inside class Root  
but inside C (or somewhere else)? Maybe there is a trick in Ruby (hook  
method?) so that the class C1 won’t be created in Root at all and than  
I could pass the block somewhere else for creation?

---

<div class="post-metadata">

**Author:** ![asetzler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@asetzler](https://www.ruby-forum.com/u/asetzler)\
**Post date:** [October 19, 2008, 10:51pm UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282/2 "2008-10-19T22:51:33Z")

</div>

On Oct 19, 1:00 pm, Adam S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hi,
> 
> I’m building a DSL and trying some weird syntax structures. My DSL  
> should look like this.

```
def dsl(&block)
  C.module_eval(&block)
end

```

T.

---

<div class="post-metadata">

**Author:** ![asetzler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@asetzler](https://www.ruby-forum.com/u/asetzler)\
**Post date:** [October 19, 2008, 11:24pm UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282/3 "2008-10-19T23:24:59Z")

</div>

> > I’m building a DSL and trying some weird syntax structures. My DSL  
> > should look like this.

> ```
> def dsl(&block)
> C.module_eval(&block)
> end
> 
> ```

Well yeah, that would work. But I was thinking about something more  
general.

class Root  
def dsl(&block)  
instance\_eval(&block)  
end  
end

class C  
#…  
end

class D  
#…  
end

dsl {  
met1

class C1 \< C  
#…  
end

class D1 \< D  
#…  
end

}

Can I run part of the Proc in the context of C and part in the  
context of D i.e. can I somehow split the Proc or convert it to a  
readable String?

The more I think about it, the more absurd the reasoning behind it  
seems. But since I’m at it, I may as well continue the debate 🙂

---

<div class="post-metadata">

**Author:** ![asetzler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@asetzler](https://www.ruby-forum.com/u/asetzler)\
**Post date:** [October 19, 2008, 11:33pm UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282/4 "2008-10-19T23:33:11Z")

</div>

class C  
def self.inherited(klass)  
klass\_name = klass.name[/[^:]+$/]  
klass.to\_s.split(/::/)[0…-1].inject(Object) { |const, name|  
const.const\_get name  
}.send :remove\_const, klass\_name  
C.const\_set klass\_name, klass  
end  
end

NB: Don’t do this.

---

<div class="post-metadata">

**Author:** ![asetzler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@asetzler](https://www.ruby-forum.com/u/asetzler)\
**Post date:** [October 19, 2008, 11:42pm UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282/5 "2008-10-19T23:42:33Z")

</div>

> class C  
> def self.inherited(klass)  
> klass\_name = klass.name[/[^:]+$/]  
> klass.to\_s.split(/::/)[0…-1].inject(Object) { |const, name|  
> const.const\_get name  
> }.send :remove\_const, klass\_name  
> C.const\_set klass\_name, klass  
> end  
> end

> NB: Don’t do this.

Yes! Why haven’t I thought of this solution?!  
Thanks for that one.

Are the any non obvious reasons as why not to do this type of trick  
(code obfuscation, maintance hell etc.)?

---

<div class="post-metadata">

**Author:** ![asetzler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@asetzler](https://www.ruby-forum.com/u/asetzler)\
**Post date:** [October 19, 2008, 11:50pm UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282/6 "2008-10-19T23:50:11Z")

</div>

On Oct 19, 2008, at 23:40, Adam S. wrote:

> > NB: Don’t do this.
> 
> Yes! Why haven’t I thought of this solution?!  
> Thanks for that one.
> 
> Are the any non obvious reasons as why not to do this type of trick  
> (code obfuscation, maintance hell etc.)?

That, and

–8\<----  
class Ddddd \< C  
end

Ddddd.some\_method # !\> NameError  
–8\<----

Also, my roommate laughed uncontrollably the whole time I wrote that  
snippet.

> –  
> Adam S.

–  
a,b=%Q=Z,O^NPO\r4\_PV\PI\x15^-\x0\v=,email=%%%%c%115%%# Mikael  
Hoilund, CTO  
okay=%#;hmm=(0…a.size).map{|i|((a[i]-email[i]+2)%128).# of [Meta.io](http://Meta.io)  
ApS from  
chr}.join;!email.gsub!‘o’,“%c%c”%[3+?0.\<\<(2),?G.~@];aha=#############  
Denmark  
hmm.scan(/#{‘(.)’\*5}/);!puts(email[1…-12]+aha.shift.zip(\*aha).join)#  
Ruby \<3

---

<div class="post-metadata">

**Author:** ![asetzler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@asetzler](https://www.ruby-forum.com/u/asetzler)\
**Post date:** [October 20, 2008, 4:42am UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282/7 "2008-10-20T04:42:38Z")

</div>

On Oct 19, 5:18 pm, Adam S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> def dsl(&block)  
> end  
> end
> 
> }
> 
> Can I run part of the Proc in the context of C and part in the  
> context of D i.e. can I somehow split the Proc or convert it to a  
> readable String?
> 
> The more I think about it, the more absurd the reasoning behind it  
> seems. But since I’m at it, I may as well continue the debate 🙂

You can just allow them to be defined in Root and then use #inherited  
to set

C::C1 = Root:C1  
D::D1 = Root:D1  
…

(using const\_get and const\_set)

T.

---

<div class="post-metadata">

**Author:** ![asetzler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@asetzler](https://www.ruby-forum.com/u/asetzler)\
**Post date:** [October 20, 2008, 10:34am UTC](https://www.ruby-forum.com/t/proc-metaprogramming-tricks/151282/8 "2008-10-20T10:34:56Z")

</div>

2008/10/19 Adam S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > NB: Don’t do this.
> 
> Yes! Why haven’t I thought of this solution?!  
> Thanks for that one.
> 
> Are the any non obvious reasons as why not to do this type of trick  
> (code obfuscation, maintance hell etc.)?

Yes, there’s a reason: it does not work:

10:17:43 Temp$ ruby mod.rb  
initial  
A::X  
A::X  
after remove  
A::X  
A::X  
after set  
A::X  
A::X  
10:17:51 Temp$ cat mod.rb  
module A  
class X  
end  
end  
$cl = :🅰:X  
puts “initial”, $cl, $cl.name  
A.send :remove\_const, ‘X’  
puts “after remove”, $cl, $cl.name  
module B  
end  
B.send :const\_set, ‘Y’, $cl  
puts “after set”, $cl, $cl.name  
10:18:08 Temp$

Here’s one way to do it:

class Root

# features all objects of dsl share

class Object  
def my\_name  
# silly example  
self.class.name  
end  
end

class \<\<self  
def class\_def(name, parent = Object, &b)  
parent = const\_get(parent) unless Module === parent  
cl = Class.new parent  
const\_set name, cl  
cl.class\_eval(&b)  
cl  
end  
end  
end

def Object.const\_missing(sym)  
Root.send :const\_get, sym  
end

def dsl(&b)  
Root.class\_eval(&b)  
end

dsl {  
class\_def :Base do  
def hello() puts “Hello, I am #{my\_name}.” end  
end

class\_def :Derived, Base do  
# nothing here  
end

Derived.new.hello

p Derived.ancestors  
}

Cheers

robert
