Style

Posts tagged with "Style."
  • 25

    SEP
    2014

    Regex Code Equivalency

    #!/usr/bin/env ruby -w
    
    Name = "Gray, James"
    
    !!(Name =~ /\AGray/)      # => true
    Name.start_with?("Gray")  # => true
    
    !!(Name =~ /James\z/)    # => true
    Name.end_with?("James")  # => true
    
    !!(Name =~ /Dana/)     # => false
    Name.include?("Dana")  # => false
    
    !!(Name =~ /\A\z/)  # => false
    Name.empty?         # => false
    
    !!(Name =~ /\AGray, James\z/)  # => true
    Name == "Gray, James"          # => true
    
    !!(Name =~ /\A(?:Gray, James|Gray, Dana)\z/)  # => true
    ["Gray, James", "Gray, Dana"].include?(Name)  # => true
    
    Name =~ /\A\w+/ && $&  # => "Gray"
    Name[/\A\w+/]          # => "Gray"
    
    Name =~ /\A(\w+),\s*(\w+)\z/ && $2  # => "James"
    Name[/\A(\w+),\s*(\w+)\z/, 2]       # => "James"
    
    Name =~ /\A(?<last>\w+),\s*(?<first>\w+)\z/ && $~[:first]  # => "James"
    Name[/\A(?<last>\w+),\s*(?<first>\w+)\z/, :first]          # => "James"
    
    Name.scan(/^.*\n?/)  # => ["Gray, James"]
    Name.lines           # => ["Gray, James"]
    
    Name.scan(/./m)  # => ["G", "r", "a", "y", ",", " ", "J", "a", "m", "e", "s"]
    Name.chars       # => ["G", "r", "a", "y", ",", " ", "J", "a", "m", "e", "s"]
    
    Name.gsub(/[aeiou]/, "")  # => "Gry, Jms"
    Name.delete("aeiou")      # => "Gry, Jms"
    
    Name.gsub(/[aeiou]/, "X") # => "GrXy, JXmXs"
    Name.tr("aeiou", "X")     # => "GrXy, JXmXs"
    
    # For the destructive operations that follow you can drop the `dup()` and
    # switch `sub()` to `sub!()`, as long as you don't care about the return value.
    
    Name.sub(/(?=,)/, " II")                 # => "Gray II, James"
    Name.dup.insert(Name.index(","), " II")  # => "Gray II, James"
    
    Name.sub(/\A/, "Name:  ")    # => "Name:  Gray, James"
    Name.dup.prepend("Name:  ")  # => "Name:  Gray, James"
    
    Name.sub(/\A.*\z/m, "Gray, Dana")  # => "Gray, Dana"
    Name.dup.replace("Gray, Dana")     # => "Gray, Dana"
    
    Name.sub(/\A.*\z/m, "")  # => ""
    Name.dup.clear           # => ""
    
    
    
    Spacey = "\tsome    space\r\n"
    
    Spacey.sub(/\A\s+/, "")  # => "some    space\r\n"
    Spacey.lstrip            # => "some    space\r\n"
    
    Spacey.sub(/\s+\z/, "")  # => "\tsome    space"
    Spacey.rstrip            # => "\tsome    space"
    
    Spacey.sub(/\A\s*(.+?)\s*\z/m, '\1')  # => "some    space"
    Spacey.strip                          # => "some    space"
    
    Spacey.sub(/(?:\r?\n|\r)\z/m, "")  # => "\tsome    space"
    Spacey.chomp                       # => "\tsome    space"
    
    Spacey.sub(/(?:\r\n|.)\z/m, "")  # => "\tsome    space"
    Spacey.chop                      # => "\tsome    space"
    
    Spacey.gsub(/ +/, " ")  # => "\tsome space\r\n"
    Spacey.squeeze(" ")     # => "\tsome space\r\n"
    
  • 27

    AUG
    2014

    Which Types to Type

    I've mentioned before that I'm writing some Rust code, specifically an RPN calculator as a simple exercise. I'm going to dump the code here so we can discuss one aspect of it, but do remember that I'm very new to Rust and this code could surely be better:

    use std::fmt;
    use std::os;
    
    struct Stack {
        numbers: Vec<f64>
    }
    impl Stack {
        fn new() -> Stack {
            Stack{numbers: vec![]}
        }
    
        fn is_empty(&self) -> bool {
            self.numbers.is_empty()
        }
    
        fn push(&mut self, number: f64) {
            self.numbers.push(number);
        }
    
        fn result(&self) -> f64 {
            *self.numbers.last().expect("Stack empty.")
        }
    
        fn add(&mut self)      { self._do_binary_operation(|l, r| l + r); }
        fn subtract(&mut self) { self._do_binary_operation(|l, r| l - r); }
        fn multiply(&mut self) { self._do_binary_operation(|l, r| l * r); }
        fn divide(&mut self)   { self._do_binary_operation(|l, r| l / r); }
    
        fn _do_binary_operation(&mut self, operation: |f64, f64| -> f64) {
            let r = self.numbers.pop().expect("Stack underflow.");
            let l = self.numbers.pop().expect("Stack underflow.");
            self.numbers.push(operation(l, r));
        }
    }
    impl fmt::Show for Stack {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let mut s = String::new();
            let mut i = self.numbers.len();
            for number in self.numbers.iter() {
                i -= 1;
                s = s.add(&format!("{}: {}\n", i, number));
            }
            s.pop_char();
            write!(f, "{}", s)
        }
    }
    
    struct Tokenizer {
        tokens: Vec<String>,
        i:      uint
    }
    impl Tokenizer {
        fn new(expression: &str) -> Tokenizer {
            Tokenizer{
              tokens: expression.split(|c: char| c.is_whitespace())
                                .map(|s| s.to_string())
                                .collect(),
              i:      0
            }
        }
    
        fn has_next_token(&self) -> bool {
            self.i < self.tokens.len()
        }
    
        fn next_token(&mut self) -> &str {
            if !self.has_next_token() { fail!("Tokens exhausted.") }
    
            let token = self.tokens[self.i].as_slice();
            self.i   += 1;
            token
        }
    }
    
    struct RPNCalculator {
        stack:  Stack,
        tokens: Tokenizer
    }
    impl RPNCalculator {
        fn new(stack: Stack, tokens: Tokenizer) -> RPNCalculator {
            RPNCalculator{stack: stack, tokens: tokens}
        }
    
        fn calculate(&mut self) -> f64 {
            while self.tokens.has_next_token() {
                let token = self.tokens.next_token();
                if !self.stack.is_empty() {
                    println!("{}", self.stack);
                }
                println!("T: {}\n", token);
                match token {
                    "+" => { self.stack.add(); }
                    "-" => { self.stack.subtract(); }
                    "*" => { self.stack.multiply(); }
                    "/" => { self.stack.divide(); }
                    n   => { self.stack.push(from_str(n).expect("Not a number.")); }
                }
            }
            if !self.stack.is_empty() {
                println!("{}\n", self.stack);
            }
            self.stack.result()
        }
    }
    
    fn main() {
        let     expression = os::args();
        let     stack      = Stack::new();
        let     tokenizer  = Tokenizer::new(expression[1].as_slice());
        let mut calculator = RPNCalculator::new(stack, tokenizer);
        println!("{}", calculator.calculate());
    }
    

    Read more…

    In: Rusting | Tags: Rust & Style | 0 Comments
  • 1

    APR
    2012

    A Stylish Critique

    Before getting started, I feel compelled to point out that my dictionary defines a critique as "a detailed analysis and assessment of something." It seems like we often assume the worst of that word, but that's not how I intend it here.

    The Ruby community seems to be talking about style guides lately. So let's talk about them.

    The fact is that you will have many choices if you go looking for style guides for our favorite language. You can pick from:

    It's obvious that Rubyists care about this topic. Let's see what's out there and consider what really is and is not useful from these guides.

    What is a style guide really, and why do we even have them?

    Defining style guides is surprisingly tough. I suspect they started out as formatting rules for code, but they have evolved pretty far beyond that now.

    Most guides include general conventions that the author feels are important when writing the language in question. This can go all the way down to how to use certain constructs, opinions on what the author considers idiomatic, and syntax to outright avoid.

    Read more…

  • 8

    OCT
    2008

    Readable Booleans

    There's a great little trick you can do to improve the readability of your code. A common problem is dealing with methods that have a boolean flag arguments. Here's an example I ran into just today in a Rails application:

    def rating_stars(..., clickable = false)
      # ...
    end
    

    The problem with this is that you typically see calls like this scattered around the application:

    <%= rating_stars(..., true) %>
    

    Would you know what true did there if I hadn't shown you the name of the variable first? I didn't. I had to go hunting for that method definition.

    Ironically the opposite problem, a magical dangling false, is much more rare in my experience. That's typically the default for these kind of arguments and it just makes more sense and reads better to leave it out.

    Anyway, the point is that we can typically improve the ease of understanding the common case. Remember that in Ruby false and nil are false while everything else is true. That means that truth is very loosely defined and we can pass a lot of things for our boolean flag value. For example, after looking up the method and understanding what was needed, I chose to call it like this:

    Read more…

    In: Ruby Voodoo | Tags: APIs & Style | 2 Comments
  • 7

    OCT
    2008

    DSL Block Styles

    There's an argument that rages in the Ruby camps: to instance_eval() or not to instance_eval(). Most often this argument is triggered by DSL discussions where we tend to want code like:

    configurable.config do
      width 100
      mode  :wrap
    end
    

    You can accomplish something like this by passing the block to instance_eval() and changing self to an object that defines the width() and mode() methods. Of course changing self is always dangerous. We may have already been inside an object and planning to use methods from that namespace:

    class MyObject
      include Configurable       # to get the config() method shown above
    
      def initialize
        config do
          width calculate_width  # a problem:  may not work with instance_eval()
        end
      end
    
      private
    
      def calculate_width        # the method we want to use
        # ...
      end
    end
    

    In this example, if width() comes from a different configuration object, we're in trouble. The instance_eval() will shift the focus away from our MyObject instance and we will get a NoMethodError when we try to call calculate_width(). This may prevent us from being able to use Configurable in our code.

    Read more…

    In: Ruby Voodoo | Tags: DSLs & Style | 7 Comments
  • 13

    JUN
    2006

    Do I Need (These Parentheses()?)

    If you came to Ruby via the Learn to Program book or just don't yet have a consistent set of rules for when you do and don't need parentheses in Ruby code, this post is for you.

    I have nothing against Learn to Program, just to be clear. A member of my family is learning Ruby from it and it's going pretty well. I recommend it. However, Chris is a little inconsistent with his use of parentheses in the code samples, and worse, he doesn't really give you a good set of rules to decide when to make the choice. No problem. Let me give you the rules.

    I'm a chess player. In learning chess, you really go through two phases. First, you learn the rules of strategy. These will make you good because the rules are designed to help you avoid common mistakes. Now, to get great, you go through the second phase: learning when to break the strategy rules. Ruby is exactly the same.

    Here's the only rule of strategy you need to learn to get good: methods need parentheses around their arguments.

    Read more…