Ruby - print the variable name and then its value
Sure it is possible!
My solution tests the var by Object#object_id identity: http://codepad.org/V7TXRxmL
It's crippled in the binding passing style ...
Although it works just for local vars yet, it can be easily be made "universal" adding use of the other scope-variable-listing methods like instance_variables
etc.
# the function must be defined in such a place
# ... so as to "catch" the binding of the vars ... cheesy
# otherwise we're kinda stuck with the extra param on the caller
@_binding = binding
def write_pair(p, b = @_binding)
eval("
local_variables.each do |v|
if eval(v.to_s + \".object_id\") == " + p.object_id.to_s + "
puts v.to_s + ': ' + \"" + p.to_s + "\"
end
end
" , b)
end
# if the binding is an issue just do here:
# write_pair = lambda { |p| write_pair(p, binding) }
# just some test vars to make sure it works
username1 = "tyndall"
username = "tyndall"
username3 = "tyndall"
# the result:
write_pair(username)
# username: tyndall
How to print variable's name?
Print a Symbol
If you already know the name of the variable, you can simply print the variable's symbol. Ruby will convert this to a string automagically for you when invoking puts
. For example:
asdf = Hash.new
puts :asdf
will print:
asdf
and return nil, because Kernel#puts always returns nil.
Return a String
If you prefer to return the name of the variable instead of just printing it, then you need to convert the Symbol to a String. For example:
asdf = Hash.new
:asdf.to_s
#=> "asdf"
Ruby: getting variable name
First, you cannot implement a puti
and directly call puti a_var
to get the output as a_var = value of a_var
. At the body of puti
, Ruby sees only the formal parameter names of puti
, it cannot infer the actual parameter names.
In some other language like C/C++, you can use Macro to implement your puti
. That's another story.
However, you can implement put :a_var
, with the help of Continuation. In another question "Can you eval code in the context of a caller in Ruby?", Sony Santos has provided a caller_binding implementation to get the binding of the caller (something like the perl caller function).
The implementation should be altered a bit, because callcc
returns the return value of the block at its first returning. So you'll get an instance of Continuation
rather than nil
. Here is the updated version:
require 'continuation' if RUBY_VERSION >= '1.9.0'
def caller_binding
cc = nil # must be present to work within lambda
count = 0 # counter of returns
set_trace_func lambda { |event, file, lineno, id, binding, klass|
# First return gets to the caller of this method
# (which already know its own binding).
# Second return gets to the caller of the caller.
# That's we want!
if count == 2
set_trace_func nil
# Will return the binding to the callcc below.
cc.call binding
elsif event == "return"
count += 1
end
}
# First time it'll set the cc and return nil to the caller.
# So it's important to the caller to return again
# if it gets nil, then we get the second return.
# Second time it'll return the binding.
return callcc { |cont| cc = cont; nil }
end
# Example of use:
def puti *vars
return unless bnd = caller_binding
vars.each do |s|
value = eval s.to_s, bnd
puts "#{s} = #{value.inspect}"
end
end
a = 1
b = 2
puti :a, :b
e = 1 # place holder...
# => a = 1
# b = 2
Note the puti
should not be the last statement of your program, otherwise the ruby interpreter will terminate immediately and the trace function has no chance to run. So that's the point of the last "place holder" line.
How can I print a variable name and its value without typing the name twice?
Here's a very general, but slightly ugly way to do it in D, using compile time function evaluation (CTFE) to generate the code as a string literal, and a mixin
statement to evaluate it:
import std.stdio, std.math;
// CTFE function that generates trace code.
string trace(string varName) {
return "writeln(\"" ~ varName ~ ": \", " ~ varName ~ ");";
}
void main() {
// Trace a function call.
mixin(trace("sqrt(5)"));
// Trace a variable.
int foo = 5;
mixin(trace("foo"));
}
The only problems are that manually typing mixin
everywhere is verbose and whatever you want to trace needs to be inside an ugly string literal.
Note that there are two kinds of mixins in D. Template mixins are better behaved in many ways, but string mixins (used in this example) are about as general as it gets, in that any code can in principle be generated via CTFE and then mixed in.
Can I get the variable name from it's assignee?
Technically yes, sort of.
But you'd have to recursively search through all the instance_variables of every object. And, as Cary points out, an object can be assigned to more than one variable at a time.
Don't do that.
The reason I was looking for this behavior was to use the variable name but also as a position within a grid of data. So if had a 2 dimensional Grid the variable names would be like "AA", "AB", "BC", etc. It is knew its name it would also know its position.
What you're describing is an "action at a distance" anti-pattern where changes to one part of a program change another part of a program with no obvious connection. This violates encapsulation; good encapsulation allows you to understand a single piece of a system by just looking at its inputs and outputs. Violating encapsulation means in order to understand one part of the system you have to understand every part of the system leading to a maintenance nightmare. Modern languages and practices strive to avoid this as much as possible.
For example, a variable's name should never matter to the behavior of the program. You should be able to safely perform a Rename Variable refactoring to name a variable according to what makes sense to the user of the object. In your example this would alter the behavior of the program violating the Principle of Least Astonishment.
Instead you'd have an object to represent your Grid and this would manage the relationships between Nodes in the Grid. Rather than passing around individual Nodes you'd pass around the Grid.
Or each Node can know who their neighboring Nodes are. An example of this would be a traditional Tree, Graph, or Linked List structure. The advantage here is there is no fixed position and the data structure can grow or shrink in any direction. Any Node can be passed around and it knows its position within the structure.
Can we print the value of a local variable by using its corresponding symbol in Ruby?
Use eval
.
eval("name") # "john"
How to print out value and name of each arg from a splat argument list
Using Mark's suggestion in regard to this SO question, the following works
def puts_auto (*args, &b)
str = args.map { |arg| "#{arg} = #{eval(arg.to_s, b.binding)}" }.join(', ')
puts str
end
so
puts_auto(:a, :b){} # outputs `a = a string, b = 3`
Related Topics
How to Calculate Number of Chars Common to Two Strings
How to Seed a Database in Rails
Open an Io Stream from a Local File or Url
Get List of a Class' Instance Methods
Ruby 2.0 Rails Gem Install Error "Cannot Load Such File - Openssl"
How to Generate a List of N Unique Random Numbers in Ruby
Understanding Private Methods in Ruby
Method to Parse HTML Document in Ruby
How to Find the Local Port a Rails Instance Is Running On
What Does ≪≪-Constant Do
How to Convert a Unix Timestamp (Seconds Since Epoch) to Ruby Datetime
How to Search Within an Array of Hashes by Hash Values in Ruby
Rails Update_Attributes Without Save
Failed to Build Gem Native Extension (Installing Compass)
How to Convert a String or Integer to Binary in Ruby
How to Skip the First Line of a CSV File and Make the Second Line the Header