# CSE 341 Section 8, 17 November 2011 # Single-line comment =begin Multiple- line comment =end # Today: # - Arrays, Hashes # - Blocks, Iterators # - Random other stuff # Ruby Documentation -- very helpful # http://ruby-doc.org/ # Be sure to use the 1.8.7 docs. There are subtle and sometimes incompatible differences with 1.9.* # A fun and slightly (or more than slightly) wacky Ruby tutorial # http://mislav.uniqpath.com/poignant-guide/ # Printing puts "Hello, world." print "Hello, " puts "world." # Arrays in Ruby serve as lists, arrays, tuples, stacks, queues... # They are mutable. x = Array.new x = [2,5,6,2] # Indexing # Array bounds? Yeah right! x[1] x[9] x[-1] x[-3] x[7] = 4 puts x puts x.inspect # Array arithmetic y = x + [17,42,17] y - x [1,4,5] | [3,7,4] x.size x.first x.last # As tuples a,b,c = [1,2,3] a c # As stacks x.push(5) x.push(Array.new) x.push(7) x << 9 x.pop # As queues q = [] q << 8 q.push(2) q.inspect q.shift q.inspect q.shift q.unshift(3) q.unshift(5) q.pop # Aliasing y = x y.pop x.pop x.push(6).push(7) # Cloning y = x.clone() y.pop x.pop # Generate an array of ten elements whose content is the square of each index value # ie [0, 1, 4, 9, 16, etc] #write a function to reverse the order of elements in your array # Blocks: like dumbed-down anonymous functions. odds = [1,3,5,7,9,11,13,15,17,19] odds.each { |n| puts (n - 1) } # With slightly looser precedence: odds.each do |n| puts n * n end # You almost *never* use loops directly in Ruby. # Usually, you use each or something similar. #### BEWARE !!!!!!!!!!!!!!!! n = 42 odds.each { |n| puts n } n # This is an annoying bug in ruby < 1.9. # Avoid trying to shadow with block parameters # More and more builtin familiar friends # map odds.map { |n| n * n * n } odds.collect { |n| n * n * n } # filter odds.select { |n| n % 3 == 0 } # fold odds.inject(0) { |acc,n| acc + n } odds.reduce(1) { |acc,n| acc * n } odds.inject(:+) # Given no initial accumulator, it uses the first element instead. odds.inject { |acc,n| acc * n } # exists odds.any? {|n| n * n > 100 } odds.all? {|n| n*n < 1000 } # Go peruse the docs. The standard library is chock-full of useful stuff. # These are all methods of Enumberable a mixin used by Array and others. Dan # will talk about mixins. For now, think of them as somewhere between # interfaces and classes. Other classes are Enumerables as well. "Hello".each {|s| puts s} "Hello".map {|s| s + " world"} # Ranges (1..10).each {|n| puts n * n} # More number-related blocks 5.times {puts "hi"} 3.upto(9) {|n| puts n} # Conventions: # ? # If a method returns a boolean, its name usually ends in ? # ! # When methods have pure functional and impure imperative/mutating versions, # the latter ends in ! odds.map! {|n| n + 2} odds # put not everything obeys this convention. # push, pop, etc. # Hashes x = Hash.new x = {} x["a"] = "Found A" x[false] = "Found false" puts x["a"] puts x[false] puts x[42] puts x.keys puts x.values x.delete("a") x = {"SML"=>1, "Racket"=>2, "Ruby"=>3} x["SML"] # Symbols are like strings, but cheaper. Often used with hashes. h = {:sml=>1, :racket=>2, :ruby=>3} # Slightly weird: h.each{|x| puts x} x # oh no! # That's better: h.each{|k,v| puts k} # Word count (performance not ideal) File.open('sec8.rb') {|f| f.read }.split.reduce(Hash.new(0)) { |acc,w| acc[w] += 1; acc } # Ruby's objects really do work like Dan said... 1.send(:+, 5) class Cow def initialize @moos = 0 end def moo @moos += 1 puts "Moo" + "!" * @moos end # ignore *args and &b for now def method_missing(name, *args, &b) puts "Sorry, the method #{name} does not exist. Did you mean moo?" moo end end c = Cow.new c.methods c.send(:moo) c.send(:moo) [1, "hello", c, [4,2]].each do |o| o.send(:+, o) end # Exploratory programming c.class c.class.class c.class.class.methods c.class.class.class c.class.superclass [1,2].methods.find {|m| m.end_with?("?")} # Documentation from the command line. # ri Hash # ri Array.map # Let's write something in Ruby.