简体   繁体   中英

Printing contents of Ruby array

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
  1. The method method(p) is executed

  2. 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:

  1. You do indeed have some puts statements in the connect method which, given the flow of the method, will always output something, regardless.

  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM