Groovy instance.metaclass vs this.metaclass - gradle

I have a following script:
task myTask {}
class Person {
Person() {
Person instance = this
println this.metaClass.class.name
println this.getMetaClass().class.name
println instance.metaClass.class.name
println instance.getMetaClass().class.name
}
}
Person person = new Person()
And the output is :
groovy.lang.MetaClassImpl
groovy.lang.MetaClassImpl
org.codehaus.groovy.runtime.HandleMetaClass
org.codehaus.groovy.runtime.HandleMetaClass
Can anyone explain to me what is going on?
Thanks in advance.

Take a look at this class,
class Person {
def a, b
Person() {
a = this
b = this
println "this $this"
println "a $a"
println "b $b"
}
def printAll() {
println "this.metaClass ${this.metaClass}"
println "this.class.metaClass ${this.class.metaClass}"
println "a.metaClass ${a.metaClass}"
println "b.metaClass ${b.metaClass}"
}
}
Take a look at the screenshot of the groovysh. It might give you a little hint about what's going on.
p and q are two different objects, but
p.metaClass is the same as q.metaClass, and
printAll prints exactly the same thing for both, p and q
a.metaClass and b.metaClass are holding this.class.metaClass, not this.metaClass, you see
There is only one object created of MetaClassImpl, and also only one of HandleMetaClass, for Person. And no matter how many times you instantiate Person, they will be assigned to the instance. But, when you expand any of that instance, only then a new HandleMetaClass object will be created -- just for that particular object; and this time HandleMetaClass will be holding not MetaClassImpl, but ExpandoMetaClass instead.
See the screenshot below,
Now, to answer your question, this.metaClass is a special case, like this itself. It doesn't give you the handle, HandleMetaClass object, so you can't expand over metaClass of this -- directly; and there is no sense in that either, because then all other future instances will share that expansion.
If you really want that behaviour then you can pass this to some other variable, i.e. instance = this, as you did in the constructor, and then you can expand over that instance -- and that expansion would be true for this and all other future instances. But then, why not add the behaviour to class itself, in the first place. Why expand?

Related

How can I get argument values for a given lambda from the outside, without explicitly returning its `binding`?

I want to be able to run a lambda and get at its argument values (the values of a and b below).
I can achieve this by explicitly having the lambda return a binding, and then getting the values out of this binding:
fun = lambda { |a, b = Time.now| binding }
fun_binding = fun.call(123)
puts "A is #{fun_binding.local_variable_get(:a)} and B is #{fun_binding.local_variable_get(:b)}"
# Outputs e.g.: A is 123 and B is 2022-04-29 20:14:07 +0200
Is it possible to get these values without running any code inside the lambda body? I.e. could I do
fun = lambda { |a, b = Time.now| }
fun.call(123)
and still get the a and b values somehow from outside the lambda?
(To provide context – I'm asking because I've experimented with this as a shortcut syntax for instantiating objects with ivars/readers automatically assigned. At this stage I'm more curious about what's possible than what is advisable – so I invite any solutions, advisable or not…)
I'm not sure how advisable this is, but you can use the TracePoint class with the :b_call event to grab the lambda's binding:
fun = lambda { |a, b = Time.now| }
fun_binding = nil
TracePoint.trace(:b_call) do |tp|
fun_binding = tp.binding
tp.disable
end
fun.call(123)
puts "A is #{fun_binding.local_variable_get(:a)} and B is #{fun_binding.local_variable_get(:b)}"
This is not a perfect solution and will fail if one of the argument default values enters a block on it's own (since the default values are evaluated before the :b_call event is fired for the lambda), but that could be fixed with some additional filtering inside the TracePoint handler.

let! vs let and before in Rspec

In Rspec, let uses lazy instantiation so let(:foo) { create(...) } isn't initialised until something calls it. Usually this is good, because it is only used when needed and makes rspec testing times much quicker.
Occasionally however you will have a spec that needs that variable but doesn't explicitly call it. So with lazy instantiation, the spec will fail.
A solution is with a bang! let!(:foo) { create(...) } will force that the variable is initialised.
Some developers seem to be very against this and prefer:
let(:foo) { create(...) }
before do
foo
end
to force the initialisation.
Is there a reason for this? is there any difference between the two methods?
I can think of one difference: before blocks would compound, and you can overwrite let! with let and vice versa. I'll give you an example:
context do
let!(:foo) { create(:foo) }
let(:bar) { create(:bar) }
before { bar }
context do
# if in this context you wish to switch back to "lazy" versions you can
# do that for :foo, just do:
let(:foo) { create(:foo) }
# but you can't "undo" before, even if you define an empty one:
before { }
# it does not cancel the `before` blocks defined in higher contexts
end
end
Edit: I just realized this does not really answer the question why someone would prefer before to let!. Maybe: as mentioned in comments the order is different, but if you depend on such nuance in your specs - it's already too complicated.
Many situations is a matter of style, and the developer is not full aware of main functionalities of RSpec and many times people just don't make sense. Humans are not machines, and specially under time pressure, developers do things that they wouldn't do in ideal conditions :).
But the both cases presented they are not strictly the same.
For example, if you are using subject, it is evaluated in a before hook before the let! initialization and not inside it. I didn't test, but I believe these cases should show the diffs:
let!(:car) { create(:car) }
let(:driver) { create(:driver) }
subject { driver.car() }
it { expect(subject).to eq car } # Fail:
This forces car being created before and being available for subject:
let(:driver) { create(:driver) }
subject { driver.car() }
before { create(:car) }
it { expect(subject).to eq car } # Success

