From: David Vallner Date: 2006-10-23T08:10:53+09:00 Subject: Re: Ruby-ize me (or at least my code) --------------enigD87474276364386358C88070 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Seth Eliot wrote: > Hi all, >=20 > I am new to Ruby but find it interesting. To teach myself the language= =20 > I wrote a simple linked list implementation. It works just fine, but I= =20 > suspect that my "Java is showing" and that the same logic can be writte= n=20 > in a much more Ruby-ish fashion. >=20 > So I'd appreciate it if you can show me the Ruby way of implementing th= e=20 > following functionality. >=20 > (The one thing I know is that I am not really taking advantage of OOP b= y=20 > making my methods in LinkedListSe.rb just static utility methods=E2=80=A6= that's=20 > fine for now) > (also "next_1" is just my way of not colliding with the reserved keywor= d=20 > "next") >=20 > File: ElemLL.rb >=20 > class ElemLL >=20 > attr_accessor :data, :next_1 >=20 The following two lines don't in fact do anything and can be safely delet= ed. > @data > @next_1 > End >=20 The following should be methods of ElemLL. (There's not *much* Java showing, is there?) > File: LinkedListSe.rb >=20 > require 'ElemLL' >=20 > # Adds element to end of linked list > def addData(data, head=3Dnil) > insertData(data, head) > end >=20 > # Inserts Element at requested index in linked list. > # Shifts the element currently at that position (if any) and any=20 > subsequent > # elements to the right (adds one to their indices) > def insertData(data, head, index=3Dnil) >=20 > # special case if list currently empty (not initialized) > return newList(data) unless head >=20 If you're doing type-checking, raise an exception. This is a potential Mysterious Bug. ("Nothing seem to be broke, it just doesn't work!") > # Weakly typed languages have their downsides? :-) > return unless head.class =3D=3D ElemLL >=20 > # Initial values for first element > i =3D 1 > prev =3D nil > curr =3D head > next_1 =3D curr.next_1 >=20 > # Iterate through elements until we reach insertion point (or end o= f=20 > list) > while (curr && (!index || i prev=3Dcurr > curr =3D next_1; > next_1 =3D curr.next_1 if curr; > i=3Di.next > end >=20 > # when new element is inserted, the current curr will actually be=20 > next > next_1 =3D curr >=20 > # Create the new element at curr > curr =3D ElemLL.new > curr.data =3D data > curr.next_1=3Dnext_1 >=20 > # Set the pointer *to* the new element > if (prev) > prev.next_1 =3D curr > else > head=3Dcurr > end >=20 > return head > end >=20 The following should be an implementation of #each: > def traverse(head) Axe following line. > puts "\nLinked List contents:" >=20 > curr =3D head > while(curr) Replace with "yield curr.data". For greater pleasure, have ElemLL "include Enumerable". > puts " #{curr.data}" > curr =3D curr.next_1 > end > end >=20 The Ruby equivalent of a constructor is the "special" (i.e. not really) method initialize. > def newList(data) > head =3D ElemLL.new > head.data =3D data > return head > end >=20 Also, I personally prefer(red) opaque linked lists (in the school assignments where I actually implemented those.) - ones where you don't rely on having to supply the head node of a list to functions manipulating it, but a structure encapsulating the list. Same here, I'd avoid leaking the internal structure of the list. David Vallner --------------enigD87474276364386358C88070 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (MingW32) iD8DBQFFO/qIy6MhrS8astoRAv8PAJ9Lz9ezcDDE+l/NsnTDSRMnOuE2EgCffA7U ZyaGQPdWuI/dtXjOL4+UM6M= =luo3 -----END PGP SIGNATURE----- --------------enigD87474276364386358C88070--