170 likes | 308 Views
CS 480/680 – Comparative Languages. Ruby Containers, Blocks, and Iterators. Array Review. Ruby arrays are collections of object references Arrays must be expressly created, but are dynamically sized Undefined elements have the value nil , which also equates to false
E N D
CS 480/680 – Comparative Languages Ruby Containers, Blocks, and Iterators
Array Review • Ruby arrays are collections of object references • Arrays must be expressly created, but are dynamically sized • Undefined elements have the value nil, which also equates to false • Arrays are indexed with [] • First element is 0 • Negative numbers start at the end • array[-1] is the last element • See array.rb Blocks & Iterators
Useful array operators • & – array intersection • [ 1, 1, 3, 5 ] & [ 1, 2, 3 ] » [1, 3] • * – repetition • [ 1, 2, 3 ] * 2 » [1, 2, 3, 1, 2, 3] • + – concatenation • [ 1, 2, 3 ] + [ 3, 4, 5 ] » [1, 2, 3, 3, 4, 5] • | – union • [ 1, 2, 3 ] | [ 3, 4, 5 ] » [1, 2, 3, 4, 5] • delete • a = [ 1, 2, 3, 3, 5 ]a.delete(3)a » [1, 2, 3, 3, 4, 5] Blocks & Iterators
More useful array operators • empty? – returns true if empty, else false • index(c) – returns index of first element == c • join – concatenates array elements into a string • [ 1, 2, 3].join » “123” • [ 1, 2, 3].join(“-”) » “1-2-3” • length – returns # elements • nitems – returns # non-nil elements • reverse, sort – return a reversed/sorted array • Many others in the Ruby book: Built-in Classes and Methods/Array Blocks & Iterators
Arrays as stacks and queues • a.push(item) – add item to the end of an a • a.pop – returns the last item of a, or nil if empty • a.shift – returns and removes the first element of a, shifts every other element down by one • a.unshift(item) – prepends item to the start of a, moving all elements up one index • Stack – push & pop • Queue – push & shift Blocks & Iterators
Arrays as method parameters • a = [1, 2, 3, 4, 5, ‘a’, ‘b’, ‘c’] • someMethod(a) – passes one array argument • someMethod(*a) – passes 8 parameters, the elements of the array (expands the array) • def someMethod(*a) … collect all the parameters passed into array a Blocks & Iterators
Hashes • While the index to an array is an integer, the index to a hash can be any type • Some care must be taken here… more on that later • A hash is essentially a list of key value pairs • No implicit ordering • Can’t do stacks/queues • Most common data structure in Ruby! • h = { 'dog' => 'canine', 'cat' => 'feline', \ 'donkey' => 'asinine' } • h.length » 3 ; h['dog'] » "canine" Blocks & Iterators
Implementation Details • See jukebox.rb • Note: • Functions that behave differently with different types of arguments (similar to C++ overloading, but implemented very differently) • Use of blocks and iterators: @songs.find{} • Array as a stack/queue Blocks & Iterators
Ruby Iterators • An iterator in Ruby is a method that gets passed a code block, and it runs that code block on every element in a collection, and returns a specific result • Code blocks are enclosed in {} • Parameters to code blocks are listed between |’s Blocks & Iterators
Iterators for arrays • See iterators.rb • a.each – calls block once for each item in a, passing the item as a parameter • a.each_index – passes the index, not the item • b = a.collect – calls block once for each item in a, block’s return values are collected in b • a.sort – optional block • a.delete_if – block should return true or false • a.find – return first element of array for which block returns true Blocks & Iterators
Writing your own iterators • An iterator is simply a method that calls a block of code, possibly passing parameters • Example: Given a chunk of code, execute it three times. • Solution: • C/C++ maybe possible with function pointers • Ruby: def threeTimes yield yield yield end threeTimes { puts "Hello" } Call any block passed to this method. Blocks & Iterators
Iterator Parameters • Call any block of code, passing it each even number up to n: def evenUpTo(max) i = 2 while i <= max yield i i *= 2 end end evenUpTo(1000) { |f| print f, " " } Blocks & Iterators
Another example • The find() method for class SongList might be implemented like this: class SongList def find for i in 0...songs.size title = songs[i].name return title if yield(title) end return nil end end # Find first song title starting with ‘A’: myList.find {|title| title[0,1] == ‘A’ } Blocks & Iterators
Last iterator example • Iterators are very useful in file I/O: f = File.open("testfile") f.each {|line| print line } f.close Blocks & Iterators
Blocks • Ruby style programming uses blocks and iterators as often as possible • Blocks cannot use an explicit return() statement, the last value calculated in the block is the return value • Blocks can be specified between {}’s or between a do and end pair Blocks & Iterators
Blocks for transactions • If File.open is passed a block, it will… • Open the file • Call the block, passing it the opened file object • Close the file when the block exits File.open("testfile") do |f| f.each {|line| print line end Blocks & Iterators
Exercises • Write a simple RPN calculator, using an array as a stack, and only dealing with operators +, -, *, and / • Write a subroutine (method) that takes a variable number of arguments and prints them all to standard out • Write a program that uses array.collect to look at an array, and copy every element divisible by three into a new array • Write an iterator for your student class that returns an array of each test score that passes a test – the test is the block for the iterator and should return true or false. Call the iterator collect_exams_if Blocks & Iterators