Bindings in Ruby. What is a good way to think of them. What do they contain

I am confused about bindings.
def repl(input_stream, output_stream)
loop do
output_stream.print "> "
input = input_stream.gets()
result = binding.eval(input)
output_stream.puts(result)
end
end
repl($stdin, $stdout)
I am going to call repl with just $stdin and $stdout. I need a dumbed down version of what the line:
binding.eval(input) is doing.
Bindings are just where we currently are in the call stack right? They hold the current local variables? Anything else? What's a good way to think of them differently from the current scope?
Objects of class Binding encapsulate the execution context at some particular place in the code and retain this context for future use. The variables, methods, value of self, and possibly an iterator block that can be accessed in this context are all retained. Binding objects can be created using Kernel#binding, and are made available to the callback of Kernel#set_trace_func.
static VALUE
bind_local_variable_defined_p(VALUE bindval, VALUE sym)
{
ID lid = check_local_id(bindval, &sym);
const rb_binding_t *bind;
if (!lid) return Qfalse;
GetBindingPtr(bindval, bind);
return get_local_variable_ptr(bind->env, lid) ? Qtrue : Qfalse;
}
Here is a example of Public Instance Methods
def get_binding(param)
return binding
end
b = get_binding("hello")
b.eval("param") #=> "hello"

Is there a hook for when anonymous classes are assigned to a constant?

I've been practicing some Ruby meta-programming recently, and was wondering about assigning anonymous classes to constants.
In Ruby, it is possible to create an anonymous class as follows:
anonymous_class = Class.new # => #<Class:0x007f9c5afb21d0>
New instances of this class can be created:
an_instance = anonymous_class.new # => #<#<Class:0x007f9c5afb21d0>:0x007f9c5afb0330>
Now, when the anonymous class is assigned to a constant, the class now has a proper name:
Foo = anonymous_class # => Foo
And the previously created instance is now also an instance of that class:
an_instance # => #<Foo:0x007f9c5afb0330>
My question: Is there a hook method for the moment when an anonymous class is assigned to a constant?
There are many hooks methods in Ruby, but I couldn't find this one.
Let's take a look at how constant assignment works internally. The code that follows is extracted from a source tarball of ruby-1.9.3-p0. First we look at the definition of the VM instruction setconstant (which is used to assign constants):
# /insns.def, line 239
DEFINE_INSN
setconstant
(ID id)
(VALUE val, VALUE cbase)
()
{
vm_check_if_namespace(cbase);
rb_const_set(cbase, id, val);
INC_VM_STATE_VERSION();
}
No chance to place a hook in vm_check_if_namespace or INC_VM_STATE_VERSION here. So we look at rb_const_set (variable.c:1886), the function that is called everytime a constant is assigned:
# /variable.c, line 1886
void
rb_const_set(VALUE klass, ID id, VALUE val)
{
rb_const_entry_t *ce;
VALUE visibility = CONST_PUBLIC;
# ...
check_before_mod_set(klass, id, val, "constant");
if (!RCLASS_CONST_TBL(klass)) {
RCLASS_CONST_TBL(klass) = st_init_numtable();
}
else {
# [snip], won't be called on first assignment
}
rb_vm_change_state();
ce = ALLOC(rb_const_entry_t);
ce->flag = (rb_const_flag_t)visibility;
ce->value = val;
st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
}
I removed all the code that was not even called the first time a constant was assigned inside a module. I then looked into all the functions called by this one and didn't find a single point where we could place a hook from Ruby code. This means the hard truth is, unless I missed something, that there is no way to hook a constant assignment (at least in MRI).
Update
To clarify: The anonymous class does not magically get a new name as soon as it is assigned (as noted correctly in Andrew's answer). Rather, the constant name along with the object ID of the class is stored in Ruby's internal constant lookup table. If, after that, the name of the class is requested, it can now be resolved to a proper name (and not just Class:0xXXXXXXXX...).
So the best you can do to react to this assignment is to check the name of the class in a loop of a background worker thread until it is non-nil (which is a huge waste of resources, IMHO).
Anonymous classes don't actually get their name when they're assigned to a constant. They actually get it when they're next asked what their name is.
I'll try to find a reference for this. Edit: Can't find one, sorry.

A list of predefined groovy variables

I'm new to groovy and I'm wondering where can I find a full list of predefined
groovy variables like it and delegate?
The particular thing that I'm interested in is if there are predefined keyword for
the reference to the object from where the current method was invoked, for example:
5.times { print 5 - it}
with the use of such keyword it should be something like:
5.times { print *keyword* - it }
so the question is what's the keyword should be used there?
P.S.: another example:
MyObject myObject = new myObject();
myObject.getField(); // MyObject has method named getField
myObject.doJob ({
...
((MyObject)*keyword*).getField(); // instead of myObject.getField();
...
})
For a good list of all actual keywords (which are fewer than you'd think) and object-level properties that are like keywords, this article is really good: http://marxsoftware.blogspot.com/2011/09/groovys-special-words.html
If you have control over the doJob method in your example, then you should set the delegate of the closure:
def doJob(Closure closure) {
closure.delegate = this
closure.resolveStrategy = Closure.DELEGATE_FIRST
// loop or whatever
closure()
}
Now, in your closure, you can reference any properties on the parent object directly, like so:
myObject.doJob ({
...
getField()
...
})
Groovy Closures - Implicit Variables.
Are you asking for this?
int number = 5
number.times { print number - it }
Hope this will help you

Resources