Archive for May, 2008

commas in ruby hash literals

# I didn't realize this was possible
# and I still don't know if I like it.
# However, there are reasons for this,
# like easy addition or moving of literal
# entries without thinking about commas

irb(main):001:0> {
irb(main):002:1*   :foo => :bar,
irb(main):003:1*   :baz => :bam,
irb(main):004:1* }
=> {:foo=>:bar, :baz=>:bam}

ruby’s last character in a String

# returns the character code
# I don't know how to translate this back to a String
irb(main):002:0> "bar"[-1]
=> 114

# This works but reads a little awkward
irb(main):001:0> "bar"[-1..-1]
=> "r"

ruby conditional syntax

irb(main):001:0> if 1 == 1
irb(main):002:1>   :foo
irb(main):003:1> elsif 2 == 2
irb(main):004:1>   :bar
irb(main):005:1> elsif 3 == 3
irb(main):006:1>   :baz
irb(main):007:1> else
irb(main):008:1*   :bam
irb(main):009:1> end
=> :foo

irb(main):010:0> if    1 == 1 : :foo
irb(main):011:1> elsif 2 == 2 : :bar
irb(main):012:1> elsif 3 == 3 : :baz
irb(main):013:1> else
irb(main):014:1*   :bam
irb(main):015:1> end
=> :foo

irb(main):028:0> if    1 == 1; :foo
irb(main):029:1> elsif 2 == 2; :bar
irb(main):030:1> elsif 3 == 3; :baz
irb(main):031:1> else
irb(main):032:1*   :bam
irb(main):033:1> end
=> :foo

irb(main):022:0> if    1 == 1 then :foo
irb(main):023:1> elsif 2 == 2 then :bar
irb(main):024:1> elsif 3 == 3 then :baz
irb(main):025:1> else
irb(main):026:1*   :bam
irb(main):027:1> end
=> :foo

irb(main):016:0> if    1 == 1 :foo
irb(main):017:1> elsif 2 == 2 :bar
irb(main):018:1> elsif 3 == 3 :baz
irb(main):019:1> else
irb(main):020:1*   :bam
irb(main):021:1> end
NameError: undefined local variable or method `foo' for main:Object
from (irb):16
from :0

common treetop pattern for parsing lists of things

rule expression_list
  expression tail:(SPACE expression)* {
    def eval(env = {})
      expressions.inject([]) do |exprs, expr|
        exprs << expr.eval(env)
      end
    end

    def expressions
      [ expression ] + tail.elements.map { |e| e.expression }
    end
  }
end

comment and keyword handling in treetop

# whitespace
rule white
[ \r\t\n]+
end

# mandatory space
rule SPACE
(white / comment)+
end

# optional space
rule space
SPACE?
end

# anything but not white
rule non_white_char
!white .
end

# typical keyword rule
rule var_keyword
'var' !non_white_char
end

rule comment
comment_to_eol / multiline_comment
end

rule multiline_comment
'/*' (!'*/' . )* '*/'
end

rule comment_to_eol
# TODO find out why this doesn't work in specs
#'#' (!"\n" .)+ "\n"

'#' (!"\n" .)*
end

(ab)using ruby within treetop(?)

rule case_expression

case_keyword SPACE case_exp:expression SPACE
when_expression_list SPACE
else_keyword SPACE else_exp:statement_list SPACE
end_keyword

{
def eval(env = {})
case_val = case_exp.eval(env)
else_val = else_exp.eval(env)
Kernel.eval <<-CASE_STMT
lambda do
case #{case_val.is_a?(String) ? "'#{case_val}'" : case_val}
#{ruby_when_expressions(env)}
else #{else_val.is_a?(String) ? "'#{else_val}'" : else_val}
end
end [] # call this lambda immediately
CASE_STMT
end

def ruby_when_expressions(env = {})
when_expression_list.eval(env).inject('') do |ruby, e|
# possible string values have been wrapped in '' already
ruby << "when #{e[:condition]} then #{e[:expression]} "
end
end
}

end

sex spam

“Tent your trousers with your new rod” — olossien@BIGIRONTECH.COM

aligned numbers aka zerofill

# zerofill(7,3) => "007"
def zerofill(value, digits = 9)
"%0#{digits}d" % value.to_i
end