I would like to know why arrays will print content even if not told too. Here's an example because I'm bad at explaining.
def connect(host)
begin
sock = Socket.new(:INET, :STREAM)
sockaddr = Socket.sockaddr_in(23, host)
puts "Telnet available on #{host}\n" if sock.connect(sockaddr)
rescue Errno::ECONNREFUSED
puts "Telnet unavailable on #{host}"
end
end
def scan
@host = str_r(@host) # Formats IP
(1..255).each do |oct|
begin
nhost = @host+oct.to_s
@array << connect(nhost)
rescue Errno::EHOSTUNREACH
#puts "Host #{nhost} unreachable!"
end
end
#puts @array
end
Where method loops does something like try to connect to a host. Even though I haven't told it to 'puts' anything, it does. It puts the results of method(p), one by one. What I'd rather have it do is save all the results into an array, and then print them all at the end once it's done trying to connect to all the hosts. Doesn't the '<<' operator simply add whatever into an array?
In the ruby doc it says that
ary << obj → ary
Append—Pushes the given object on to the end of this array. This expression returns the array itself, so several appends may be chained together.
This is a syntactic sugar ; Others ways to write your code could be
@array.<<(connect(nhost))
@array.send(:<<, connect(nhost))
Your pushed object is given by the returned value of connect(nhost)
it is an argument of your push method. (and is evaluated on method call as any other arguments).
If you do not want your method to be evaluated, you can use a Proc object like this :
(1..255).each do |oct|
nhost = @host+oct.to_s
array << -> { connect(nhost) }
# same as
# array.push(Proc.new { connect(nhost) })
end
And get Proc objects called later like this : array[0].call
or array.map &:call
the way it works in this code:
(1..20).each do |p|
array << method(p)
end
The method method(p)
is executed
The result of executing method(p)
(the returned value) is appended to the array
If you would like to store the method for later evaluation, there are a few techniques you can use. One simple one would be to store the method as a string...
(1..20).each do |p|
array << 'method(p)'
end
... and later execute it using an eval
statement..
eval array[0] # will evaluate the string in array[0] as ruby code.
You may also want to look up Procs and Lambdas which are a more flexible way to store program code in a variable.
Based on the update, there are two issues:
You do indeed have some puts
statements in the connect
method which, given the flow of the method, will always output something, regardless.
In ruby, the last statement in a method is the value returned from that method. The puts
method doesn't return anything, and puts
is the last line of the method (even if it drops in to the rescue block). You can either try rewriting the method so the value you want is the last time (probably messy), or simply add return [something]
at the end, to ensure the value you want is returned (where [something]
is the variable to be returned).
Also, just to address your statement in the comments: I really don't understand why the print out even if I'm just pushing it all into and array .
The key thing to keep in mind is that those are two separate operations: First, the method is called...THEN the return value is pushed to the array. The method has no clue where its return value is going, so those puts
statements are going to be executed regardless, unless you put something in the method to filter them (like an if
statement, which you already have at least once, it looks like).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.