[#321574] Regular Expressions — Mmcolli00 Mom <mmc_collins@...>

Hi everyone.

15 messages 2008/12/01

[#321655] Ruby cgi script — ZippySwish <fischer.jan@...>

I put "script.rb" into the cgi-bin folder of my webhost, but nothing's

12 messages 2008/12/02

[#321733] FFI 0.2.0 — "Wayne Meissner" <wmeissner@...>

Greetings Rubyists.

20 messages 2008/12/03

[#321920] Force a program to stop if runtime exceeds given duration — Aldric Giacomoni <"aldric[remove]"@...>

Any idea how to do that?

25 messages 2008/12/04
[#321924] Re: Force a program to stop if runtime exceeds given duration — "Glen Holcomb" <damnbigman@...> 2008/12/04

On Thu, Dec 4, 2008 at 10:04 AM, Aldric Giacomoni <"aldric[remove]"@

[#322011] Re: Force a program to stop if runtime exceeds given duration — Ron Fox <fox@...> 2008/12/05

See http://www.ruby-doc.org/core-1.9/classes/Process.html#M003012

[#322016] Re: Force a program to stop if runtime exceeds given duration — Aldric Giacomoni <"aldric[remove]"@...> 2008/12/05

Everybody automatically assumes that rubyists are using Linux - sadly,

[#321969] Are there any Ruby Technical Writers here? — Vito Fontaine <vito.matro@...>

I am a beginner with Ruby who was interested in writing some programs.

15 messages 2008/12/04
[#321975] Re: Are there any Ruby Technical Writers here? — Robert Klemme <shortcutter@...> 2008/12/04

On 04.12.2008 22:43, Vito Fontaine wrote:

[#321984] Re: Are there any Ruby Technical Writers here? — Vito Fontaine <vito.matro@...> 2008/12/05

Robert Klemme wrote:

[#322014] Proximity searches in Ruby — Stuart Clarke <stuart.clarke1986@...>

Does Ruby have the ability to perform proximity searches on data. For

14 messages 2008/12/05
[#322056] Re: Proximity searches in Ruby — Ilan Berci <coder68@...> 2008/12/05

No proximity searches with 1.8.. you would need a full fledged text

[#322073] shoes 2 (raisins) is go. — _why <why@...>

Salutations and hi.

13 messages 2008/12/06

[#322260] Help on algorythm — Helder Oliveira <hrpoliveira@...>

Guys i have been trying to make this algorythm but with no sucess, can

13 messages 2008/12/09
[#322261] Re: Help on algorythm — "Glen Holcomb" <damnbigman@...> 2008/12/09

On Tue, Dec 9, 2008 at 7:44 AM, Helder Oliveira <hrpoliveira@gmail.com>wrote:

[#322283] Completely new programmer lacks direction — Cameron Carroll <ubernoobs@...>

Hi. I recently picked up a beginning ruby book, having only lightly

17 messages 2008/12/09

[#322285] compare 2 text files - check for difference - Please help — Mmcolli00 Mom <mmc_collins@...>

Hi. I want to take two files that are supposed to be identical, then ook

12 messages 2008/12/09
[#322301] Re: compare 2 text files - check for difference - Please help — Brian Candler <b.candler@...> 2008/12/09

Mmcolli00 Mom wrote:

[#322306] Re: compare 2 text files - check for difference - Please help — Mmcolli00 Mom <mmc_collins@...> 2008/12/09

require 'diff/lcs/Array'

[#322417] why Hash corrupts 'key' object ? — Dmitry Perfilyev <dmitry1976@...>

Hi, I have next script:

13 messages 2008/12/10

[#322464] Q: FFI and C++? — Jeremy Henty <onepoint@...>

If I want to wrap a C++ library using FFI, can it cope with the name

14 messages 2008/12/11

[#322516] Invoking Ruby code from a low-level language? — Alex Fulton <a.fulton@...>

Hi, my sincerest apologies if this question has already been answered

11 messages 2008/12/11

[#322529] parallel method return value — Louis-Philippe <default@...>

Hi all,

17 messages 2008/12/12

[#322566] How to run background processes (more than 1 worker) parallely. — "Deepak Gole" <deepak.gole8@...>

Hi

10 messages 2008/12/12

[#322624] singleton methods vs. meta instance methods — Daniel DeLorme <dan-ml@...42.com>

If I understand the ruby object model correctly, then an object's

15 messages 2008/12/13

[#322705] ruby 1.9.1: Encoding trouble: broken US-ASCII String — Tom Link <micathom@...>

Hi,

22 messages 2008/12/14

[#322710] Help with an "easy" regular expression substitution — Iñaki Baz Castillo <ibc@...>

Hi, I'm getting crazy to get a theorically easy substitution:

16 messages 2008/12/14

[#322819] Pure Ruby Zlib::GzipWriter — Daniel Berger <djberg96@...>

Hi,

53 messages 2008/12/15
[#323877] Re: Pure Ruby Zlib::GzipWriter — Daniel Berger <djberg96@...> 2009/01/03

[#323903] Re: Pure Ruby Zlib::GzipWriter — Roger Pack <rogerpack2005@...> 2009/01/04

[#324011] Re: Pure Ruby Zlib::GzipWriter — Daniel Berger <djberg96@...> 2009/01/05

[#324442] Re: Pure Ruby Zlib::GzipWriter — Luis Lavena <luislavena@...> 2009/01/10

On Jan 9, 9:26=A0pm, "Charles L." <aquas...@gmail.com> wrote:

[#322987] Using ruby hash on array — Stuart Clarke <stuart.clarke1986@...>

I would like to process some data from an array and using hash to

14 messages 2008/12/17

[#323085] Ruby and Rails supported on 10gen — "Jim Menard" <jim.menard@...>

http://www.10gen.com/blog/2008/12/ruby-support-on-10gen

11 messages 2008/12/18

[#323166] Dreaming of a Ruby Christmas (#187) — Matthew Moss <matt@...>

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

11 messages 2008/12/19

[#323204] get first and last line from txt file - how? — Mmcolli00 Mom <mmc_collins@...>

I have txt file with date/time stamps only. I want to grab the first

19 messages 2008/12/20
[#323205] Re: get first and last line from txt file - how? — Tim Hunter <TimHunter@...> 2008/12/20

Mmcolli00 Mom wrote:

[#323207] Re: get first and last line from txt file - how? — "Yaser Sulaiman" <yaserbuntu@...> 2008/12/20

I'm just wondering..

[#323273] how to make installing Ruby easier for amateurs — Tom Cloyd <tomcloyd@...>

Greetings!

21 messages 2008/12/22

[#323312] Name that data structure! — Simon Chiang <simon.a.chiang@...>

I'm using a data structure that I'm sure has been implemented and

18 messages 2008/12/22
[#323314] Re: Name that data structure! — "Gregory Brown" <gregory.t.brown@...> 2008/12/22

On Mon, Dec 22, 2008 at 5:38 PM, Simon Chiang <simon.a.chiang@gmail.com> wrote:

[#323342] Are all Ruby built-in objects thread safe? — "Just Another Victim of the Ambient Morality" <ihatespam@...>

Are all built-in objects thread safe? For example, if I have an array

23 messages 2008/12/23
[#323346] Re: Are all Ruby built-in objects thread safe? — Yukihiro Matsumoto <matz@...> 2008/12/23

Hi,

[#323519] What does 'Monkey Patching' exactly Mean in Ruby? — "Yaser Sulaiman" <yaserbuntu@...>

According to Wikipedia, a monkey patch[1] is:

36 messages 2008/12/27
[#323813] Re: What does 'Monkey Patching' exactly Mean in Ruby? — Jg W Mittag <JoergWMittag+Usenet@...> 2009/01/02

Phlip wrote:

[#323832] Re: What does 'Monkey Patching' exactly Mean in Ruby? — "David A. Black" <dblack@...> 2009/01/02

Hi --

[#323644] Why Ruby? — Mike Stephens <rubfor@...>

I have never seen or heard of Ruby in a corporate context. The single

35 messages 2008/12/30

[#323668] Ruby 1.9.1 RC1 is released — "Yugui (Yuki Sonoda)" <yugui@...>

Hi, folks

21 messages 2008/12/30

[SUMMARY] Befunge (#184)

From: Matthew Moss <matt@...>
Date: 2008-12-04 22:25:03 UTC
List: ruby-talk #321973
Writing a Befunge interpreter isn't terribly difficult. Some things  
need to be handled with care -- stack underflow and program counter  
wraparound, for example -- but overall Befunge is a pretty  
straightforward, stack-based language. That the program counter can  
move in two dimensions isn't really cumbersome in itself. The  
interpreter still executes code sequentially; code just "bends" about  
to suit the user's whim. I suspect most any Befunge program could be  
written in a single line, though it's certainly more convenient to  
have a 2D space.

I'm not going to do a long summary of any one of the interpreters.  
Most of the code I saw was easy to understand. For younger Rubyists,  
check out my solution (i.e. the first solution by Matthew Moss) for a  
plain, simple, no-frills approach. There is very little in my code  
that is spectacularly Ruby specific. (Also excuse a few bugs in my  
code; some, but not all, were discussed on the mailing list, but I  
never got around to revising my submission.)

For a summary, I will compare a few pieces of different solutions,  
just to show the various techniques used while writing these  
interpreters. Befunge isn't so fancy that it needs a fancy solution,  
but of course these techniques are certainly applicable to more  
complex systems.

First, a brief look at the stack. There really isn't much needed here,  
since Ruby's `Array` provides `push` and `pop` methods, and so can act  
as a stack with no extra code. However, one minor detail of Befunge is  
that if you pop an empty stack, it should return zero. Several  
submissions did this with a custom version of pop:

     def pop
       @stack.pop || 0
     end

If `@stack` is an empty array, `pop` returns `nil`. As `nil` evaluates  
to false in a boolean context, the logical-or operator `||` will then  
evaluate the right side, returning zero. If `pop` returned an actual  
value, the logical-or operator would short-circuit, skipping the right  
side. It works very similar to another submissions version of pop:

     def pop
       x = @stack.pop
       x.nil? ? 0 : x
     end

This is more explicit in intent, and perhaps clearer for those  
unfamiliar with `||`.

Let's look next at some implementations of the program counter. One  
implementation looked like this (code stripped down to relevant  
portions):

     PC = Struct.new(:row, :col, :direction)
     @pc = PC.new(0, 0, :right)

	def current_cell
	  @program[@pc.row][@pc.col]
	end
	
     def tick_pc
       case @pc.direction
       when :right
         if @pc.col == @program[@pc.row].size - 1
           @pc.col = 0
         else
           @pc.col += 1
         end
       # other direction cases here... implemented similarly
       end
     end

I like the use of Struct here to easily create a class (`PC`) with  
well-named members `row` and `col`. These seem more appropriate than  
`x` and `y`, since the typical access pattern into a 2D array (often  
as pulled from the file) will be row-first, then column. As you can  
see in `current_cell` here, the names make it very clear.  
`@program[@pc.y][@pc.x]` would also be correct, but the order of x and  
y is reversed from what might be expected, and so could be a source of  
bugs if the coder does not pay careful attention to this detail.

While I like the struct and cell access here, updating the program  
counter is a little cumbersome; it's not wrong, but it is a lot of  
code for what should be a simple operation: modular addition. Here is  
a version that's much more compact:

     def step
     	case @direction
     	when :right:	@PC_x += 1
     	when :left:		@PC_x -= 1
     	when :down:		@PC_y += 1
     	when :up:		@PC_y -= 1
     	end
     	@PC_x %= 80
     	@PC_y %= 25
     end

There is excess work being done: if `@PC_x` is updated, for example,  
we don't *need* to modulate `@PC_y`. However, the cost of this is  
likely to be rather low. The alternative is simply to move the modulo  
operations up into each case: minor code duplication for minor  
performance gains. Personally, I'd leave it as it is.

One note on the modulo operator. My own solution modified the program  
counter as such:

     @pc[0] = (@pc[0] - 1 + @hgt) % @hgt

Adding in `@hgt` before taking the modulo by `@hgt` was insurance that  
I would get an expected value, not knowing ahead of time whether the  
modulus of a negative number (as could happen if I simply subtracted 1  
from the pc) would be positive or negative. As it turns out, Ruby  
keeps the result positive if the second argument of the modulus  
operator is positive, so my insurance here was unnecessary.

Finally, let's take a look at "method" dispatch. As the program  
counter moves through the Befunge source code, each character  
represents an operation to be performed. The naive (umm... old-skool)  
implementation is a big case statement:

     when ?0..?9
        push (curr - ?0)
      when ?+, ?-, ?*, ?/, ?%
        b, a = pop, pop
        push a.send(curr.to_sym, b)
      when ?!
        push (pop.zero? ? 1 : 0)
      when ?,
	   print pop.chr
      when ?>
        @dir = :east
      # ...

Not very Rubyish. Let's look at something cooler. A number of  
solutions used a "code block" technique, creating a hash of code  
blocks, the various Befunge symbols as keys into that hash. Here's a  
portion of one submission:

     module Befunge
       Commands = {
         "0" => lambda { @stack.push(0) },
         "1" => lambda { @stack.push(1) },
         "2" => lambda { @stack.push(2) },
         # ...
         "*" => lambda { @stack.push(@stack.pop * @stack.pop) },
         "/" => lambda { val2, val1 = @stack.pop, @stack.pop;  
@stack.push(val1 / val2) },
         "%" => lambda { val2, val1 = @stack.pop, @stack.pop;  
@stack.push(val1 % val2) },
         # ...
         ">" => lambda { @pc.direction = :right },
         "<" => lambda { @pc.direction = :left },
         # ...
       }
     end

Executing the appropriate lambda block is done like so:

     def process_cell
       cell = current_cell
       raise "Unknown command: #{cell} at (#{@pc.col}, #{@pc.row})"  
if !Commands.include? cell
       instance_eval(&Commands[cell])
       cell
     end

`cell` is looked up in the `Commands` hash and passed to  
`instance_eval`. This executes the code block in the context of the  
interpreter (i.e. the object of `process_cell`). This ensures that the  
interpreter's `@stack` and `@pc`, etc. are available for access by  
these code blocks.

One last technique for handling these various commands is the "define  
method" technique: each Befunge symbol becomes a method of the  
interpreter. Here is a portion of that submission:

     class Befunge93
       instance_methods.each { |m| undef_method m unless (m =~ /^__| 
send/) }

	  (0..9).each do |d|
	    define_method :"#{d}" do
	      push d
	    end
	  end

	  %w{ + - * / % }.each do |o|
	    define_method :"#{o}" do
	      a, b = pop, pop
	      push b.send(:"#{o}", a)
	    end
	  end

	  # etc...

   	  def run
	    loop do
	      send @memory[@position]
	      move
	    end
	  end
	end
	
First, notice that we have code right in the class definition, outside  
of any method. If you're new to Ruby, this may look rather strange,  
but this code executes when the class is defined. Quite a handy thing:  
code that executes once at definition let's you do some very meta-ish  
things.

Here, we start with the interesting line at the top enumerating over  
all the class' instance methods. Most methods (except for `send` and a  
few special methods) are undefined; this gives us a "clean" object  
free of any methods that would interfere with the Befunge methods.

Next, `define_method` is called for all the Befunge symbols. (Only  
some shown here.) Inside `define_method` is the code for that  
particular Befunge symbols. Since we are defining instance methods on  
the interpreter itself, these bits of code can access other instance  
methods (such as `pop`). This sort of technique is very convenient for  
the digits and the arithmetic operators shown above, as their  
implementation is nearly identical. The direction changing commands  
are handled in a similar way, though the rest of the commands must be  
done individually (at which point, the hash of lambdas is more compact).

Finally, note how these defined methods are executed in `run`: via the  
`send` method, one of the few that was allowed to remain. The Befunge  
symbol is accessed via `@memory[@position]` and sent to the interpreter.


Thanks for all the submissions! I intentionally wrote a simple, case- 
based interpreter in the hopes that others would provide some more  
Ruby-ish solutions, and we got 'em. Now I'm off to write a Ruby  
interpreter in Befunge...


In This Thread

Prev Next