Ruby methods at bottom of script? - ruby

I'm using ruby 1.8.7. I could have sworn that I've written my functions at the bottom of my script before and it worked fine.
Do I have to put them at the top? It seems to be the only way they work now. Not a big deal. I just prefer to have them at the bottom so I figured I'd ask.

You can do initializing code in one or more BEGIN-blocks (inherited from Perl, which inherited them from awk).
can_i_do_this? #=>yes
BEGIN {
def can_i_do_this?
puts "yes"
end
}
And for completeness, there are also END-blocks:
END {
can_i_do_this? #=> yes
}
def can_i_do_this?
puts "yes"
end

a
def a
puts "Hello world!"
end
Running this script in Ruby will give you:
script.rb:1:in `<main>': undefined local variable or method `a' for main:Object (NameError)
So no, you can't have them at the bottom. As Ruby is an interpreted language, any code is parsed and processed at runtime ONLY. Therefore, you can only run code (call methods, use variables...) that have already been defined prior to the actual reference.

Related

Simple Ruby program does not produce output

I wrote a basic ruby program with TextMate in Mac OS:
def hello
puts " This works!"
end
name it Check-it.rb
I open a Terminal session, cd to the directory where the program is stored.
Then I type
ruby Check-it.rb
And nothing appears.
ruby -v
shows me the version, so it's there.
But with this and every other Ruby program, nothing appears.
As others already pointed out. The code in your file
def hello
puts " This works!"
end
defines a method called hello that outputs a string. But that method is never called. To actually call that method and run it change your code in the file to
def hello # this block defines the `hello` method
puts " This works!"
end
hello # this line calls the method `hello`
I think you are not calling this method at all. Call this method and then run your code, it will work.

Conflicting output for the same ruby code in irb and pry

I do the following in irb and have also tried out the same code in pry
class Number < Struct.new(:value)
end
class Number
def to_s
value.to_s
end
def inspect
"<<#{self}>>"
end
end
Now, if i do Number.new(2), it correctly returns <<2>> in irb, but in pry it incorrectly returns #<struct Number value=2> . Why is this so ?
Thank You
I'm not very familiar with pry (I've never used it until just now), but the obvious answer to your question is: because pry isn't calling inspect on your object. You can manually call it, and it works as expected:
Number.new(2).inspect
# => "<<2>>"
My question was: why isn't pry calling inspect, and what's it doing instead? Looking at the code, it looks like it calls pretty_inspect instead. There may be a smarter workaround, but the simplest thing that comes to mind for me is to just alias pretty_inspect to inspect for Number:
class Number
alias_method :pretty_inspect, :inspect
end
Number.new(2)
# => <<2>>

How to execute local functions using code from external file in ruby?

