Look up object from `inspect` value / pointer - ruby

As part of my debugging, I need to dump out a big object. Some of the data shows up like this:
#<Sketchup::Face:0x00007f9119bafea8>
This is the result of calling .inspect on the Sketchup::Face object, and Ruby calls .inspect internally when things are printed to the console.
Is it possible to then get a reference to the actual instance, using that 0x00007f9119bafea8 identifier? I don't even know exactly what this is - a pointer, instance id, something else?
Of course I can always manipulate my data before printing to console but since this is just for temporary debugging I'm hoping there's a quick and easy way.
Note: normally I would put in a binding.pry to avoid this whole business but due to Sketchup's restrictive programming environment it's not possible to use breakpoints there.

Related

Setting a global value (and keeping it) within the scope of an eval

I've got a large Rails 5 app (Ruby 2.6.x at present) that makes crucial use of Kernel::eval (please don't tell me to try to refactor this out because eval is dangerous - I didn't write the original code, and this is not in the cards for any time soon).
There are a very wide variety of Ruby expressions (coming out of the db) that can be passed to eval, sometimes of great complexity, making extensive use of classes and resources of the app.
(you might want to jump straight down to BIG EDIT below)
What I want is to be able to set a global value ($global) that will be seen within the scope of the eval execution, but that will not "infect" any of the execution context outside of that. I can't try to interpolate this into the string and pass it down though method params and such, because, as I say, the code being eval'ed is complex and stacks can get very deep, and I want the value to potentially be accessed (though never modified) anywhere within.
I understand about Bindings. I have played around with setting local and instance vars in a binding, and passing this to eval, but inevitably these are not seen inside any method calls within the eval, especially if I'm inside a method of some random class (which I always am). Seems like global is the only possibility. But experimentation shows that a global set inside an eval remains in the code that calls the eval:
2.6.3 :002 > $foo
=> nil
2.6.3 :003 > eval("$foo = 12")
=> 12
2.6.3 :004 > $foo
=> 12
Although I might find some hacky way to deal with this situation, I'm sure you can see where I'd really rather not.
The Binding class offers methods to set local and instance vars dynamically within a Binding object, but nothing for globals (apparently). I've thought about something like this:
...
eval code_string, get_binding()
...
def get_binding
$global = :special_value
binding
end
but I'm really worried, with a Rails app that might be servicing lots of requests at the same time, that these settings of $global will step on each other in unpredictable ways. Related clarifying question: Is a global value in a Rails app global to the entire thing, readable and writable within the scope of all the requests whose servicing may be overlapping in time? (I'm running under Passenger, if that means anything)
So this is a fairly simple and straightforward problem when you understand it, although oddly not addressed in anything I can google about it, and I think I've written enough words. Thanks for any help or ideas to try.
BIG EDIT:
Ok, let me try to refocus this in a different way. I'm getting that the scope of a global can never, no-how, be constrained (duh, right?), but how about this strategy (similar to above):
...
eval code_string, get_binding()
...
def get_binding
luaapg = :special_value ## local used as a pseudo-global
binding
end
So, now I've got this Binding that includes the local var luaapg. I've confirmed that. I eval code_string with this Binding. When I am somewhere inside the execution of code_string, where do I find luaapg - how do I access it? If you look at pretty much every tutorial on this stuff on the web, they show you puts eval("luaapg", get_binding) and voila, the assigned value comes out! But this is too simplistic for real life. When I am in the middle of my code_string, in some method scope of some class, luaapg is not there. I had great hope that this would work, even deep down the stack:
TOPLEVEL_BINDING.local_variable_get(:luaapg)
but it doesn't (I learned about TOPLEVEL_BINDING from here - thanks to that author). So this is the new question: what does it mean to say that I have executed (eval'ed) my code_string in the context of that Binding, which contains a local variable, if I have no way to access that variable, other than with the most simpleminded code? (incidentally I played around with instance vars too - same thing). I'm still hoping there's some magic incantation...
I think you've put your finger on it in the name of the type of variable - it's global - common to all the code in the executing program. I'm not sure exactly how Passenger works but I suspect it runs several copies of your program, so it won't be common between the copies.
To get reliable shared information I think you're going to have to use your database or some sort of information cache like memcached. You choose how you save/name it there.

How to display a value to the homescreen during a ti-89 titanium program

