|
Rootroute ruby language pages |
instance_methods(nil) return?
The method instance_methods returns an array containing the
names of methods that the receiver responds to. This will include the
methods in superclasses and in mixed-in modules.
instance_methods(nil) returns
the name of just those methods which are defined in the object's class.
It depends. In Ruby versions prior to 1.5.2, the random number
generator had (by default) a constant seed, and so would produce the
same series of numbers each time a program was run. If you needed less
deterministic behaviors, you called srand to set up a less
predictable seed.
Newer Rubys (Rubies?) have a different behavior. If rand is called
without a prior call to srand, Ruby will generate its own
random(ish) seed. Successive runs of a program that does not use
srand will generate different sequences of random numbers. To
get the old, predictable, behavior (perhaps for testing), call
srand with a constant seed.
Fixnum, true, nil, and false are
implemented as immediate values. With immediate values, variables hold
the objects themselves, rather than references to them.
Singleton methods cannot be defined for such objects. Two
Fixnums of the same value always represent the same
object instance, so (for example) instance variables for the
Fixnum with the value "one" are shared between all the "ones"
is the system. This makes it impossible to define a singleton method
for just one of these.
nil and false?
First the similarity. nil and false are the only two
values that evaluate to false in a boolean context.
However, they are instances of different classes (NilClass
and FalseClass), and have different behaviors elsewhere.
We recommend that predicate methods (those whose name ends with a
question mark) return true or false. Other methods
that need to indicate failure should return nil.
open("example", "r+").readlines.each_with_index{|l, i|
l[0,0] = (i+1).to_s + ": " }
|
This program does not add line numbers to the file "example". It does read the contents of the file, and for each line read prepend the line number, but the data is never written back. The code below does update the file (although somewhat dangerously, as it takes no backup before starting the update):
io = open("example", "r+")
ary = io.readlines
ary.each_with_index{|l, i| l[0,0] = (i+1).to_s + ": "}
io.rewind
io.print ary
io.close
|
Using the command-line option -i, or built-in variable $-i,
you can read a file and replace it.
The code in the preceding question, which added line numbers to file, is probably best written using this technique:
$ ruby -i -ne 'print "#$.: #$_"' example |
If you want to preserve the original file, use -i.bak to
create a backup.
This code will not work correctly:
open('file', 'w').print "This is a file.\n"
system 'cp file newfile'
|
Because I/O is buffered, file is being copied before
its contents have been written to disk. newfile will probably
be empty. However, when the program terminates, the buffers are
flushed, and file has the expected content.
The problem doesn't arise if you close file before copying:
f = open('file', 'w')
f.print "This is a file.\n"
f.close
system "cp file newfile"
|
As you read from a file, Ruby increments a line number counter in the
global variable $.. This is also available using the
lineno attribute of the File object.
The special constant ARGF is a file-like object that can be
used to read all the input files specified on the command line (or
standard input if there are no files). ARGF is used implicitly by code
such as:
while gets print $_ end |
In this case, $. will be the cumulative number of lines read
across all input files. To get the line number in the current file,
use
ARGF.file.lineno |
You can also get the name of the current file using
ARGF.file.path.
less to display my program's output?
I tried the following, but nothing came out:
f = open '|less', 'w' f.print "abc\n" |
That's because the program ends immediately, and less never
gets a chance to see the stuff you've written to it, never mind to
display it. Use close to wait until less ends.
f = open '|less', 'w' f.print "abc\n" f.close |
File object which is no longer referenced?
A File object which is no longer referenced becomes
eligible for garbage collection. The file will be closed automatically when
the File object is garbage collected.
There are at least four good ways of ensuring that you do close a file:
(1) f = open "file"
begin
f.each {|l| print l}
ensure
f.close
end
(2) File.open("file") { |f|
f.readlines.each { |l| print l }
}
(3) IO.foreach("file") {|l| print l}
(4) IO.readlines("file").each {|l| print l}
|
Dir.glob("*").sort{|a,b| File.mtime(b) <=> File.mtime(a)}
|
Although this works (returning a list in reverse chronological order) it isn't very efficient, as it fetches the files' modification times from the operating system on every comparison.
More efficiency can be bought with some extra complexity:
Dir.glob("*").collect! {|f| [File.mtime(f), f]}.
sort{|a,b| b[0] <=> a[0]}.collect! {|e| e[1]}
|
freq = Hash.new(0)
open("example").read.scan(/\w+/){|w| freq[w] += 1}
freq.keys.sort.each {|k| print k, "-", freq[k], "\n"}
Produces:
and-1
is-3
line-3
one-1
this-3
three-1
two-1
|
false?
Q: An empty string ("") returns true in a conditional
expression! In Perl, it's false.
A: In Ruby, only nil and false are false in
conditional contexts. This is a way of gaining speed--both
nil and false have immediate values, so they can be
tested without having to chase a reference to an object.
You can use empty?, compare the string to "", or compare
length to 0 to find out if a string is empty.
If you want your strings to sort 'AAA', 'BBB', ..., 'ZZZ', 'aaa', 'bbb', then the built-in comparison will work just fine.
If you want to sort ignoring case distinctions, compare downcased versions of the strings in the sort block:
array = %w( z bB Bb BB bb Aa aA AA aa a )
puts array.sort { |a,b| a.downcase <=> b.downcase }
Produces:
a
aa
AA
aA
Aa
bb
BB
bB
Bb
z
|
If you want to sort so that the 'A's and 'a's come together, but 'a' is considered greater than 'A' (so 'Aa' comes after 'AA' but before 'AB'), use:
puts array.sort { |a,b|
(a.downcase <=> b.downcase).nonzero? || a <=> b
}
Produces:
a
AA
Aa
aA
aa
BB
Bb
bB
bb
z
|
"abcd"[0] return?
It returns the character code for ``a'', 97(Fixnum).
You can express a character code as an integer constant by prefixing
the character with a question mark, so ?a is also 97(Fixnum).
If a holds the string to be expanded, you could use one of:
1 while a.sub!(/(^[^\t]*)\t(\t*)/){$1+' '*(8-$1.size%8+8*$2.size)}
#or
1 while a.sub!(/\t(\t*)/){' '*(8-$~.begin(0)%8+8*$1.size)}
#or
a.gsub!(/([^\t]{8})|([^\t]*)\t/n){[$+].pack("A8")}
|
Regexp.quote('\\') escapes a backslash.
It gets trickier if you're using sub and gsub, Say you
write gsub(/\\/, '\\\\'), hoping to replace each backslash
with two. The second argument is converted to '\\' in syntax
analysis. When the substitution occurs, the regular expression engine
converts this to '\', so the net effect is to replace each single
backslash with another single backslash. You need to write
gsub(/\\/, '\\\\\\')!
However, using the fact that \& contains the matched string,
you could also write gsub(/\\/, '\&\&').
If you use the block form of gsub,
i.e. gsub(/\\/){'\\\\'}, the string for substitution is
analyzed only once (during the syntax pass) and the result is what you
intended.
sub and sub!?
In sub, a copy of the receiver is generated, substituted
and returned.
In sub!, the receiver is altered and returned if any match was
found. Otherwise, nil is returned.
Methods like sub! are called
destructive methods
which alter the attribute of the receiver. If there are two similar
methods and one is destructive, the destructive one has a suffix !.
def foo(str)
str = str.sub(/foo/, "baz")
end
obj = "foo"
foo(obj) # -> "baz"
obj # -> "foo"
def foo(str)
str = str.sub!(/foo/, "baz")
end
foo(obj) # -> "baz"
obj # -> "baz"
|
\Z matches just before the last \n if the string ends with a \n, otherwise it matches at the end of a string.
.." and "..."?
.. includes the right hand side in the range, ... does not.
A Proc object generated by Proc.new, proc, or lambda
can be referenced from a variable, so that variable could be said to
be a function pointer. You can also get references to methods
within a particular object instance using Object.method.
thread and fork?
Ruby threads are implemented within the interpreter, while
fork invokes the operating system to create a separately
executing subprocess.
Thread and fork have following characteristics:
fork is slow, thread is not.fork does not share the memory space.thread does not cause thrashing.thread works on DOS.thread gets in a deadlock, the whole process
stops.fork can take advantage of pauses waiting for I/O to
complete, thread does not (at least not without some help).You probably shouldn't mix fork and thread.
Marshal is used to store an object in a file or a string, and later reconstitute it. Objects may be stored using:
Marshal.dump obj [, io ] [, lev] |
io is a writable IO object, lev designates the level
to which objects are dereferred and stored. If lev levels of
dereferring are done and object references still exist, then
dump stores just the reference, not the object referenced. This is
not good, as these referenced objects cannot be subsequently
reconstructed.
If io is omitted, the marshaled objects are returned in a string.
You can load objects back using:
obj = Marshal.load io #or obj = Marshal.load str |
where io is a readable IO object, str is the dumped
string.
Ruby supports a flexible exception handling scheme:
begin statements which may raise exceptions. rescue [exception class names] statements when an exception occurred. rescue [exception class names] statements when an exception occurred. ensure statements that will always run end |
If an exception occurs in the begin clause, the
rescue clause with the matching exception name
is executed. The ensure clause is executed whether an exception
occurred or not. rescue and ensure clauses may be omitted.
If no exception class is designated for rescue clause,
StandardError exception is implied, and exceptions which are
in a is_a? relation to StandardError are captured.
This expression returns the value of the begin clause.
The latest exception is accessed by the global variable $! (and
so its type can be determined using $!.type).
trap?
trap associates code blocks with external events (signals).
trap("PIPE") {raise "SIGPIPE"}
|