Gray Soft

The programming blog of James Edward Gray II (JEG2).
  • 16

    FEB
    2007

    The Ruby VM: Episode I

    Hello and thank you both for agreeing to answer my questions. To begin, would you please introduce yourselves and tell us about your role in Ruby's development?

    Matz:

    I am the designer and the first implementer of the Ruby language. My real name is Yukihiro Matsumoto, that sounds something like You-Key-Hero Matz-Motor in English. But it's too long to remember and pronounce, so just call me Matz.

    I have been developing Ruby since 1993. It is now quite complicated and has performance problem. I have had vague plan of rewriting the interpreter for long time, but I have never been motivated enough to throw out the current interpreter and start developing new one.

    Then Koichi came in with YARV that seemed to have much brighter future than my vaporware - it runs - so I asked him to take a role of the official implementer of the core. Although I enjoy both designing and implementation of the language, I don't think I am gifted for language implementation. So I thought that it might be the time to focus on designing when I saw YARV.

    ko1:

    Thank you for your interest in YARV and me. BTW, I'm thinking what "YARV" stand for. Because it is not Yet Another. Someone proposed that "YARV ain't RubyVM". If YARV means "YARV ain't RubyVM", what is YARV?

    I'm Koichi Sasada. Koichi is given name, and "ichi" means "one" in Japanese. So I use "ko1" as my nick. I'm an assistant at Department (...snip...) of Tokyo. My research interest is systems software, especially operating system, programming language, parallel systems, and so on. And I'm a member of Nihon Ruby no Kai (Ruby Association in Japan). I plan(ed) some Ruby events like RubyKaigi and am an editor of Rubyist Magazine. I also develop(ed) Nadoka, Rava, Rucheme, and some projects. Say, I'm a developer of YARV: Yet Another RubyVM.

    My role in Ruby's development? To steal VM hacking pleasure from Matz?

    Read more…

  • 16

    FEB
    2007

    The Ruby VM Serial Interview

    I have really enjoyed reading Pat Eyler's Rubinius Serial Interview and Nick Sieger's spun-off JRuby Serial Interview. It's very educational to read what the developers have to say about their projects and ideas.

    The more I read though, the more I wanted the equivalent content for the official Ruby VM. I asked Matz and Koichi if they would be willing to answer questions from me and they agreed to do so. We are now ready to share their responses with the community.

    This will be a serial interview as Pat Eyler calls them. We will deliver regular episodes until I run out of good questions or Matz and Koichi get sick of me bothering them, whichever comes first. I will ask the questions in the interview, but feel free to make suggestions in the comments to this article.

    One last note: we are not promising any kind of schedule for the episodes. Matz and Koichi are heroically providing their answers in English. We want to respect how much work that is and give them all the time they need to do that. Personally, I cannot thank them enough.

    Read more…

  • 12

    DEC
    2006

    news_to_mail.rb

    [Note: You need to know what the Gateway is before reading this article.]

    The second half of the Ruby Gateway runs as a cron job every five minutes and is expected to move all new newsgroup messages from the NNTP host to the Ruby Talk mailing list. The cron invocation is simply:

    ruby /path/to/gateway/bin/news_to_mail.rb /path/to/news_to_mail.log
    

    This side of the Gateway is not piped any messages and exit codes from it are not monitored. It needs to tend its own affairs.

    The Code

    Here's the source:

    GATEWAY_DIR  = File.join(File.dirname(__FILE__), "..").freeze
    DATA_DIR     = File.join(GATEWAY_DIR, "data").freeze
    LAST_ID_FILE = File.join(DATA_DIR, "last_news_id.txt").freeze
    PID_FILE     = File.join(DATA_DIR, "pid.txt").freeze
    
    $LOAD_PATH << File.join(GATEWAY_DIR, "config") << File.join(GATEWAY_DIR, "lib")
    
    # ...
    

    The script begins by locating the root directory of the Gateway source and the data sub directory, building constants for two external files it will interact with, and adjusting the $LOAD_PATH so that it can require needed resources.

    Read more…

  • 5

    DEC
    2006

    mail_to_news.rb

    [Note: You need to know what the Gateway is before reading this article.]

    There are two halves to the Ruby Gateway. One half runs as a qmail filter for an email address on the Ruby Talk mailing list. Every message sent to that address is piped through this filter with a shell script like:

    ruby /path/to/gateway/bin/mail_to_news.rb /path/to/mail_to_news.log
    

    The email is piped to the filter via the standard input and the code is expected to handle the message by posting it to comp.lang.ruby or choosing to ignore it. If the filter exits normally, qmail considers the matter handled. A non-zero exit code will cause the filter to be called with that same message again later.

    The Code

    Let's dive right into the source of this half of the Gateway:

    GATEWAY_DIR = File.join(File.dirname(__FILE__), "..").freeze
    
    $LOAD_PATH << File.join(GATEWAY_DIR, "config") << File.join(GATEWAY_DIR, "lib")
    
    # ...
    

    The code above just sets things up so this script can require some other files in the project normally. Here are those requires:

    Read more…

  • 4

    DEC
    2006

    Hacking the Gateway

    [Update: The Ruby Gateway was retired in June of 2011. Our community simply grew past the point were we needed to combine the various groups, in my opinion.]

    Though I rewrote the current Gateway and I handle the maintenance, it really belongs to the Ruby community. Because of that, I'm going to release the two primary source files on this blog for all to view and critique. This may have value to those who want to know how the Gateway works, those who would like to implement similar technologies, and those who would like to purpose changes to the Gateway code.

    I do welcome purposed changes to the Gateway, but let's set some ground rules for the right way to make suggestions:

    • I will show the important elements of the Gateway code and do my best to explain it as I go. In return, please take the time to read what I write about the code and try to understand how it works. Poorly developed change requests increase my maintenance time with the Gateway, which all comes out of my free time, so please be considerate.
    • You purpose changes to the Gateway by commenting on the code articles. This is intended to be a public discussion with all of us working together. Don't email me or Ruby Talk ideas, I'm monitoring the comments here.
    • Show code in your requests. I don't want to throw the Gateway in a publicly accessible Subversion repository and start taking patches for several reasons. If you want a change, convince me to implement it. The best way to do that is to throw around some code showing me how we would build your request and how it would make the Gateway better.
    • I am thinking about some elements of the Gateway you are not, like the fact that I run this code on a server provided by my work where security is a consideration and the level of maintenance a change will inflict on me. I ask only that you keep this in mind as we debate changes. In return, I will be as open minded to improvements as possible.
    • Gateway changes will not happen overnight. (See note about free time above.) Please be patient.
  • 1

    DEC
    2006

    What is the Ruby Talk Gateway?

    [Update: The Ruby Gateway was retired in June of 2011. Our community simply grew past the point were we needed to combine the various groups, in my opinion.]

    The Ruby community makes use of both email and Usenet communication, in addition to other resources. The primary mailing list is Ruby Talk and the primary Usenet group is comp.lang.ruby. These two services are joined by the Ruby Gateway.

    In 2001 The Pragmatic Programmers wrote the initial version of the Ruby Gateway to ferry messages back and forth between these two resources. Emails sent to Ruby Talk are posted as Usenet messages and Usenet posts are forwarded to Ruby Talk by the Gateway. The Gateway has had a few guardians and code changes since then, but the functionality remains the same.

    I'm am the current caretaker of the Ruby Gateway. Highgroove Studios generously provides hosting for it and I monitor the system for problems. I also wrote the current version of the Gateway.

    You are free to report Gateway problems for me to look into. Before you do though, please read the following notes:

    Read more…

  • 7

    NOV
    2006

    Doing It All!

    I'm not really in the habit of putting non-code content on this blog, but more than one person asked me the same question at RubyConf. If people really want to know, I'll try to answer. Paraphrasing, the question was:

    How do you keep up with so many Ruby projects?

    First, this question surprised me. Do I really do that much? If you just said yes to that, I would like to introduce you to Ryan Davis. He easily doubles my output and his projects are wicked complex compared to mine.

    That doesn't answer the question though.

    In short, I do as much as I possibly can with the time I have. The truth is that I would like to do a lot more. I turn down at least as many damn cool Ruby projects as I accept because I'm a wimp and not willing to give up my sleep. There are so many crazy cool Ruby projects out there that I would love to be a part of. There just aren't enough hours in the day.

    I guess I still didn't answer the question.

    The question was "How…" and the answer to that is actually trivial. Masayoshi Takahashi summed it up with a single slide in his presentation at RubyConf:

    Read more…

    In: Non-code | Tags: Process | 0 Comments
  • 1

    OCT
    2006

    I Just Want One Character!

    Every so often a person asks the question on Ruby Talk, "How can I get just one character from the keyboard (without needing the user to hit return)?" Everyone is always quick to post solutions, but sadly there are some issues with almost every one of them.

    The general consensus is that this is a tough problem to solve correctly. I say that's the exact reason to let HighLine handle this for you:

    #!/usr/bin/env ruby -w
    
    require "highline/system_extensions"
    include HighLine::SystemExtensions
    
    print "Enter one character:  "
    char = get_character
    puts char.chr
    

    That doesn't look too tough, does it?

    What's terrific about this solution is that under-the-hood HighLine will check your platform and libraries and then try to use the solution that makes the most sense for your environment. The code is really pretty robust too, because people a lot smarter than me have been sending in patches for over a year, slowly eliminating all of those tricky edge cases.

    As you can see, I've split this functionality of HighLine into a separate module so you don't even need to load the full HighLine system. This was done just because this is such a real and common problem. This section of HighLine is one pure Ruby file, so feel free to vendor it if the external dependency is an issue.

    Read more…

  • 2

    AUG
    2006

    RegexpChallenge

    Just recently I have been working with two different people to improve their regular expression skills. To help me in this endeavor, I built a trivial little script we have been using in IRb. To get started, you construct a new challenge object and add a couple of challenges:

    >> reg_chal = RegexpChallenge.new
    No challenges.
    => 
    >> reg_chal.challenge("Gray, James", "James", "The names can vary.")
    => nil
    >> reg_chal.challenge("abbbbbbbc bc", 10)
    => nil
    >> reg_chal.challenge( "    \n\t  ", nil,
    ?>                     "We want to test for non-space data." )
    => nil
    >> reg_chal.challenge( "cogs 9, widgets 12, ...", "12",
    ?>                     "The numbers can vary." )
    => nil
    >> reg_chal.challenge( "I'm a simple sentence, with words.",
    ?>                     %w[I'm a simple sentence with words] )
    => nil
    

    You can ask for challenges to see what you would like to solve:

    >> reg_chal.challenges
    Challenge #0:
       Input:  "Gray, James"
      Output:  "James"
        Note:  "The names can vary."
    Challenge #1:
       Input:  "abbbbbbbc bc"
      Output:  10
    Challenge #2:
       Input:  "    \n\t  "
      Output:  nil
        Note:  "We want to test for non-space data."
    Challenge #3:
       Input:  "cogs 9, widgets 12, ..."
      Output:  "12"
        Note:  "The numbers can vary."
    Challenge #4:
       Input:  "I'm a simple sentence, with words."
      Output:  ["I'm", "a", "simple", "sentence", "with", "words"]
    => nil
    

    Read more…

  • 30

    JUL
    2006

    PStore Meets YAML

    I love the PStore standard library. It's a very graceful interface to get some fairly robust serialized mini-database handling in just a few lines. With it you get:

    1. Transactions with commit and rollbacks (automatic on exception).
    2. File locking, shared and exclusive.
    3. Multiprocessing safety.

    PStore does even more, including some file mode checking and MD5 hashing to avoid unneeded writes, but the above are the major selling points for me.

    Now, if I had to level any one complaint at PStore, it would be that because it uses Marshal under the hood it doesn't create files you can easily browse or tweak by hand. (Marshal is a feature, don't get me wrong. It's fast, which is very helpful.) Sometimes though I want PStore protection with the YAML file format.

    I'm embarrassed to admit that I use to use a hack for this:

    require "pstore"
    require "yaml"
    class PStore; Marshal = YAML; end
    

    That just redefines the Marshal constant in a scope that should only alter PStore. The library only uses dump() and load() and those methods work the same with Marshal and YAML.

    Read more…