Ruby: define function prototypes? - ruby

It is possible to define a prototype of a function or in some way indicate to Ruby that a function exists even though it may not be defined yet?
I have lots of classes like this:
class Program
FIRST = Block.FIRST
FOLLOW = Set.new['$']
end
class Block
FIRST = Declaration.FIRST
FOLLOW = Set.new['.']
end
class Declaration
FIRST = ConstDecl.FIRST + VarDecl.FIRST + ProcDecl.FIRST
end
class ConstDecl
FIRST = Set.new['const'] + EMPTY_SET
end
Which as you can see reference fields from classes that are defined below them, Is there a way to indicate to Ruby that these classes exist, and ask Ruby to look for them?

The simplest way I can think of is something like this:
class Program
def self.first; Block.first end
def self.follow; Set.new['$'] end
end
class Block
def self.first; Declaration.first end
def self.follow; Set.new['.'] end
end
class Declaration
def self.first; ConstDecl.first + VarDecl.first + ProcDecl.first end
end
class ConstDecl
def self.first; Set.new['const'] + EMPTY_SET end
end
This doesn't seem like good design to me, though, I'd probably make those objects instead of classes and use a proper type hierarchy.

A major difference between Ruby and other languages which you may be accustomed to (like C/C++) is that before execution, a C/C++ program is processed by a compiler which matches up uses of variables/functions to their definitions. Ruby programs are simply executed from top to bottom, one statement at a time. So when a line which references Block.FIRST is executed, the Ruby interpreter can't "look forward" in the program code and see what value will be assigned to Block.FIRST later. It knows nothing about what will come later; it only knows what it has executed so far.
Perhaps one of the strongest characteristics of Ruby is that almost everything is dynamic and can be changed at run-time. If you are coming from a C/C++ background, this is the first thing you need to get your head around to understand Ruby. For example, constants in Ruby can be assigned conditionally:
class Block
if rand % 2 == 0
FIRST = '.'
else
FIRST = '$'
end
end
If the Ruby interpreter was required to "look forward" to see what the value of Block.FIRST should be, what should it predict in the above case?
This is a conceptual shift from what you are used to, and it will require you to structure your programs in a different way, and think about your programs in a different way. If you try to write C/C++/Java in Ruby, you will be fighting all the way.
In this case, I recommend you simply reverse the order of your definitions and go "bottom-up". There are other ways to achieve the same effect, but that is the simplest one.

you can try defined?(function_name)

Related

Get list of classes and methods that call a specific global method

I have a method called $muffinize and I would like to find where it can be found in my code. In other words, given the following code:
class A
def foo
$muffinize(1)
end
def bar
...
end
end
class B
def shoop
$muffinize(2)
end
def woop
...
end
end
class C
def nope
...
end
end
I would like to the result to be (written to a file):
A:foo
B:shoop
I was thinking of accomplishing this with a Regex, but I was wondering if there would be some way of accomplishing this with Ruby meta-programming (which I might be accidentally using as a buzz-word)?
Kernel.caller() will help you show the line number and method that is calling it at runtime. If you put something like puts caller(1,1) in your muffinize function it will output those locations, but only if they are called at runtime.
If you want to do offline source analysis, you need to parse the AST (abstract syntax tree) with something like https://github.com/whitequark/parser.
Here is a quick example with ripper (built into new rubies) - this isn't strictly an AST but it's not extracting classes either
#!/usr/local/env ruby
require 'ripper'
#require 'pry'
contents = File.open('example.rb').read
code = Ripper.lex(contents)
code.each do |line|
if(line[1] == :on_ident and line[2] == "muffinize")
puts "muffinize found at line #{line.first.first}"
end
end
Ignoring the fact that your code isn't even syntactically valid, this is simply not possible.
Here's a simple example:
class A
def foo
bar
muffinize(1)
end
end
A#foo will call Object#muffinize if and only if bar terminates. Which means that figuring out whether or not A#foo calls Object#muffinize requires to solve the Halting Problem.
By getting a list of classes and methods via ri, I was then able to analyze each method to retreive their source code using the method_source gem and then searching for muffinize. This does not rule out the possibility of muffinize from appearing in a comment or a string, but I consider the likelihood of this happening to be small enough to ignore.

What is the semantics of this "do ... end"

