Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Burlington Ruby Conference Keynote 2014

Burlington Ruby Conference Keynote 2014

Opening keynote for Burlington Ruby Conference.

Ernie Miller

August 02, 2014
Tweet

More Decks by Ernie Miller

Other Decks in Technology

Transcript

  1. =

  2. = /

  3. =

  4. – Dad “I owe you an apology. I used to

    think you were lazy. Now I realize you were just selective.”
  5. sub _parse_predicate_in_handler { my( $flag, $score)= @_[1..2]; $_[0]=~ s{( ($REG_STRING)

    # strings |\@($REG_TAG_NAME)(\s* $REG_MATCH \s* $REG_REGEXP) # @att and regexp |\@($REG_TAG_NAME)(?=\s*(?:[><=!])) # @att followed by a comparison operator |\@($REG_TAG_NAME) # @att (not followed by a comparison operator) |=~|!~ # matching operators |([><]=?|=|!=)(?=\s*[\d+-]) # test before a number |([><]=?|=|!=) # test, other cases |($REG_FUNCTION) # no arg functions # this bit is a mess, but it is the only solution with this half-baked parser |(string\(\s*$REG_NAME\s*\)\s*$REG_MATCH\s*$REG_REGEXP) # string( child)=~ /regexp/ |(string\(\s*$REG_NAME\s*\)\s*$REG_COMP\s*$REG_STRING) # string( child) = "value" (or other test) |(string\(\s*$REG_NAME\s*\)\s*$REG_COMP\s*$REG_NUMBER) # string( child) = nb (or other test) |(and|or) # |($REG_NAME(?=\s*(and|or|$))) # nested tag name (needs to be after all other unquoted strings) |($REG_TAG_IN_PREDICATE) # nested tag name (needs to be after all other unquoted strings) )} { my( $token, $str, $att_re_name, $att_re_regexp, $att, $bare_att, $num_test, $alpha_test, $func, $str_regexp, $str_test_alpha, $str_test_num, $and_or, $tag) = ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14); $score->{predicates}++; # store tests on text (they are not always allowed) if( $func || $str_regexp || $str_test_num || $str_test_alpha ) { $flag->{test_on_text}= 1; } ! if( defined $str) { $token } elsif( $tag) { qq{(\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->has_child( '$tag'))} } elsif( $att) { $att=~ m{^#} ? qq{ (\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->{att}->{'$att'})} : qq{\$elt->{'$att'}} } elsif( $att_re_name) { $att_re_name=~ m{^#} ? qq{ (\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->{att}->{'$att_re_name'}$att_re_regexp)} : qq{\$elt->{'$att_re_name'}$att_re_regexp} } # for some reason Devel::Cover flags the following lines as not tested. They are though. elsif( $bare_att) { $bare_att=~ m{^#} ? qq{(\$elt->{'$ST_ELT'} && defined(\$elt->{'$ST_ELT'}->{att}->{'$bare_att'}))} : qq{defined( \$elt->{'$bare_att'})} } elsif( $num_test && ($num_test eq '=') ) { "==" } # others tests are unchanged elsif( $alpha_test) { $PERL_ALPHA_TEST{$alpha_test} } elsif( $func && $func=~ m{^string}) { "\$elt->{'$ST_ELT'}->text"; } elsif( $str_regexp && $str_regexp =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_MATCH)\s*($REG_REGEXP)}) { "defined( _first_n { \$_->text $2 $3 } 1, \$elt->{'$ST_ELT'}->_children( '$1'))"; } elsif( $str_test_alpha && $str_test_alpha =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_COMP)\s*($REG_STRING)}) { my( $tag, $op, $str)= ($1, $2, $3); $str=~ s{(?<=.)'(?=.)}{\\'}g; # escape a quote within the string $str=~ s{^"}{'}; $str=~ s{"$}{'}; "defined( _first_n { \$_->text $PERL_ALPHA_TEST{$op} $str } 1, \$elt->{'$ST_ELT'}->children( '$tag'))"; } elsif( $str_test_num && $str_test_num =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_COMP)\s*($REG_NUMBER)}) { my $test= ($2 eq '=') ? '==' : $2; "defined( _first_n { \$_->text $test $3 } 1, \$elt->{'$ST_ELT'}->children( '$1'))"; } elsif( $and_or) { $score->{tests}++; $and_or eq 'and' ? '&&' : '||' ; } else { $token; } }gexs; } Twig.pm, L1765-1823
  6. sub _parse_predicate_in_handler { my( $flag, $score)= @_[1..2]; $_[0]=~ s{( ($REG_STRING)

    # strings |\@($REG_TAG_NAME)(\s* $REG_MATCH \s* $REG_REGEXP) # @att and regexp |\@($REG_TAG_NAME)(?=\s*(?:[><=!])) # @att followed by a comparison operator |\@($REG_TAG_NAME) # @att (not followed by a comparison operator) |=~|!~ # matching operators |([><]=?|=|!=)(?=\s*[\d+-]) # test before a number |([><]=?|=|!=) # test, other cases |($REG_FUNCTION) # no arg functions # this bit is a mess, but it is the only solution with this half-baked parser |(string\(\s*$REG_NAME\s*\)\s*$REG_MATCH\s*$REG_REGEXP) # string( child)=~ /regexp/ |(string\(\s*$REG_NAME\s*\)\s*$REG_COMP\s*$REG_STRING) # string( child) = "value" (or other test) |(string\(\s*$REG_NAME\s*\)\s*$REG_COMP\s*$REG_NUMBER) # string( child) = nb (or other test) |(and|or) # |($REG_NAME(?=\s*(and|or|$))) # nested tag name (needs to be after all other unquoted strings) |($REG_TAG_IN_PREDICATE) # nested tag name (needs to be after all other unquoted strings) )} { my( $token, $str, $att_re_name, $att_re_regexp, $att, $bare_att, $num_test, $alpha_test, $func, $str_regexp, $str_test_alpha, $str_test_num, $and_or, $tag) = ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14); $score->{predicates}++; # store tests on text (they are not always allowed) if( $func || $str_regexp || $str_test_num || $str_test_alpha ) { $flag->{test_on_text}= 1; } ! if( defined $str) { $token } elsif( $tag) { qq{(\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->has_child( '$tag'))} } elsif( $att) { $att=~ m{^#} ? qq{ (\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->{att}->{'$att'})} : qq{\$elt->{'$att'}} } elsif( $att_re_name) { $att_re_name=~ m{^#} ? qq{ (\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->{att}->{'$att_re_name'}$att_re_regexp)} : qq{\$elt->{'$att_re_name'}$att_re_regexp} } # for some reason Devel::Cover flags the following lines as not tested. They are though. elsif( $bare_att) { $bare_att=~ m{^#} ? qq{(\$elt->{'$ST_ELT'} && defined(\$elt->{'$ST_ELT'}->{att}->{'$bare_att'}))} : qq{defined( \$elt->{'$bare_att'})} } elsif( $num_test && ($num_test eq '=') ) { "==" } # others tests are unchanged elsif( $alpha_test) { $PERL_ALPHA_TEST{$alpha_test} } elsif( $func && $func=~ m{^string}) { "\$elt->{'$ST_ELT'}->text"; } elsif( $str_regexp && $str_regexp =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_MATCH)\s*($REG_REGEXP)}) { "defined( _first_n { \$_->text $2 $3 } 1, \$elt->{'$ST_ELT'}->_children( '$1'))"; } elsif( $str_test_alpha && $str_test_alpha =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_COMP)\s*($REG_STRING)}) { my( $tag, $op, $str)= ($1, $2, $3); $str=~ s{(?<=.)'(?=.)}{\\'}g; # escape a quote within the string $str=~ s{^"}{'}; $str=~ s{"$}{'}; "defined( _first_n { \$_->text $PERL_ALPHA_TEST{$op} $str } 1, \$elt->{'$ST_ELT'}->children( '$tag'))"; } elsif( $str_test_num && $str_test_num =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_COMP)\s*($REG_NUMBER)}) { my $test= ($2 eq '=') ? '==' : $2; "defined( _first_n { \$_->text $test $3 } 1, \$elt->{'$ST_ELT'}->children( '$1'))"; } elsif( $and_or) { $score->{tests}++; $and_or eq 'and' ? '&&' : '||' ; } else { $token; } }gexs; } Twig.pm, L1765-1823 (of 14006)
  7. sub _parse_predicate_in_handler { my( $flag, $score)= @_[1..2]; $_[0]=~ s{( ($REG_STRING)

    # strings |\@($REG_TAG_NAME)(\s* $REG_MATCH \s* $REG_REGEXP) # @att and regexp |\@($REG_TAG_NAME)(?=\s*(?:[><=!])) # @att followed by a comparison operator |\@($REG_TAG_NAME) # @att (not followed by a comparison operator) |=~|!~ # matching operators |([><]=?|=|!=)(?=\s*[\d+-]) # test before a number |([><]=?|=|!=) # test, other cases |($REG_FUNCTION) # no arg functions # this bit is a mess, but it is the only solution with this half-baked parser |(string\(\s*$REG_NAME\s*\)\s*$REG_MATCH\s*$REG_REGEXP) # string( child)=~ /regexp/ |(string\(\s*$REG_NAME\s*\)\s*$REG_COMP\s*$REG_STRING) # string( child) = "value" (or other test) |(string\(\s*$REG_NAME\s*\)\s*$REG_COMP\s*$REG_NUMBER) # string( child) = nb (or other test) |(and|or) # |($REG_NAME(?=\s*(and|or|$))) # nested tag name (needs to be after all other unquoted strings) |($REG_TAG_IN_PREDICATE) # nested tag name (needs to be after all other unquoted strings) )} { my( $token, $str, $att_re_name, $att_re_regexp, $att, $bare_att, $num_test, $alpha_test, $func, $str_regexp, $str_test_alpha, $str_test_num, $and_or, $tag) = ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14); $score->{predicates}++; # store tests on text (they are not always allowed) if( $func || $str_regexp || $str_test_num || $str_test_alpha ) { $flag->{test_on_text}= 1; } ! if( defined $str) { $token } elsif( $tag) { qq{(\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->has_child( '$tag'))} } elsif( $att) { $att=~ m{^#} ? qq{ (\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->{att}->{'$att'})} : qq{\$elt->{'$att'}} } elsif( $att_re_name) { $att_re_name=~ m{^#} ? qq{ (\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->{att}->{'$att_re_name'}$att_re_regexp)} : qq{\$elt->{'$att_re_name'}$att_re_regexp} } # for some reason Devel::Cover flags the following lines as not tested. They are though. elsif( $bare_att) { $bare_att=~ m{^#} ? qq{(\$elt->{'$ST_ELT'} && defined(\$elt->{'$ST_ELT'}->{att}->{'$bare_att'}))} : qq{defined( \$elt->{'$bare_att'})} } elsif( $num_test && ($num_test eq '=') ) { "==" } # others tests are unchanged elsif( $alpha_test) { $PERL_ALPHA_TEST{$alpha_test} } elsif( $func && $func=~ m{^string}) { "\$elt->{'$ST_ELT'}->text"; } elsif( $str_regexp && $str_regexp =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_MATCH)\s*($REG_REGEXP)}) { "defined( _first_n { \$_->text $2 $3 } 1, \$elt->{'$ST_ELT'}->_children( '$1'))"; } elsif( $str_test_alpha && $str_test_alpha =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_COMP)\s*($REG_STRING)}) { my( $tag, $op, $str)= ($1, $2, $3); $str=~ s{(?<=.)'(?=.)}{\\'}g; # escape a quote within the string $str=~ s{^"}{'}; $str=~ s{"$}{'}; "defined( _first_n { \$_->text $PERL_ALPHA_TEST{$op} $str } 1, \$elt->{'$ST_ELT'}->children( '$tag'))"; } elsif( $str_test_num && $str_test_num =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_COMP)\s*($REG_NUMBER)}) { my $test= ($2 eq '=') ? '==' : $2; "defined( _first_n { \$_->text $test $3 } 1, \$elt->{'$ST_ELT'}->children( '$1'))"; } elsif( $and_or) { $score->{tests}++; $and_or eq 'and' ? '&&' : '||' ; } else { $token; } }gexs; } Twig.pm, L1765-1823 (of 14006) search
  8. sub _parse_predicate_in_handler { my( $flag, $score)= @_[1..2]; $_[0]=~ s{( ($REG_STRING)

    # strings |\@($REG_TAG_NAME)(\s* $REG_MATCH \s* $REG_REGEXP) # @att and regexp |\@($REG_TAG_NAME)(?=\s*(?:[><=!])) # @att followed by a comparison operator |\@($REG_TAG_NAME) # @att (not followed by a comparison operator) |=~|!~ # matching operators |([><]=?|=|!=)(?=\s*[\d+-]) # test before a number |([><]=?|=|!=) # test, other cases |($REG_FUNCTION) # no arg functions # this bit is a mess, but it is the only solution with this half-baked parser |(string\(\s*$REG_NAME\s*\)\s*$REG_MATCH\s*$REG_REGEXP) # string( child)=~ /regexp/ |(string\(\s*$REG_NAME\s*\)\s*$REG_COMP\s*$REG_STRING) # string( child) = "value" (or other test) |(string\(\s*$REG_NAME\s*\)\s*$REG_COMP\s*$REG_NUMBER) # string( child) = nb (or other test) |(and|or) # |($REG_NAME(?=\s*(and|or|$))) # nested tag name (needs to be after all other unquoted strings) |($REG_TAG_IN_PREDICATE) # nested tag name (needs to be after all other unquoted strings) )} { my( $token, $str, $att_re_name, $att_re_regexp, $att, $bare_att, $num_test, $alpha_test, $func, $str_regexp, $str_test_alpha, $str_test_num, $and_or, $tag) = ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14); $score->{predicates}++; # store tests on text (they are not always allowed) if( $func || $str_regexp || $str_test_num || $str_test_alpha ) { $flag->{test_on_text}= 1; } ! if( defined $str) { $token } elsif( $tag) { qq{(\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->has_child( '$tag'))} } elsif( $att) { $att=~ m{^#} ? qq{ (\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->{att}->{'$att'})} : qq{\$elt->{'$att'}} } elsif( $att_re_name) { $att_re_name=~ m{^#} ? qq{ (\$elt->{'$ST_ELT'} && \$elt->{'$ST_ELT'}->{att}->{'$att_re_name'}$att_re_regexp)} : qq{\$elt->{'$att_re_name'}$att_re_regexp} } # for some reason Devel::Cover flags the following lines as not tested. They are though. elsif( $bare_att) { $bare_att=~ m{^#} ? qq{(\$elt->{'$ST_ELT'} && defined(\$elt->{'$ST_ELT'}->{att}->{'$bare_att'}))} : qq{defined( \$elt->{'$bare_att'})} } elsif( $num_test && ($num_test eq '=') ) { "==" } # others tests are unchanged elsif( $alpha_test) { $PERL_ALPHA_TEST{$alpha_test} } elsif( $func && $func=~ m{^string}) { "\$elt->{'$ST_ELT'}->text"; } elsif( $str_regexp && $str_regexp =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_MATCH)\s*($REG_REGEXP)}) { "defined( _first_n { \$_->text $2 $3 } 1, \$elt->{'$ST_ELT'}->_children( '$1'))"; } elsif( $str_test_alpha && $str_test_alpha =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_COMP)\s*($REG_STRING)}) { my( $tag, $op, $str)= ($1, $2, $3); $str=~ s{(?<=.)'(?=.)}{\\'}g; # escape a quote within the string $str=~ s{^"}{'}; $str=~ s{"$}{'}; "defined( _first_n { \$_->text $PERL_ALPHA_TEST{$op} $str } 1, \$elt->{'$ST_ELT'}->children( '$tag'))"; } elsif( $str_test_num && $str_test_num =~ m{string\(\s*($REG_TAG_NAME)\s*\)\s*($REG_COMP)\s*($REG_NUMBER)}) { my $test= ($2 eq '=') ? '==' : $2; "defined( _first_n { \$_->text $test $3 } 1, \$elt->{'$ST_ELT'}->children( '$1'))"; } elsif( $and_or) { $score->{tests}++; $and_or eq 'and' ? '&&' : '||' ; } else { $token; } }gexs; } Twig.pm, L1765-1823 (of 14006) search replace
  9. –Larry Wall, Programming Perl “We will encourage you to develop

    the three great virtues of a programmer: laziness, impatience, and hubris.”
  10. $ python3 Python 3.4.1 (default, May 19 2014, 13:10:29) [GCC

    4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import this The Zen of Python, by Tim Peters ! Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! >>>
  11. $ python3 Python 3.4.1 (default, May 19 2014, 13:10:29) [GCC

    4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import this The Zen of Python, by Tim Peters ! Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! >>>
  12. $ python3 Python 3.4.1 (default, May 19 2014, 13:10:29) [GCC

    4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import this The Zen of Python, by Tim Peters ! Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! >>> quit Use quit() or Ctrl-D (i.e. EOF) to exit >>> quit() $
  13. “Ruby stole everything good from Perl; [...] then Matz took

    the best of list processing from Lisp, and the best of OO from Smalltalk and other languages, and the best of iterators from CLU, and pretty much the best of everything from everyone. ! And he somehow made it all work together so well that you don't even notice that it has all that stuff.”! –Steve Yegge, Tour de Babel (2004) http://steve.yegge.googlepages.com/tour-de-babel
  14. – Tony Arcieri “Celluloid solves some of the synchronization problems

    of multithreaded programs, but not all of them. It’s still possible to share objects sent in messages between Celluloid actors, and it’s possible for concurrent mutations in these objects go unnoticed. ! I don’t think I can solve these problems effectively without VM-level support in the form of the aforementioned proposed features to core Ruby.” http://tonyarcieri.com/2012-the-year-rubyists-learned-to-stop-worrying-and-love-the-threads
  15. – Tony Arcieri “Eventually you’re in a place where you’re

    trying to build a jet engine out of silly putty.”
  16. –Matz (2001) http://www.linuxdevcenter.com/pub/a/linux/2001/11/29/ruby.html “I believe people want to express themselves

    when they program. They don't want to fight with the language. ! Programming languages must feel natural to programmers. I tried to make people enjoy programming and concentrate on the fun and creative part of programming when they use Ruby.”