Calling ObjectSpace.each_object(Class) does not seem to return any eigenclasses. For example, when investigating Ruby metaclasses: why three when defined singleton methods?, I found that while ObjectSpace.count_objects[:T_CLASS] was getting incremented by 3 in the case of defining a new class with a class method, ObjectSpace.each_object(Class).count was only being incremented by one.
Is there any way to enumerate the eigenclasses active in the system?
Looking at MRI C code, the function ObjectSpace.each_object tests if the object is an internal object and if it is true the object is removed from the iterator.
The test is made by the following function, which consider the classes internally flagged as singleton as an internal object:
static int
internal_object_p(VALUE obj)
{
RVALUE *p = (RVALUE *)obj;
if (p->as.basic.flags) {
switch (BUILTIN_TYPE(p)) {
case T_NONE:
case T_ICLASS:
case T_NODE:
case T_ZOMBIE:
break;
case T_CLASS:
if (FL_TEST(p, FL_SINGLETON)) /* Here */
break;
default:
if (!p->as.basic.klass) break;
return 0;
}
}
return 1;
}
The Ruby EigenClasses are flagged as Singleton, so it will be not returned.
It is important to mention that, the singleton flag used internally by the MRI is different from the Singleton module from standard library.
If you create a class and include the Singleton module on it, it will be returned by the ObjectSpace.each_object method.
Related
Here is the code:
class SomeType {
public:
SomeType() {}
~SomeType() {}
std::string xxx;
}
bool funtion_ab() {
SomeType(); // This is a right val;
// The right val destructs here when I test the code. I want to make sure that it would always destructs here.
int a = 0, b = 10;
....// other code
return true;
}
Please tell me if you know the truth. Thank you!
What you have is called a temporary object. From §6.7.7,
Temporary objects are created
when a prvalue is converted to an xvalue
or, more specifically,
[Note 3: Temporary objects are materialized:
...
when a prvalue that has type other than cv void appears as a discarded-value expression ([expr.context]).
— end note]
and, on the lifetime, the same section has this to say
Temporary objects are destroyed as the last step in evaluating the full-expression ([intro.execution]) that (lexically) contains the point where they were created.
You can read more about the expression semantics, but in your case "full-expression" is fairly unambiguous.
SomeType();
The "full-expression" containing your constructor call is... the constructor call itself. So the destructor will be called immediately after evaluating the constructor. There are some exceptions to this rule (such as if the temporary object is thrown as an exception or is bound as a reference), but none of those apply here.
As noted in the comments, compilers are free to inline your constructor and destructor calls and then are free to notice that they do nothing and omit them entirely. Optimizers can do fun stuff with your code, provided it doesn't change the semantics. But a strict reading of the standard states that the destructor is called exactly where you suggested.
I'm having trouble adding elements to an object that keeps a collection of generic-typed values. I tried a Minimal Working Example that causes the error:
class OneElementQueue {
type eltType;
var elements : [0..0] eltType;
//initializer
proc init(type eltType) {
this.eltType = eltType;
}
proc add(element : eltType) {
this.elements[0] = element;
}
proc remove() : eltType {
return this.elements[0];
}
} //end of OneElementQueue
class Monkey {
var name: string;
var age: int;
proc init(name : string, age : int) {
this.name = name;
this.age = age;
}
} //end of class Monkey
var q = new owned OneElementQueue(Monkey);
var m = new owned Monkey("Kyle", 6);
q.add(m);
When I try to compile all of this, I get an error:
$ chpl BadQueue.chpl
BadQueue.chpl:12: In function 'add':
BadQueue.chpl:13: error: Scoped variable would outlive the value it is set to
BadQueue.chpl:12: note: consider scope of element
$
What is the correct way to go about adding something to a generic data structure like this? How am I going about this the wrong way?
There are two possible approaches you can take here, depending on what behavior you want:
"I want to have my collection take ownership of the Monkey objects"
In this case, you'll want to instantiate your OneElementQueue collection to store owned Monkey objects rather than simply [borrowed] Monkey objects, which is the default for class types. You can do this with the one line change (Try it Online):
var q = new owned OneElementQueue(owned Monkey);
In this approach, passing an owned Monkey to your add() method will pass the ownership to the argument and eventually to the collection, making the original object reference invalid (nil).
"I want to have my collection borrow the existing Monkey objects without taking ownership of them"
In this case, you'll need to tell the add() method that the argument passed into it will outlive the argument itself (and then be sure not to lie about it). In Chapel version 1.19, this can be done via lifetime annotations:
proc add(element : eltType) lifetime element > this {
where the annotation lifetime element > this asserts that the actual argument passed through element will outlive the this collection itself, so the compiler should not fear that the borrow will cease to exist once the formal argument has.
Lifetime annotations were not available in Chapel 1.18, so if you're using that version you need to use a slightly bigger hammer and apply pragma "unsafe" to the method. Note that pragmas are not an officially supported feature and may change in the future, so for this case, served as a stopgap until lifetime annotations had been implemented (Try it Online):
pragma "unsafe"
proc add(element : eltType) {
I have two NSResponder methods (cut, copy) and they have basically the same code except they call their own super. How to create method with parameter _CMD as selector that calls super and I won't end up with recursion?
- (void)copy:(id)sender
{
[self notifyAndPerformSelector:_cmd withObject:sender];
}
- (void)cut:(id)sender
{
[self notifyAndPerformSelector:_cmd withObject:sender];
}
- (void)notifyAndPerformSelector:(SEL)selector withObject:(id)sender
{
[super performSelector:selector withObject:sender];
//code...
}
As you have discovered your code doesn't call the superclass method as you want but the one in the current class, resulting in infinite recursion.
Your first option faced with this is to refactor your code, something along the lines of:
#implementation MyDerivedClass
{
- (void)copy:(id)sender
{
[super copy:sender];
[self commonCodeAfterSelector:_cmd withObject:sender];
}
- (void)cut:(id)sender
{
[super cut:sender];
[self commonCodeAfterSelector:_cmd withObject:sender];
}
- (void)notifyAndPerformSelector:(SEL)selector withObject:(id)sender
{
//code...
}
}
If this approach suits your situation use it. If not...
A second option is to become the compiler...
Standard and super method calls
A standard method call of the form:
[object someMethodWithArg1:x andArg2:y]
invokes a search for the method someMethodWithArg1:andArg2:. This search starts at the runtime class of object. The emphasis on runtime is important, the actual object referenced by object could be of the same class as the declared type of object or and of the subclasses of that type and the search must find the most derived implementation of the method.
A super method call of the form:
[super someMethodWithArg1:x andArg2:y]
also invokes a search for the method someMethodWithArg1:andArg2:. However in this search starts at the compile time class of superclass of the class in which code occurs. For example if MyDerivedClass above is a subclass of MyBaseClass then the search for the method starts at MyBaseClass ignoring the runtime type of self – which could be MyDerivedClass or a subclass of it (say MyDerivedDerivedClass)
Why does your current code recurse?
Your call:
[super performSelector:selector withObject:sender];
starts the search for the method performSelector:withObject: in the superclass, that search won't find the method until it reaches the NSObject class. Once found the method is invoked and starts a standard (not super) search for the method for selector, this search starts at the runtime type of self and so finds the method in MyDerivedClass... recursion.
What you need is something like:
[self performSuperSelector:selector withObject:sender];
but unfortunately that does not exist. But you can make one...
Compiling method calls
The compiler takes a standard method call of the form:
[object someMethodWithArg1:x andArg2:y]
and effectively (we're glossing over a few details, the need ones will get filled in below) compiles this to a call to the runtime function objc_msgSend():
objc_msgSend(object, #selector("someMethodWithArg1:andArg2:"), x, y)
Notice that the selector is passed as a SEL value, this is where the value for _cmd comes from.
A super call of the form:
[super someMethodWithArg1:x andArg2:y]
is effectively compiled to a call to objc_msgSendSuper() of the form:
objc_msgSendSuper(`struct` containing `self` and superclass,
#selector("someMethodWithArg1:andArg2:"), x, y)
You can call these runtime functions directly in your own code. You must import the <objc/objc-runtime.h> to obtain the definitions, cast them to the appropriate type, etc.
Becoming the compiler and bypassing performSelector
Your code uses performSelector as it has a SEL value, but as shown above the runtime calls used for method calling take a SEL directly. If you "compile" the super call yourself you do not need to use performSelector, which in turn avoids the recursion problem.
Before calling objc_msgSendSuper() the function needs to be cast so its return and argument types match the actual return and argument types of the selector you are calling. This is so that the correct code is compiled to handle the arguments and return value, and that code is dependent on the types. The two selectors you are calling, copy: and cut:, have the same type which makes the code shorter. To make the casting easier we first define a shorthand for the type:
typedef void (*CutOrCopyRunner)(struct objc_super *super, SEL op, id sender);
which defines CurOrCopyRunner as a function pointer type. Now your method:
- (void)notifyAndPerformSelector:(SEL)selector withObject:(id)sender
{
// "compile" [super selector:sender];
// first cast objc_msgSendSuper to the correct type by
// casting a function pointer to it (a function name by
// itself, e.g. objc_msgSendSuper, evaluates to a pointer
// to the function)
CutOrCopyRunner msgSender = (CutOrCopyRunner)objc_msgSendSuper;
// now build the first argument struct
struct objc_super superInfo;
superInfo.receiver = self;
superInfo.super_class = MyDerivedClass.class.superclass;
// now execute the super call
msgSender(&superInfo, selector, sender);
// code...
}
HTH
I'm currently designing a class structure for a project I'm working on. I have a method that uses one instance state. I don't now wheter it's better to make this method static and parse this instance state as an argument or just tie the method to the instance.
If performance was no issue I would tie the method without any doubt to the instance, because it's much cleaner that way. But in my case performance will be really crucial. So, does it make any difference performance-wise to make the method static / non-static?
If it makes no difference, will that be true for the generated *.dart.js javascript aswell?
Edit:
After reading my own question it's not really coherent. I will try to formulate it again, but clearer.
This code ...
class MyClass {
void foo() {}
}
void main() {
MyClass a = new MyClass();
MyClass b = new MyClass();
print(a.foo == b.foo);
}
... outputs false. This make me think that for each new instance a new method is created. If that is true this seems to me as a waste of memory. So, does each new instance create a copy of all it's bound methods?
PS: The question is basically the same as this question, but then for Dart.
No, creating two instances doesn't duplicate the methods. Methods are like static functions where the object instance is passesd as argument with the name this.
Don't worry too much about performance before you run into actual performance issues especially at such micro-level.
Usually performance isn't a matter for the bigger part of your applications code base because most of the code is usually run very seldom.
When you run into performance issues you can investigate and find the real hot spots that are executed often enough so that optimization actually makes a difference.
Dart classes don't have different methods for different instances.
There is only one method per class.
Extracting a function creates a new function object every time you do it, and those objects may or may not be equal depending on which function you extract from which objects:
class MyClass {
void foo() {}
}
void main() {
MyClass a = new MyClass();
MyClass b = new MyClass();
print(a.foo == b.foo); // False.
print(a.foo == a.foo); // True
print(identical(a.foo, a.foo)); // False!
}
When you perform a method extraction from an object, you create a new object. The new object is a "closure" which contains the function to call and the object to call it on. Two such closures are equal (according to operator==) if they refer to the same function on the same object. That's why a.foo and b.foo are not equal - they are equivalent to () => a.foo() and () => b.foo() respectively, and since a and b are not the same object, the function objects are not considered equal.
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"