I am new to Ruby and am learning from reading an already written code.
I encounter this code:
label = TkLabel.new(#root) do
text 'Current Score: '
background 'lightblue'
end
What is the semantics of the syntax "do" above?
I played around with it and it seems like creating a TkLabel object then set its class variable text and background to be what specified in quote. However when I tried to do the same thing to a class I created, that didn't work.
Oh yeah, also about passing hash into function, such as
object.function('argument1'=>123, 'argument2'=>321)
How do I make a function that accepts that kind of argument?
Thanks in advance
What you're looking at is commonly referred to as a DSL, or Domain Specific Language.
At first glance it may not be clear why the code you see works, as text and background are seemingly undefined, but the trick here is that that code is actually evaluated in a scope in which they are. At it's simplest, the code driving it might look something like this:
class TkLabel
def initialize(root, &block)
#root = root
if block
# the code inside the block in your app is actually
# evaluated in the scope of the new instance of TkLabel
instance_eval(&block)
end
end
def text(value)
# set the text
end
def background(value)
# set the background
end
end
Second question first: that's just a hash. Create a function that accepts a single argument, and treat it like a hash.
The "semantics" are that initialize accepts a block (the do...end bit), and some methods accepting string parameters to set specific attributes.
Without knowing how you tried to do it, it's difficult to go much beyond that. Here are a few, possible, references that might help you over some initial hurdles.
Ruby is pretty decent at making miniature, internal DSLs because of its ability to accepts blocks and its forgiving (if arcane at times) syntax.

is it OK to use begin/end in Ruby the way I would use #region in C#?

I've recently moved from C# to Ruby, and I find myself missing the ability to make collapsible, labelled regions of code. It just occurred to me that it ought to be OK to do this sort of thing:
class Example
begin # a group of methods
def method1
..
end
def method2
..
end
end
def method3
..
end
end
...but is it actually OK to do that? Do method1 and method2 end up being the same kind of thing as method3? Or is there some Ruby idiom for doing this that I haven't seen yet?
As others have said this doesn't change the method definition.
However, if you want to label groups of methods, why not use Ruby semantics to label them? You could use modules to split your code into chunks that belong together. This is good practice for large classes, even if you don't reuse the modules. When the code grows, it will be easy to split the modules into separate files for better organisation.
class Example
module ExampleGroup
def method1
# ..
end
def method2
# ..
end
end
include ExampleGroup
def method3
# ..
end
end
Adding arbitrary Ruby code in order to please your editor doesn't seem reasonable to me at all. I think you should try to get a decent text editor, one that would be able to configure to use some keyword you put in your comments to enable code folding there, for example:
# region start AAA
some(:code, :here)
# region end AAA
And if you allow me to be sarcastic: you should know that Ruby is lot more expressive, elegant and pretty than C#, and chances are that there isn't any Ruby code ought to be hidden in the first place! ;)
I know this might be a bit old but I ran into this issue and found a killer solution. If you're using "Rubymine" you can do #regions.
This is where they talk about navigating regions
https://www.jetbrains.com/ruby/help/navigating-to-custom-region.html
#region Description
Your code goes here...
#endregion
So with the above in your code you will see the below:
Rubymine code editor - With a sample method using regions un-folded
Rubymine code editor - With a sample method using regions folded
I think it should be OK. I haven't seen it a lot though. Another way you could accomplish the same thing, while using less indentation, is to close and reopen the class, like so:
class Example
def method1
..
end
def method2
..
end
end
# optionally put some other code here
class Example
def method3
..
end
end
I think this is often used so that you can put other code in the middle, such as when there's a constant defined in the first class Example block, which is used to define a constant in the middle code, which is used to define a constant in the second class Example block. That way you never have to refer to a constant before it's defined.
Yes, it is okay to do that (i.e. it doesn't change the semantics of your code).
However this isn't a common pattern and it might be confusing to readers of your code who wouldn't understand what the purpose of the begin ... end block is.

Are there any advantages in using block initialization?

Is there any reason to do use block initialization, like this:
x = Observer.new do
add_event(foo)
some_other_instance_method_on_observer
self.some_attribute = something
end
instead of initializing attributes using the dot operator on an instance variable like this:
x = Observer.new
x.add_event(foo)
x.some_other_instance_method_on_observer
x.some_attribute = something
The only reason here is to have more concise code(you don't have to add the instance name before the method call). By using blocks in general you can write very neat, concise and readable code. Some times you can save your code consumers lots of typing and even code logic.
Here is a traditional case!
file = File.open("some_file.txt","w")
file << "more code"
file.close
Compare it to this nice block alternative:
File.open("some_file.txt","w") { |file| file << "adding new stuff" }
It saved the user from the hassle of having to open and close(personally i keep forgetting this one) the file himself. Instead it made him focus on what he wants.
Try to invest blocks in such situations + when you want to write nice DSLs.
One advantage is that it makes it obvious that those additional actions are initialization actions.
Building on khell's answer, variables created within a block go out of scope outside of the block, which is a good thing if you don't have any more use of it.
If your code is in a method, which returns the object. Compare
def create_observer
Observer.new {|x| x.foo, x.bar = calculate_foo, calculate_bar }
end
def create_observer
x = Observer.new
x.foo = calculate_foo
x.bar = calculate_bar
x
end
So using a block can potentially allow you to write your logic in one line.
Even if you use parallel assignment in the second example, you still need 3 lines.
Also, check out tap here. It has similar benefits.

How to get argument names using reflection

I would like to do some fairly heavy-duty reflection in Ruby. I want to create a function that returns the names of the arguments of various calling functions higher up the call stack (just one higher would be enough but why stop there?). I could use Kernel.caller, go to the file and parse the argument list but that would be ugly and unreliable.
The function that I would like would work in the following way:
module A
def method1( tuti, fruity)
foo
end
def method2(bim, bam, boom)
foo
end
def foo
print caller_args[1].join(",") #the "1" mean one step up the call stack
end
end
A.method1
#prints "tuti,fruity"
A.method2
#prints "bim, bam, boom"
I would not mind using ParseTree or some similar tool for this task but looking at Parsetree, it is not obvious how to use it for this purpose. Creating a C extension like this is another possibility but it would be nice if someone had already done it for me.
I can see that I'll probably need some kind of C extension. I suppose that means my question is what combination of C extension would work most easily. I don't think caller+ParseTree would be enough by themselves.
As far as why I would like to do this goes, rather than saying "automatic debugging", perhaps I should say that I would like to use this functionality to do automatic checking of the calling and return conditions of functions:
def add x, y
check_positive
return x + y
end
Where check_positive would throw an exception if x and y weren't positive. Obviously, there would be more to it than that but hopefully this gives enough motivation.
In Ruby 1.9.2, you can trivially get the parameter list of any Proc (and thus of course also of any Method or UnboundMethod) with Proc#parameters:
A.instance_method(:method1).parameters # => [[:req, :tuti], [:req, :fruity]]
The format is an array of pairs of symbols: type (required, optional, rest, block) and name.
For the format you want, try
A.instance_method(:method1).parameters.map(&:last).map(&:to_s)
# => ['tuti', 'fruity']
Of course, that still doesn't give you access to the caller, though.
I suggest you take a look at Merb's action-args library.
require 'rubygems'
require 'merb'
include GetArgs
def foo(bar, zed=42)
end
method(:foo).get_args # => [[[:bar], [:zed, 42]], [:zed]]
If you don't want to depend on Merb, you can choose and pick the best parts from the source code in github.
I have a method that is quite expensive and only almost works.
$shadow_stack = []
set_trace_func( lambda {
|event, file, line, id, binding, classname|
if event == "call"
$shadow_stack.push( eval("local_variables", binding) )
elsif event == "return"
$shadow_stack.pop
end
} )
def method1( tuti, fruity )
foo
end
def method2(bim, bam, boom)
foo
x = 10
y = 3
end
def foo
puts $shadow_stack[-2].join(", ")
end
method1(1,2)
method2(3,4,4)
Outputs
tuti, fruity
bim, bam, boom, x, y
I'm curious as to why you'd want such functionality in such a generalized manner.
I'm curious how you think this functionality would allow for automatic debugging? You'd still need to inject calls to your "foo" function. In fact, something based on set_trace_func is more able to be automatic, as you don't need to touch existing code. Indeed this is how debug.rb is implemented, in terms of set_trace_func.
The solutions to your precise question are indeed basically, as you outlined. use caller + parsetree, or open the file and grab the data that way. There is no reflection capability that I am aware of that will let you get the names of arguments. You can approve upon my solution by grabbing the associated method object and calling #arity to then infer what of local_variables are arguments, but though it appears the result of that function is ordered, I'm not sure it is safe to rely on that. If you don't mind me asking, once you have the data and the interface you describe, what are you going to do with it? Automatic debugging was not what initially came to mind when I imagined uses for this functionality, although perhaps it is failing of imagination on my part.
Aha!
I would approach this differently then. There are several ruby libraries for doing design by contract already, including ruby-contract, rdbc, etc.
Another option is to write something like:
def positive
lambda { |x| x >= 0 }
end
def any
lambda { |x| true }
end
class Module
def define_checked_method(name, *checkers, &body)
define_method(name) do |*args|
unless checkers.zip(args).all? { |check, arg| check[arg] }
raise "bad argument"
end
body.call(*args)
end
end
end
class A
define_checked_method(:add, positive, any) do |x, y|
x + y
end
end
a = A.new
p a.add(3, 2)
p a.add(3, -1)
p a.add(-4, 2)
Outputs
5
2
checked_rb.rb:13:in `add': bad argument (RuntimeError)
from checked_rb.rb:29
Of course this can be made much more sophisticated, and indeed that's some of what the libraries I mentioned provided, but perhaps this is a way to get you where you want to go without necessarily taking the path you planned to use to get there?
if you want the value for the default values, too, there's the "arguments" gem
$ gem install rdp-arguments
$ irb
>> require 'arguments'
>> require 'test.rb' # class A is defined here
>> Arguments.names(A, :go)
In fact, the method you describe clearly fails to distinguish arguments from local variables while also failing to work automatically
That's because what you're trying to do is not something which is supported. It's possible (everything is possible in ruby), but there's no documented or known way to do it.
Either you can eval the backtrace like what logan suggested, or you can bust out your C compiler and hack sourcecode for ruby. I'm reasonably confident there aren't any other ways to do this.

Resources