In relationship to this thread, this is also what i am kind of trying to do but i have had a bit more leeway in this.
My problem is i am currently working on a defining program (for my ti-89 titanium) to write out the definitions of variables. However, considering i had indefinite amounts of variables to add, i thought using the define function over and over again would waste memory and processing power. So my thinking was Save the variable to another variable to be defined in a later portion of the program.
prompt x
lbl x_d_r
x_d_r->q:Goto def
lbl def
define expr(q)[1]=x
where x_d_r has no assigned value. So the program was supposed to use the defined string as a list value to be x. However the obvious error came about.
So i played around on the home screen and program screen for a bit and came across entry(1) and ans(1). See back on the ti-83 (or 84) i could basically go (If i remember correctly)
disp q*1
x->ans(1)
However ans(1) on a ti-89 titanium is based upon the last answer submitted to the homescreen. Even then, ans(1) or entry(1) gets replaced in the program by just that. Lucky me, i found a way to avoid this.
Prgm
expr(char(120)&char(22)&char(97)&char(110)&char(115)&char(40)&char(49)&char(41))
EndPrgm
For those that do not know, this is simply expressing x->ans(1) which is a way for the code to transmit ans(1) within a program without removing the code to say so.
But it still does not work as a value needs to be sent to the home screen in order for it to record properly. This is one of those advantages that the ti-84 or ti-83 i wish it still had on the titanium. So i have spent some time searching for ways how i can display values of q to the home screen from within a program.
So far i learned that functions when used straight from the home screen return the value of q to the same place. However i have no way of implementing this in an actual program as the function does not wish to transmit the value to the home screen, and its rather useless within the program.
Secondly i have found this website which details methods of such ways to return values to the homescreen. While method 1 seems to hold promise, i do not seem to have any way of accessing that folder/program. Most likely because it is one that he made and has not shared its location on the pdf. I do like the expr("q"&":stop"), but q is not evaluated out so maybe i would have to rework it somehow.
While this was happening, i thought some other ideas could be using the paste key within a program but i have no idea how to implement stuff found from getkey let alone how the second and grab buttons factor in.
Or i could somehow have the ans(1) look to someplace else other than the home screen. Preferably to the i/0 screen but maybe to some other list or data matrix.
Anybody have any ideas on how to relay a value to the homescreen be it through function, pasting or something, and have the program i defined earlier define it as a value?
UPDATE+1
Ok i am beginning to question if maybe i am making it more complex than it needs to be...
After all, i am only going for just x->x_d_r[1], which is already defined elsewhere. So does it beat x->q:Goto def
Lbl def
Define expr(q)=x
(Or something like that which calls to a history recording program to define values?)
in terms of processing speed and memory count?
Got it. See here for what i was really trying to do.
So as an explanation of what the main problem was again, i wanted to be able to post a string value of q to be defined by another value of x.
The expr( function is quite a powerful tool on the ti-89 and like the person in that other forum, underestimated it. See what the person was trying to do was
InputStr "Function:",f(x)
expr(f)→f(x)
And was later answered by reworking it as
InputStr "function", n
expr(n & "->f(x)")
The expression tool just simply expresses what is in the parentheses. So during break periods in school today, i reworked in my head thinking "What if i tried rewriting the parenthesis out so it reads Expr("x->"&String(q))?
Lo-and-behold it works. Tested it with the fuller version of define to get
td()
Prgm
Prompt X
x_d_r->q
expr("x->"&string(q)&"[1]")
Disp x_d_r[1]
Delvar x_d_r
EndPrgm
Tried, tested and true. Works all the way. See what i think is happening is that anything that is not within the quotes is evaluated immediately in an expression while the the quoted objects are simply expressed and added later in response to the "&" key. Furthermore it makes sense if i was to describe it more with english; "Express x to be stored into the string of q's respective table".
While for variables sake i would have to look into ways to make x_d_r local only to the program without compensating the fact that the x_d_r portion is not considered a store value when executing x_d_r->q. But knowing what i know now i could probably do
expr("q"+"x_d_r"&->a)
expr("x->"&string(a)-"q"&"[1]")
In order to bypass that problem.

Is it possible to change Ruby's frozen object handling behaviour?

I am submitting solutions to Ruby puzzles on codewars.com and experimenting with how locked into the testing enviroment I am for one of the challenges.
I can redefine the classes used to test my solution but they are defined by the system after I submit my code. If I freeze these objects, the system cannot write over them but a RunTime error is raised when it tries to.
I'm fairly new to Ruby, so I'm not sure which parts (other than falsiness and truthiness) are impossible to override. Can I use Ruby code to force modification of frozen objects to silently fail instead of terminate the program or is that bound up in untouchable things like the assignment operator or similar?
The real answer here is that if you might want to modify an object later, you shouldn't freeze it. That's inherent in the whole concept of "freezing" an object. But since you asked, note that you can test whether an object is frozen with:
obj.frozen?
So if those pesky RuntimeErrors are getting you down, one solution is to use a guard clause like:
obj.do_something! if !obj.frozen?
If you want to make the guard clauses implicit, you can redefine the "problem" methods using a monkey patch:
class Array
# there are a couple other ways to do this
# read up on Ruby metaprogramming if you want to know
alias :__pop__ :pop
def pop
frozen? ? nil : __pop__
end
end
If you want your code to work seamlessly with any and all Ruby libraries/gems, adding behavior to built-in methods like this is probably a bad idea. In this case, I doubt it will cause any problems, but whenever you choose to start hacking on Ruby's core classes, you have to be ready for the possible consequences.

Halting and continuing embebbed ruby code

I call Ruby functions from my C++ code through the embedding commands (rb_eval and the like). Is there any way to stop the execution of the code partway, save the local variables, and restart it from the same spot later?
If you want to store Ruby variables for use later, you want to use a feature called Marshaling. Create a class in which you can store all variables you wish to save, and use Marshal::dump to store the class into a file. The data can be reconstituted into a Ruby variable again later by using Marshal::load.
Restarting your code from a particular point might not be as easy. You can marshal classes and data but not necessarily the state of the entire Ruby interpreter itself. One possibility is to store enough state information in your marshaled data to let you re-load the data and figure out where you need to pick up.

Should we create objects if we need them only once in our code?

This is a coding style questions:-
Here is the case
Dim obj1 as new ClassA
' Some lines of code which does not uses obj1
Something.Pass(obj1) ' Only line we are using obj1
Or should we directly initiaize the object when passing it as an argument?
Something.new(new ClassA())
If you're only using the object in that method call, it's probably better to just pass in "new ClassA()" directly into the call. This way, you won't have an extra variable lying around, that someone might mistakenly try to use in the future.
However, for readability, and debugging it's often useful to create the temporary object and pass it in. This way, you can inspect the variable in the debugger before it gets passed into the method.
Your question asks "should we create objects"; both your examples create an object.
There is not logically any difference at all between the two examples. Giving a name to an object allows it to be referred to in more than one place. If you aren't doing that, it's much clearer to not give it a name, so someone maintaining the code can instantly see that the object is only passed to one other method.
Generally speaking, I would say no, there's nothing wrong with what you're doing, but it does sound like there may be some blurring of responsibilities between your calling function, the called function, and the temporary object. Perhaps a bit of refactoring is in order.
I personally prefer things to be consistent, and to make my life easier (what I consider making my life easier may not be what you consider making your life easier... so do with this advice what you will).
If you have something like this:
o = new Foo();
i = 7
bar(o, i, new Car());
then you have an inconsistency (two parameters are variables, the other is created on the fly). To be consistent you would either:
always pass things as variables
always pass things created on the fly
only one of those will work (the first one!).
There are also practical aspects to it as well: making a variable makes debugging easier.
Here are some examples:
while(there are still lines in the file)
{
foo(nextLine());
}
If you want to display the next line for debugging you now need to change it to:
while(there are still lines in the file)
{
line = nextLine();
display(line);
foo(line);
}
It would be easier (and safer) to have made the variable up front. It is safer because you are less likely to accidentally call nextLine() twice (by forgetting to take it out of the foo call).
You can also view the value of "line" in a debugger without having to go into the "foo" method.
Another one that can happen is this:
foo(b.c.d()); // in Java you get a NullPointerException on this line...
was "b" or "c" the thing that was null? No idea.
Bar b;
Car c;
int d;
b = ...;
c = b.c; // NullPointException here - you know b was null
d = c.d(); // NullPointException here - you know c was null
foo(d); // can view d in the debugger without having to go into foo.
Some debuggers will let you highlight "d()" and see what it outputs, but that is dangerous if "d()" has side effects as the debugger will wind up calling "d()" each time you get the value via the debugger).
The way I code for this does make it more verbose (like this answer :-) but it also makes my life easier if things are not working as expected - I spend far less time wondering what went wrong and I am also able to fix bugs much faster than before I adopted this way of doing things.
To me the most important thing when programming is to be consistent. If you are consistent then the code is much easier to get through because you are not constantly having to figure out what is going on, and your eyes get drawn to any "oddities" in the code.

Resources