Compiler patch for runtime reflection

Robert Jacques sandford at jhu.edu
Mon Oct 24 08:37:32 PDT 2011


On Mon, 24 Oct 2011 03:30:02 -0400, Jacob Carlborg <doob at me.com> wrote:
> On 2011-10-23 20:54, Robert Jacques wrote:
>> On Sun, 23 Oct 2011 13:48:03 -0400, Jacob Carlborg <doob at me.com> wrote:
>>> On 2011-10-23 18:03, Robert Jacques wrote:
>>>> On Sun, 23 Oct 2011 07:06:42 -0400, Timon Gehr <timon.gehr at gmx.ch>
>>>> wrote:
>>>> [snip]
>>>>> The module can generate RTTI for all types recursively from the
>>>>> starting
>>>>> point iff that information is statically available. It does not have to
>>>>> be. A module that comes as .di + static library binary could return a
>>>>> reference to a private class that has a publicly exported base class.
>>>>> How would you generate RTTI for a statically invisible class?
>>>>
>>>> You're not supposed to be able to. Runtime reflection should only apply
>>>> to public data members.
>>>
>>> It's not enough. Take this for example:
>>>
>>> class Foo < ActiveRecord::Base
>>> before_save :bar
>>>
>>> private
>>>
>>> def bar
>>> end
>>> end
>>>
>>> The above code is an example from Ruby on Rails. The "before_save" call
>>> sets up a callback, "bar", that will called before saving the model. The
>>> callback method will be called using reflection.
>>
>> Using a short, cryptic stub from another programming language is not an
>> effective communication tool. Case in point: all I understand is that
>> something is returning a delegate to something, and reflection never
>> enters the picture.
>
> What's happening is that the class method "before_save" is called with
> the symbol (think string) "bar". Then later ActiveRecord::Base will call
> the method corresponding to the string "bar" using reflection.
>
> In D you would proabably do something like:
>
> class Foo : ActiveRecord.Base
> {
>      private void bar () {}
>
>      mixin beforeSave!(bar);
> }
>
> Now you still won't be able to call "bar" outside "Foo" if "bar" is private.

Thanks. But how does super know to call "bar"? And if you can pass information to super, couldn't you just pass a delegate? And isn't passing information to super simply passing information to yourself?

>> But, for sake of argument, let me assume that ActiveRecord needs to
>> reflect Foo for rails to work (i.e. ActiveRecord::Base's ctor reflects
>> this). At a very fundamental level, this isn't an argument for or
>> against RTTI in D; in D you'd do this with a mixin of some sort. When
>> looking a use cases/features from other languages, always remember to
>> first ask oneself a) how would I do it in D today? b) Is language X's
>> solution 'better, faster, stronger' in some way?
>
> You can think of it like this, just because you haven't come up with a
> reason for calling privte methods using reflection doesn't mean anyone
> else won't come up with a good reason. I tried here to give a reason.

I'm sorry if I've come across that way. I'm well aware with the reasons for wanting access to private methods/fields via reflection and have mentioned them in previous posts. What I've tried to point out is very eloquently stated by fig. 6.3 on page 204 of TDPL: allowing reflection to bypass protection guarantees essentially makes all declarations public in nature, if not extern. That's a very heavy price to pay, just from a program maintenance perspective. And if you consider someone writing medical or financial software, the privacy concerns of exposing private variable to all become very real.

Back to my actual argument, what I was pointing out was that the toolboxes of various languages differ heavily. Just because Ruby has a very cool library which uses runtime reflection, one shouldn't simply state 'D must have runtime reflection.' One needs to first decompose what the library is trying to achieve from the language mechanisms used to implement it. Then you can ask yourself 1) Can I do that in D? 2) How does D's solution compare to Ruby's?

My impression of what ActiveRecord, (which my be wrong), is that its using runtime-reflection to do various meta-programming activities and that under-the-hood, it stretching Ruby to the breaking point in order to do so. D, on the other hand, has a ton of meta-programming specific features, and doesn't need to rely on reflection to do so. This is partly to do with Ruby supporting 'eval' and thus making no distinction between compile-time and run-time behavior; that's correct for Ruby, but D is a different kettle of fish.

>> I mean, considering that Ruby is a dynamic language, would bar even be
>> considered private from inside the super-class's ctor? Is Ruby's private
>> even comparable to D's private? Given that Ruby, by design, requires
>> fields to be private and for all external accesses to happen via
>> methods, should we consider a way to violate that contract an example of
>> mis-feature?
>
> There is no constructor involved here. "before_save" is class method
> called when the class "Foo" is loaded.

So it's the static ctor, then.

> You can do basically whatever you want with the code in Ruby. You can
> replace an existing method/class in the standard library with your own.
> You can easily add methods to existing classes. It's the programmer that
> is responsible to not mess up things, just as in D where you can cast
> away immutable, shared and do unsafe things with pointers.

Well one one hand, none of those things are allowed in SafeD (And you know, that's not a resounding argument for reflection of private members). On the other, you didn't answered my other two questions. In fact, the impression I'm getting is that Ruby's private isn't comparable to D's private.


More information about the Digitalmars-d mailing list