[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Proc metaprogramming tricks?

Adam Skobi

10/19/2008 5:00:00 PM

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?

--
Adam Skobi


7 Answers

Trans

10/19/2008 8:50:00 PM

0



On Oct 19, 1:00=A0pm, Adam Skobi <dxm...@gmail.com> wrote:
> Hi,
>
> I'm building a DSL and trying some weird syntax structures. My DSL
> should look like this.

=A0 def dsl(&block)
=A0 =A0 C.module_eval(&block)
=A0 end

T.

Adam Skobi

10/19/2008 9:19:00 PM

0

=0D=0A>> I'm building a DSL and trying some weird syntax structures. My DSL
>> should look like this.

> =A0 def dsl(&block)
> =A0 =A0 C.module_eval(&block)
> =A0 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 :-)

--=20
Adam Skobi


Mikael Høilund

10/19/2008 9:31:00 PM

0

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.


Adam Skobi

10/19/2008 9:41:00 PM

0


> 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.)?

--
Adam Skobi


Mikael Høilund

10/19/2008 9:49:00 PM

0

On Oct 19, 2008, at 23:40, Adam Skobi wrote:

>
>> 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.)?
>

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 Skobi
>
>

--
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
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


Trans

10/20/2008 2:41:00 AM

0



On Oct 19, 5:18=A0pm, Adam Skobi <dxm...@gmail.com> wrote:
> >> I'm building a DSL and trying some weird syntax structures. My DSL
> >> should look like this.
> > =A0 =A0 def dsl(&block)
> > =A0 =A0 =A0 C.module_eval(&block)
> > =A0 =A0 end
>
> Well yeah, that would work. But I was thinking about something more
> general.
>
> class Root
> =A0 def dsl(&block)
> =A0 =A0 instance_eval(&block)
> =A0 end
> end
>
> class C
> =A0 #...
> end
>
> class D
> =A0 #...
> end
>
> dsl {
> =A0 met1
>
> =A0 class C1 < C
> =A0 =A0 #...
> =A0 end
>
> =A0 class D1 < D
> =A0 =A0 #...
> =A0 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 =3D Root:C1
D::D1 =3D Root:D1
...

(using const_get and const_set)

T.

Robert Klemme

10/20/2008 8:33:00 AM

0

2008/10/19 Adam Skobi <dxm997@gmail.com>:
>
>> 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.)?

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 = ::A::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

--
remember.guy do |as, often| as.you_can - without end