Can a require execute a locally defined function? I guess the easiest way to describe what I need is to show an example.
I'm using ruby 1.9.3, but solutions for 1.8 and 2.0 are also welcome.
I have a file main.rb as the following:
class Stuff
def self.do_stuff(x)
puts x
end
require_relative('./custom.rb')
do_stuff("y")
end
And also have a file custom.rb in the same folder, with the following content:
do_stuff("x")
Running main.rb, I have following output:
/home/fotanus/custom.rb:1:in `<top (required)>': undefined method `do_stuff' for main:Object (NoMethodError)
from main.rb:5:in `require_relative'
from main.rb:5:in `<class:Stuff>'
from main.rb:1:in `<main>'
Note that without the require, the output is y.
I'm not sure if it is the best solution but using eval should do the trick.
class Stuff
def self.do_stuff(x)
puts x
end
eval(File.read('./custom.rb'))
do_stuff("y")
end
The output will be:
pigueiras#pigueiras$ ruby stuff.rb
x
y
In C, #include literally drops the code as-is into the file. require in Ruby is different: it actually runs the code in the required file in its own scope. This is good, since otherwise we could break required code by redefining things before the require.
If you want to read in the contents of a script and evaluate it in the current context, there are methods for doing just that: File.read and eval.

Is there a "main" method in Ruby like in C?

I'm new to Ruby, so apologies if this sounds really silly.
I can't seem to figure out how to write a "main" code and have methods in the same file (similar to C). I end up with a "main" file which loads a seperate file that has all the methods. I appreciate any guidance on this.
I spotted the following SO post but I don't understand it:
Should I define a main method in my ruby scripts?
While it's not a big deal, it's just easier being able to see all the relevant code in the same file. Thank you.
[-EDIT-]
Thanks to everyone who responded - turns out you just need to define all the methods above the code. An example is below:
def callTest1
puts "in test 1"
end
def callTest2
puts "in test 2"
end
callTest1
callTest2
I think this makes sense as Ruby needs to know all methods beforehand. This is unlike C where there is a header file which clearly list the available functions and therefore, can define them beneath the main() function
Again, thanks to everyone who responded.
#Hauleth's answer is correct: there is no main method or structure in Ruby. I just want to provide a slightly different view here along with some explanation.
When you execute ruby somefile.rb, Ruby executes all of the code in somefile.rb. So if you have a very small project and want it to be self-contained in a single file, there's absolutely nothing wrong with doing something like this:
# somefile.rb
class MyClass
def say_hello
puts "Hello World"
end
end
def another_hello
puts "Hello World (from a method)"
end
c = MyClass.new
c.say_hello
another_hello
It's not that the first two blocks aren't executed, it's just that you don't see the effects until you actually use the corresponding class/method.
The if __FILE__ == $0 bit is just a way to block off code that you only want to run if this file is being run directly from the command line. __FILE__
is the name of the current file, $0 is the command that was executed by the shell (though it's smart enough to drop the ruby), so comparing the two tells you precisely that: is this the file that was executed from the command line? This is sometimes done by coders who want to define a class/module in a file and also provide a command-line utility that uses it. IMHO that's not very good project structure, but just like anything there are use cases where doing it makes perfect sense.
If you want to be able to execute your code directly, you can add a shebang line
#!/usr/bin/env ruby
# rest of somefile.rb
and make it executable with chmod +x somefile.rb (optionally rename it without the .rb extension). This doesn't really change your situation. The if __FILE__ == $0 still works and still probably isn't necessary.
Edit
As #steenslag correctly points out, the top-level scope in Ruby is an Object called main. It has slightly funky behavior, though:
irb
>> self
=> main
>> self.class
=> Object
>> main
NameError: undefined local variable or method `main' for main:Object
from (irb):8
Don't worry about this until you start to dig much deeper into the language. If you do want to learn lots more about this kind of stuff, Metaprogramming Ruby is a great read :)
No there isn't such structure. Of course you can define main function but it won't be called until you do so. Ruby execute line by line so if you want to print 'Hello World' you simply write:
puts 'Hello World'
The question that you mentioned is about using one file as module and executable, so if you write
if __FILE__ == $0
# your code
end
It will be called only if you run this file. If you only require it in other file then this code will never run. But IMHO it's bad idea, better option is using RubyGems and there add executables.
Actually there is a main, but it is not a method; it's the top-level object that is the initial execution context of a Ruby program.
class Foo
p self
end
#=> Foo
p self
#=> main
def foo
p self
end
foo
#=> main
There is no magic main function in Ruby. See http://en.wikipedia.org/wiki/Main_function#Ruby
If you wish to run Ruby scripts like C compiled files, do the following:
#!/usr/bin/env ruby
puts "Hello"
and then chmod a+x file_name.rb. Everything that is below the first line will be run, as if it was contents of main in C. Of course class and function definitions won't give you any results until they are instantiated/invoked (although the code inside class definitions is actually evaluated, so you could get some output but this is not expected in normal circumstances).
Another way to write main() method is:
class HelloWorld
def initialize(name)
#name = name
end
def sayHello()
print "Hello ##name!"
end
end
def main()
helloWorld = HelloWorld.new("Alice")
helloWorld.sayHello
end
main

Why am I getting NoMethodError from IRB for my own Module and method

I have taken this example exactly from the Ruby Cookbook. Unfortunately for me, like a whole lot of the examples in that book, this one does not work:
my file (Find.rb - saved both locally and to Ruby\bin):
require 'find'
module Find
def match(*paths)
matched=[]
find(*paths) { |path| matched << path if yield path }
return matched
end
module_function :match
end
I try to call it this way from IRB, according to the example the book provides:
irb(main):002:0> require 'Find'
=> false
irb(main):003:0> Find.match("./") { |p| ext = p[-4...p.size]; ext && ext.downcase == "mp3" }
It SHOULD return a list of mp3 files in my recursive directory. Instead, it does this:
NoMethodError: undefined method `match' for Find:Module
from (irb):3
from C:/Ruby192/bin/irb:12:in `<main>'
What gives? I'm new at this (although I MUST say that I'm farther along with Python, and much better at it!).
How can I get IRB to use my method?
I ran into this with irb on a Mac running Snow Leopard while using the default version of ruby (and irb of course) installed with OS X. I was able to get past it by including the module in IRB after loading the module or in the file after the module definition.
include module_name
I'm not sure if this is a defect or known behavior.
The only explanation is that the code you posted is not the code you are running, since both carefully reading it and simply cut&paste&running it shows absolutely no problems whatsoever.
What directory are you calling IRB from? Try calling it from the directory where your find.rb file is located. Also, I don't know if it makes any difference but convention is to name the file the lowercase version of the module / class. So the module would be Find and the file name would be find.rb. You shouldn't need the require call in the file itself.
So, start your command prompt window, cd into the directory that contains find.rb and run irb. In IRB you should be able to require "find" and it should return true. From there you should be able to call Find.match.
I know this question is already 3 years old, but since this is the first hit on google for the problem, and I had been banging my head against the wall all afternoon with the same problem doing the tutorial here: http://ruby.learncodethehardway.org/book/ex25.html, here goes: the function definition in the module should read
module Find
def Find.match(*paths)
...
end
end

Resources