Iterators

Posts tagged with "Iterators."
  • 11

    SEP
    2014

    Experimenting With Ownership

    Let's use a trivial exercise to see what we can learn about ownership, moving, borrowing, and more in Rust. Here's the idea:

    1. We'll allocate a list of numbers
    2. We'll add one to each number in the list
    3. We'll print the resulting list of numbers

    This is a simple process requiring only a few lines of code:

    fn main() {
        let mut numbers = vec![1u, 2, 3];
        for n in numbers.mut_iter() {
            *n += 1;
        }
        println!("{}", numbers);
    }
    

    The output is hopefully what we all expect to see:

    $ ./one_function 
    [2, 3, 4]
    

    In this code there is just one variable: numbers. That variable owns a list of numbers on the heap and it's scope is limited to the main() function, which is just a way to say that the data exists for the length of that function call. Since all three steps happen in that one function call, ownership doesn't really affect us here.

    To better examine what ownership really means, let's add one small twist to our exercise:

    • The increment of each number in the list must happen in a separate function

    Read more…

  • 11

    FEB
    2012

    Test Driving an Algorithm (Part 2)

    In the last article, I built a quick and dirty solution to PuzzleNode's Hitting Rock Bottom puzzle. I didn't use specs, objects, or even multiple files. In this article, I'll repeat the exercise but using all of those elements. Let's see how that affects the results.

    The Disciplined Approach

    This time, I'll reign in my desire to push forward and solve the problem more carefully, without having to build a fully formed algorithm all at once.

    I still think the input is the right place to start. I need to read in the units. Let's add a spec for that in spec/parser_spec.rb:

    require "minitest/autorun"
    require "stringio"
    
    require "hitting_rock_bottom/parser"
    
    describe HittingRockBottom::Parser do
      let(:units)  { 42 }
      let(:io)     { StringIO.new(units.to_s) }
      let(:parser) { HittingRockBottom::Parser.new(io) }
    
      it "reads the units number from the beginning of the stream" do
        parser.units.must_equal(units)
      end
    end
    

    If you haven't seen the standard stringio library before, it simply wraps a String with an IO interface. That's will allow me to call gets() and other IO methods on it in my implementation. It's perfect for tests like this.

    Read more…

  • 21

    JAN
    2012

    Iteration Patterns

    I love studying how the human brain works. It's an amazing biological machine capable of impressive feats. Of course, it also has its quirks.

    For example, the brain is a terrific pattern matcher. That's probably one of its favorite activities. It wants to do this so much that it will often even find patterns that aren't there.

    While this "feature" of your brain can get you into trouble, you can also make it work for you. Some parts of programming really are about patterns. If you prime your brain with the right data, it will just take over and do one of the things it does best.

    How I Teach Iterators

    One evening, at a post Ruby conference dinner, Glenn Vanderburg and I had a lengthy discussion about iterators and patterns. During this discussion we nailed down a plan for how the iterators could be taught.

    I know that we've both used the strategy we came up with in multiple Ruby trainings and we have both seen it work wonders. This is hands down the best way to learn the iterators, in my opinion.

    Read more…

  • 21

    DEC
    2011

    Refactoring: rcat

    I use these Rubies in the Rough articles to teach how I think about code. Well, I have a scary admission to make: I didn't really understand refactoring until I was many years into being a programmer. Sure, I knew what it meant, but I just didn't get it. I hope to save you from the same mistake.

    Refactoring is important. Very important. It may be one of the most important things we do as programmers. If I learned one thing from reading Smalltalk Best Practice Patterns, it's that code's primary purpose is to communicate with the reader. Let's face it though, when we are trying to get something working, it's often like stumbling around in the dark. We are running into all kinds of things, breaking stuff, and just trying to reach that "Holy cow it works!" moment. We're probably not thinking too long and hard about how well this mess we are making communicates and that's perfectly fine.

    Refactoring is where you get to fix that. It's about taking working code and making it sexy. Note that I said it starts with working code. Until you have that, there's nothing worth communicating to a potential reader. Make it work, then make it sexy. (I believe that saying really involves speed, but that's a very different conversation we can have at a later date.)

    Read more…

  • 11

    DEC
    2011

    Even More Eloquent Ruby

    I recently read Eloquent Ruby so we can discuss it on an upcoming Ruby Rogues episode with author Russ Olsen. In short, the book is fantastic. You should definitely read it.

    I, on the other hand, am cranky. When you have read Ruby books since the first one was published (literally!), you can always find something to complain about. There are a handful of examples in Eloquent Ruby that could be better, in my opinion. I thought I would show you some of those. If you've read the book, this should make a nice supplement. Don't worry if you haven't though, you will still be able to follow these ideas just fine. I also won't spoil the ending, but you all know that the Rubyist saves the day.

    Before I start, let me stress one more time that this is a terrific book. It has so many clear discussions of real issues Rubyists must face when writing code like class variables, the differences between lambda(), proc(), and Proc.new(), how to use blocks and modules, why people think Ruby leaks memory and how you can avoid those problems, plus more. Don't let any fun I poke at the examples below change your view of this book. If I didn't love it, I wouldn't have bothered to write this article.

    Read more…

  • 7

    JAN
    2009

    The Evils of the For Loop

    I've never liked the for…in loop in Ruby. I cringe every time I see it in examples (Rails seems to put it in views a lot) and I tend to switch it to an each() call. It really bugs me.

    That's mostly just my gut reaction, but if I had to put it into words it's that I fell in love with Ruby's iterators early on and for just doesn't seem to fit in well with them. I don't think that's just my emotions talking either, it really doesn't fit in. I'll try to show you why I say that.

    First, let's see what I'm talking about. We are all pretty comfortable with each(), right?

    (1..3).each { |i| p i }
    # >> 1
    # >> 2
    # >> 3
    

    I doubt that surprises anyone. Many of you probably also know that Ruby allows you to write that as:

    for i in 1..3
      p i
    end
    # >> 1
    # >> 2
    # >> 3
    

    That's almost the same thing. It really does use each() under the hood, for example:

    class MyEachThing
      def each
        yield 1
        yield 42
        yield 2
        yield 42
        yield 3
      end
    end
    
    for i in MyEachThing.new
      p i
    end
    # >> 1
    # >> 42
    # >> 2
    # >> 42
    # >> 3
    

    Read more…

  • 2

    JAN
    2008

    Getting FasterCSV Ready for Ruby 1.9

    The call came down from on high just before the Ruby 1.9 release: replace the standard csv.rb library with faster_csv.rb. With only hours to make the change it was a little harder than I expected. The FasterCSV code base was pretty vanilla Ruby, but it required more work than I would have guessed to get running on Ruby 1.9. Let me share a few of the tips I learned while doctoring the code in the hope that it will help others get their code ready for Ruby 1.9.

    Ruby's String Class Grows Up

    One of the biggest changes in Ruby 1.9 is the addition of m17n (multilingualization). This means that Ruby's Strings are now encoding aware and we must clarify in our code if we are working with bytes, characters, or lines.

    This is a good change, but the odds are that most of us have lazily used the old way to our advantage in the past. If you've ever written code like:

    lines = str.to_a
    

    you have bad habits to break. I sure did. Under Ruby 1.9 that code would translate to:

    lines = str.lines.to_a
    

    Read more…

  • 21

    MAR
    2006

    The Why and How of Iterators

    A friend of mine has been asking some general questions about iterators in private emails we have traded. I wanted to put some of my answers here, in case they appeal to a wider audience.

    Why do we have iterators?

    First, let's invent a little data to play with:

    >> Name = Struct.new(:first, :last)
    => Name
    >> names = [ Name.new("James", "Gray"),
    ?>           Name.new("Dana", "Gray"),
    ?>           Name.new("Caleb", "Nordloh"),
    ?>           Name.new("Tina", "Nordloh") ]
    => [#<struct Name first="James", last="Gray">,
        #<struct Name first="Dana", last="Gray">,
        #<struct Name first="Caleb", last="Nordloh">,
        #<struct Name first="Tina", last="Nordloh">]
    

    Now let's assume we want to print some names. We can use the each() iterator for that, no index:

    >> names.each { |name| puts "#{name.last}, #{name.first}" }
    Gray, James
    Gray, Dana
    Nordloh, Caleb
    Nordloh, Tina
    => [#<struct Name first="James", last="Gray">,
        #<struct Name first="Dana", last="Gray">,
        #<struct Name first="Caleb", last="Nordloh">,
        #<struct Name first="Tina", last="Nordloh">]
    

    Read more…

  • 31

    JAN
    2006

    Iterators (Chapters 4 and 5)

    Due to a printing error, these two chapters actually came out longer than intended. Originally their contents were: "Use Ruby."

    All jokes aside, there's really not a whole lot for me to talk about from these chapters, since iterators are so internal to Ruby. Readers from our camp should run into a lot less surprises here that the intended audience. Just translate MDJ's anonymous subroutines to blocks, replace his returns with yields, and you are 90% of the way there.

    Here are translations for some of the examples in these chapters. I think these all come out cleaner and more natural in Ruby, but you be the judge:

    Permutations

    #!/usr/local/bin/ruby -w
    
    def permute(items)
      0.upto(1.0/0.0) do |count|
        pattern = count_to_pattern(count, items.size) or break
        puts "Pattern #{pattern.join(' ')}:" if $DEBUG
        yield(pattern_to_permutation(pattern, items.dup))
      end
    end
    
    def pattern_to_permutation(pattern, items)
      pattern.inject(Array.new) { |results, i| results + items.slice!(i, 1) }
    end
    
    def count_to_pattern(count, item_count)
      pattern = (1..item_count).inject(Array.new) do |pat, i|
        pat.unshift(count % i)
        count /= i
        pat
      end
      count.zero? ? pattern : nil
    end
    
    if ARGV.empty?
      abort "Usage:  #{File.basename($PROGRAM_NAME)} LIST_OF_ITEMS"
    end
    
    permute(ARGV) { |perm| puts(($DEBUG ? "  " : "") + perm.join(" ")) }
    

    Read more…

  • 5

    JAN
    2006

    Code as a Data Type

    Introduction

    This is the first of a series of articles where I will try to demystify some Ruby idioms for the people who come to Ruby through Rails and find themselves wanting to learn a little more about the language under the hood.

    Strings, Arrays, ... and Code?

    You don't have to code for long in any language before you get intimately familiar with some standard data types. We all have a fair grasp of Ruby's String and Array, because every language has something similar. Ruby has an unusual data type though, which can trip up newcomers. That type is Ruby code itself.

    Allow me to explain what I mean, through an example. First, let's create a little in-memory database to work with:

    class ClientDB
      Record = Struct.new(:client_name, :location, :projects)
    
      def initialize
        @records = [ Record.new( "Gray Soft", "Oklahoma",
                                 ["Ruby Quiz", "Rails Extensions"] ),
                     Record.new( "Serenity Crew", "Deep Space",
                                 ["Ship Enhancements"] ),
                     Record.new( "Neo", "Hollywood", 
                                 ["Rails interface for the Matrix"] ) ]
      end
    end
    

    Read more…