From: Eric Mahurin Date: 2005-05-20T23:06:24+09:00 Subject: Re: [ANN] cursor-0.5 --- Aleksi wrote: > Eric Mahurin wrote: > > I just released the gem package cursor-0.5 on rubyforge: > > Sounds interesting. > > > The is an initial release that focuses on the functionality > and > > tries to give a robust API (mimics stuff in IO, > Array/String, > > is Enumerable, is Rangable, is Comparable). The derived > > classes are minimally implemented and not very efficient > (and > > some cases terribly inefficient). > > Could you tell a bit more in detail how does your goal differ > from let's > say MetaRuby. > > Not this MetaRuby > > http://www.zenspider.com/Languages/Ruby/MetaRuby.html but > instead this > > but original one > > http://raa.ruby-lang.org/project/metaruby/ > > which source code you can apprently view here > > http://raa.ruby-lang.org/gonzui/markup/metaruby > > and which quite old source balls might be here > > http://artengine.ca/matju/MetaRuby/ > > The concept of Hollowness comes through as similar goal in > yours and > Matju's work. I'm not sure what Hollowness is. What I did is quite different than the above. The above looks to make an abstraction of Array/String I think - basing everything off of a few routines - length, get(i), put(i), etc. If you wanted to compare what I did to an existing Ruby class, it is most like an IO. Just like an IO has current position in a file and reads/writes at that point, a Cursor represents a position into some sequential data structure and read/writes (and inserts/deletes) at that point. Also take a look at the iterator package for reference: http://aeditor.rubyforge.org/iterator/ For the Cursor class, there are only 2 very fundamental operations that the base class can do everything off of - delete an element (before or after) and insert an element (before or after). These 2 methods are protected and the fundamental operations from the user of this class are get and put which can do things like putc, getc, puts, gets, read, write from IO in addtion to other stuff (insertion and deletion). All other methods are based on these get/put methods - random access, length, begin/end, marking/setting a position, etc. A unique feature compared to other external iterators is the way the end/begin of sequence is handled. Instead of the get simply returning nil (would have problems with nil elements) or requiring a has_next? call, get/put can take a block that is executed when the end/begin is found. This block can simply set some eof flag or even give more data to trick it into thinking that you are not at the end/begin. I use this last tricking capability to easily accomplish buffering - when the buffer cursor reaches its end, it reads from the input cursor to get more data. Comparing to the iterator package (like the C++ iterators), this is how you would do a simple iteration of the elements: while iter.has_next? element = iter.current # do something with element iter.next end You can do it the same type of way in Cursor (using eof?, [], and succ!), but here is a better way (one method call instead of 3): continue = true loop do element = cursor.get { continue = nil } break unless continue # do something with element end or if you know valid elements can't be nil you can do it the IO way: while element = cursor.get # do something with element end To give you an idea of what can be done, here are the docs for get (put has a similar range of capabilities): --------- get(length=nil,flags=Next) {|len| ...} Get a single element or a sequence of them. length can be nil (get one element - like IO#getc), a positive number (get a sequence of that many elements - like IO#read), 0 (get all remaining - like IO#read), a negative number (get all but that many), or what data_class says (get a sequence up until it finds a match to length - like IO#gets). The observed bits in flags are Reverse (read before instead of after the cursor), Hold (don�t move the cursor), Ignore (just return true or a count instead of the value), and Delete (delete the element or sequence while retrieving it). If there is anything left, either nil (no code block) or the result from code block is returned. This code block could set some variable(s) to signify it is done or return data from some other source to make it look as though it is not done. When returning more data, it should return it in a String or Array of up to len elements. ----------- Here are the current cursor classes I have: Cursor - base class Cursor::Position - used for marking positions Cursor::Test - minimal override to test base class Cursor::Indexed - make a cursor from a String/Array Cursor::Reversed - reverses direction of a cursor Cursor::Buffer - inexpensive insert/delete Cursor::Buffered - buffers input and/or output cursors Cursor::IO - make a cursor out of an IO Yahoo! Mail Stay connected, organized, and protected. Take the tour: http://tour.mail.yahoo.com/mailtour.html