instance_methods(nil)?
instance_methods returns an array of the methods of an
object, whereas instance_methods(nil) returns the methods which are
defined in the class of the object, excluding the methods inherited
from superclasses.
rand generate the same random number sequence?
rand generates the same sequence every time the script runs.
You need to give a different seed by srand to generate
different random numbers every time. srand called without
an argument makes the seed as the time being, and generates different
random numbers.
def sample(n, m)
if m.zero?
[]
else
s = sample(n-1, m-1)
t = rand(n+1)
s.concat s.include?(t) ? n : t
end
end
To write it in non-recursive iterated form,
def sample(n, m)
s = []
((n-m)...n).each do |j|
t = rand(j+2)
s.concat s.include?(t) ? j+1 : t
end
s
end
Fixnum, true, nil, and false
are implemented as immediate values, what is the difference between
an immediate value and a reference?
Fixnums of the same value are
always the same instance, so when instance variables are defined,
they point the same objects.
nil and false?
nil and false is
shown by executing nil.methods - false.methods and
false.methods - nil.methods.
nil cannot be a value, but false can.
true or false
if it is a predicate, and a value or nil otherwise.
? is usually a predicate, but
some built-in functions are not.
open("example", "r+").readlines.each_with_index{|l, i|
l[0,0] = (i+1).to_s + ": "}
This script does not add line numbers to the file "example".
It is because this script does not write to the file but only change
the strings received from readlines. You must write back the
result to the file.
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
-i, or built-in variable $-i,
you can read a file and replace it.
$ ruby -i -ne 'print "#$.: #$_"' example
If you want to reserve the original file, use -i.bak or
whatever you like.
open('file', 'w').print "This is a file.\n"
system 'cp file copy'
When copying the file in this script, the content is not yet
flushed. You should close the file before copying.
f = open('file', 'w')
f.print "This is a file.\n"
f.close
system "cp file copy"
less to display strings?
f = open '|less', 'w'
f.print "abc\n"
This script ends immediately, and you cannot see less displaying.
Use close to wait until less ends.
f = open '|less', 'w'
f.print "abc\n"
f.close
The first line can be written as f = IO.popen 'less', 'w'.
File object which has no reference?
File object, which is not referred as in open("file").read,
will be garbage collected in next GC, when it is closed.
(1)
a = open "file"
begin
a.each {|l| print l}
ensure
a.close
end
(2)
IO.foreach("file") {|l| print l}
(3)
IO.readlines("file").each {|l| print l}
Dir.glob("*").filter{|f| [File.mtime(f), f]}.
sort{|a,b| b[0]<=>a[0]}.filter{|e| e[1]}
This script returns an array with the filenames sorted by the
access time in reverse order. If you want to sort in straight order,
you can omit the block of sort.
Dir.glob("*").sort{|a,b| File.mtime(b)<=>File.mtime(a)}
will give the same answer, but this script takes longer time because
it accesses files each time it compares the modified time.
freq = Hash.new(0)
open("file").read.scan(/\w+/){|w| freq[w] += 1}
freq.keys.sort.each {|k| print k, "--", freq[k], "\n"}
true in a condition expression.
nil or false returns false condition.
You can use empty? or compare the string to "" or compare
length to 0 to find out if a string is empty.
"abcd"[0] return?
a, do either of following.
1 while a.sub!(/(^[^\t]*)\t(\t*)/){$1+' '*(8-$1.size%8+8*$2.size)}
1 while a.sub!(/\t(\t*)/){' '*(8-$~.begin(0)%8+8*$1.size)}
a.gsub!(/([^\t]{8})|([^\t]*)\t/n){[$+].pack("A8")}
Regexp.quote('\\') escapes a backslash.
gsub, if you write gsub(/\\/, '\\\\'), the second
argument is
analyzed as '\\' in syntax analysis and when the substitution occurs
it is again analyzed as '\' which means to substitute one backslash
to one backslash. You need to write gsub(/\\/, '\\\\\\'). Using the
fact that \& expresses the match, you can write
gsub(/\\/, '\&\&').
gsub, i.e. gsub(/\\/){'\\\\'},
the string for substitution is analyzed only once and the result is
what you intended.
sub and sub!?
sub, a copy of the receiver is generated, substituted
and returned.
sub!, the receiver is altered and returned if any match was
found. Otherwise, nil is returned.
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 ! to denote the
destructiveness.
def foo(str)
str = str.sub(/foo/, "baz")
end
obj = "foo"
foo(obj)
print obj
# -> "foo"
def foo(str)
str = str.sub!(/foo/, "baz")
end
foo(obj)
print obj
# -> "baz"
Destructive methods like sub! sometimes return an unexpected
result. Be careful.
.. and ...?
.. includes the right hand side in the range, ... does not.
Proc.new, proc, or lambda
serves as a function pointer.
thread and fork?
Thread and fork have following characteristics.
fork is slow, thread is not.fork does not share the memory space.fork,
thread worse.thread does not cause thrashing.thread works on DOS.thread gets in a deadlock, whole process stops.fork and thread.
thread in Ruby is implemented by time sharing, dividing to
threads does not gain the speed of execution.
Marshal.dump obj, io, lev
io is a writable IO object, lev designate the level to which
referred objects are dereferred and stored. If lev levels of
dereferring are done and still object referrences exist, then
the dump of the object is only the referrence. It cannot be
reconstructed when loaded.
obj = Marshal.load io
or,
obj = Marshal.load str
io is a readable IO object, str is the dumped string.
begin
statements which may raise exceptions.
rescue [exception class name]
statements when an exception occurred.
ensure
statements to be done in the end.
end
If an exception occurs in the begin clause, rescue clause
is executed. The ensure clause is executed whether an exception
occurred or not. rescue and ensure claused can 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.
$!.
The kind of exception is checked by $!.type.
trap?
trap("PIPE") {raise "SIGPIPE"}