Lists

Hi!

I want to implement a single/double chained list,
what I've done looks to much complicated (better to do a whole rewrite!)
- so: how would you do that (elegant!)
Where (in which class) to put which methods?
-three classes?? class1: Container for Lists, .new=>List, methods list1+list2, list1==list2
class2: Methods of list (List-Operations), methods: list1.name=...; list1.push el
class3: ListElement +links, methods: Element.new, el1==el2
class2+3 could be in one class, but list.new seems not to be compatible to element.new
(both list.new_element and list.new should be def initialize..., the get a new class-object!!)
classes 1+2 could also be merged into 1 class (class+object-methods)
BUT classes 1,2,3 can't be merged into one class -> whats a nice elegant way to combine that all / how to "classify" it best?

(wanted) RESULT:

list1 = Lists.new(:listA, :double) # Lists: Storage for many lists
# i would prefer: class DList < Lists(type= :double); end; list1 = DList.new(:listA) # how to do that?
list2 = Lists.new(:listB, :double)
list2.details => {type: :double, name: :listB, count: 0 /*Elements*/ }
Lists.count # 2 (Lists)

el1 = list1.new('abc')
el2 = list1.new('def')
el3 = ListA.new('ghi') # metaprogramming... # see below: #{Name}

list1.count # 3 Elements
list1.name # :listA
list1 # ['abc','def','ghi']
list1.map{|el| el } # ['abc','def','ghi']
list1.find('def').previous # 'abc'
list1.delete 'def'
list3 = list(1) + list(2) ## Lists.count+=1, because of list3=... ! ???
list2.destroy # removes Elements and list
Lists.count # 2

thank you!
---- (my try / forget the rest:) ---

class Lists
@@allLists = {}

def initialize(listname) # new list
erg = [] # should be List.new !
@@allLists[listname] = erg
return erg
end

def delete(name)
@@allLists -= @@allList[name]
end

def names
@@allLists.keys
end
def count
@@allLists.count
end

end

class List
def initialize(listname,type=:double) # new list(!)
@name=listname
@erg = [] # for example
@@allLists[listname] << erg
return @erg
end

def type # :no, :single or :double # -chained list (:no=array)
@type
end

def name=newname # Name of List => How can I then use #{Name}.new ?
@name=newname
end
def name
@name
end

def destroy # self
Lists.delete self.name
@erg.map{|el| el.destroy } # free it ??
@erg = nil
self.destroy # free self ??
end

def add_new(obj) # Element!
el = Element.new(obj)
@erg[-1][1][1] = self # set "Pointer" in previous element to this one
if self.type==:double then self[1][0] = @erg[-1] end # set prev ptr
@erg << el # add element to list
end

def push
add_new(obj)
end

def pop

end

def first
@erg[0]
end

def last
@erg[-1]
end

def insert_at
end

def delete_at
end

def next
el.previous # ??? # call next from class Element
end

def previous
el.next # ??? # class Element
end

@list_pos=-1
def each
if @list_pos<@erg.length then
@list_pos+=1
"return" @erg
end
## @erg.each{|el| el ... } # how to return
end

def reset
@list_pos=-1
end

def count # of elements
self.length
end
def remove_element(pos)
@erg[pos].delete # class Element

end

class Element
def initialize(obj) # new element
@erg = [obj,[previousEl,nextEl]]
end
def delete
self=nil # how to destroy the whole instance?
end

def previousEl # of self
@erg[1][0]
end

def nextEl # of self
@erg[1][1]
end

end

Hi!

I want to implement a single/double chained list,
what I've done looks to much complicated (better to do a whole rewrite!)
- so: how would you do that (elegant!)
Where (in which class) to put which methods?
-three classes?? class1: Container for Lists, .new=>List, methods list1+list2, list1==list2
class2: Methods of list (List-Operations), methods: list1.name=...; list1.push el
class3: ListElement +links, methods: Element.new, el1==el2
class2+3 could be in one class, but list.new seems not to be compatible to element.new
(both list.new_element and list.new should be def initialize..., the get a new class-object!!)
classes 1+2 could also be merged into 1 class (class+object-methods)
BUT classes 1,2,3 can't be merged into one class -> whats a nice elegant way to combine that all / how to "classify" it best?

I would start with the idea that a list *is* a container. So, it should be treated similar to an array, hash, etc. since it stores elements. Starting with that idea, I would consider the following items:
* A list can store elements of any class - like a hash or array can
* Of course, internally, a list needs to have a way to maintain the data... in that, "element.new" would be an internal thing - in that sense, I would have that as a separate class. So, the "element" class is a wrapper with links and the main payload
* I would consider bringing in Enumerable into the picture so that you can benefit from what it provides

AppSignal has a write-up on enumerable which shows up on page 1 of Google if you search for 'ruby enumerable' but be warned - it has a Linked List example in the post :slight_smile:

(By the way, I would not create a container for storing ALL lists unless you have a specific reason you need it. I would imagine that someone would put those into a hash, array or build a custom class if they really need it)

Best Regards,
Mohit.
2021-8-15 | 11:17 pm.

···

On 2021-8-15 6:18 pm, Die Optimisten wrote:

I'd probably use 2 classes: List and Node, where List will have an instance
var head accessible as reader(attrr_reader :head). While Node will contain
value/data instance var and the next_node instance var that points to
another Node instance.

···

On Sun, 15 Aug 2021 at 15:48, Die Optimisten <inform@die-optimisten.net> wrote:

Hi!

I want to implement a single/double chained list,
what I've done looks to much complicated (better to do a whole rewrite!)
- so: how would you do that (elegant!)
Where (in which class) to put which methods?
  -three classes?? class1: Container for Lists, .new=>List, methods
list1+list2, list1==list2
                                 class2: Methods of list
(List-Operations), methods: list1.name=...; list1.push el
                                 class3: ListElement +links, methods:
Element.new, el1==el2
             class2+3 could be in one class, but list.new seems not to
be compatible to element.new
                 (both list.new_element and list.new should be def
initialize..., the get a new class-object!!)
             classes 1+2 could also be merged into 1 class
(class+object-methods)
             BUT classes 1,2,3 can't be merged into one class -> whats a
nice elegant way to combine that all / how to "classify" it best?

(wanted) RESULT:

list1 = Lists.new(:listA, :double) # Lists: Storage for many lists
   # i would prefer: class DList < Lists(type= :double); end; list1 =
DList.new(:listA) # how to do that?
list2 = Lists.new(:listB, :double)
list2.details => {type: :double, name: :listB, count: 0 /*Elements*/ }
Lists.count # 2 (Lists)

el1 = list1.new('abc')
el2 = list1.new('def')
el3 = ListA.new('ghi') # metaprogramming... # see below: #{Name}

list1.count # 3 Elements
list1.name # :listA
list1 # ['abc','def','ghi']
list1.map{|el| el } # ['abc','def','ghi']
list1.find('def').previous # 'abc'
list1.delete 'def'
list3 = list(1) + list(2) ## Lists.count+=1, because of list3=... ! ???
list2.destroy # removes Elements and list
Lists.count # 2

thank you!
     ---- (my try / forget the rest:) ---

class Lists
   @@allLists = {}

   def initialize(listname) # new list
         erg = [] # should be List.new !
       @@allLists[listname] = erg
     return erg
   end

   def delete(name)
     @@allLists -= @@allList[name]
   end

   def names
     @@allLists.keys
   end
   def count
     @@allLists.count
   end

end

class List
   def initialize(listname,type=:double) # new list(!)
     @name=listname
     @erg = [] # for example
       @@allLists[listname] << erg
     return @erg
   end

   def type # :no, :single or :double # -chained list (:no=array)
     @type
   end

   def name=newname # Name of List => How can I then use #{Name}.new ?
     @name=newname
   end
   def name
     @name
   end

   def destroy # self
     Lists.delete self.name
     @erg.map{|el| el.destroy } # free it ??
     @erg = nil
     self.destroy # free self ??
   end

   def add_new(obj) # Element!
     el = Element.new(obj)
     @erg[-1][1][1] = self # set "Pointer" in previous element to
this one
     if self.type==:double then self[1][0] = @erg[-1] end # set prev ptr
     @erg << el # add element to list
   end

   def push
      add_new(obj)
   end

   def pop

   end

   def first
     @erg[0]
   end

   def last
     @erg[-1]
   end

   def insert_at
   end

   def delete_at
   end

   def next
     el.previous # ??? # call next from class Element
   end

   def previous
     el.next # ??? # class Element
   end

   @list_pos=-1
   def each
     if @list_pos<@erg.length then
           @list_pos+=1
           "return" @erg
     end
     ## @erg.each{|el| el ... } # how to return
   end

   def reset
     @list_pos=-1
   end

   def count # of elements
     self.length
   end
   def remove_element(pos)
       @erg[pos].delete # class Element

end

class Element
   def initialize(obj) # new element
     @erg = [obj,[previousEl,nextEl]]
   end
   def delete
       self=nil # how to destroy the whole instance?
   end

   def previousEl # of self
     @erg[1][0]
   end

   def nextEl # of self
     @erg[1][1]
   end

end

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<ruby-talk list: member options login page>

--

Please consider the environment before printing this email.

Regards,
Surya

Hey,

List is a relatively primitive data structure by itself. It all comes down to what you wanna use it for.
Generally, I prefer to implement lists as a pair `(value; rest of the list)`. You don't really need
anything else in terms of the data structure itself.

From your code under "(wanted) RESULT:" I can tell that you want to have, basically, a stateful
singleton factory (Lists.new being the factory and `Lists.count` pointing out that it's stateful and
keeps track of its calls).
Also you, seemingly, want to sit on two chairs by making your factory create both normal list and
bi-directional one (:double argument). This seems like an overcomplication; separate them?
Some of the results in the comments don't even make sense to me (e.g. list.destroy doesn't
change Lists.count)

My advice is to try and revise your requirements first. Do you really need all these methods?
If you really do you should try and distribute responsibilities over multiple classes so every one is
simple and predictable in its nature.

My personal code style would probably be a somewhat mix of functional and object-oriented programming:
- `List.new(head, tail)` - head being a value and tail being another list. This is a behaviourless struct.
- `ListOperations::....` - a module with operations over lists like iteration, search, removing.
  All being immutable and returning a new list (where needed).

The above is basically all the basis you need. Now you need to implement the stuff specific for *your* case.
If you need a stateful factory - create one.
If you need a some kind of stateful wrapper over List, you can create one (just a class that contains a list
and performs operations on it).

The most important part - try to distribute responsibilities between small parts and just combine (compose)
them with each other. This way your code will have some sort of tree-like hierarchy and you'll probably
have easier time working with it (because you will be able to navigate it from top to bottom as opposed to
having a one big mess).

I hope it'll give you some ideas. But first of all carefuly think about what you actually want before
designing/coding anything. Work backwards.

P.S. some additional comments:
- technically, you don't need to delete anything in ruby. As soon as there're no references to an object it
  will be deleted, basically. This means that `destroy` is not an object's responsibility. You probably
  got this idea from Rails' ActiveRecord where its instances do all sorts of stuff. But in reality,
  those are just factory/etc methods that could (and, some would argue, should) be in a separate class.
- I believe using class variables (`@@my_var`) is a bad practice. Consider something else. In my experience,
  you never need singletons. And even if you do, it's usually more intuitive to use Java-style singletons
  (MyClass.get_instance, see `Singleton` module from stdlib).
- You mix camel-case and snake-case naming. Not sure if it's intentional but it's certainly not conventional.

···

--------------------------
Dmitry Non
https://nondv.wtf
https://weird-programming.dev

On 15 Aug 2021, at 11:18, Die Optimisten <inform@die-optimisten.net> wrote:

Hi!

I want to implement a single/double chained list,
what I've done looks to much complicated (better to do a whole rewrite!)
- so: how would you do that (elegant!)
Where (in which class) to put which methods?
-three classes?? class1: Container for Lists, .new=>List, methods list1+list2, list1==list2
                                class2: Methods of list (List-Operations), methods: list1.name=...; list1.push el
                                class3: ListElement +links, methods: Element.new, el1==el2
            class2+3 could be in one class, but list.new seems not to be compatible to element.new
                (both list.new_element and list.new should be def initialize..., the get a new class-object!!)
            classes 1+2 could also be merged into 1 class (class+object-methods)
            BUT classes 1,2,3 can't be merged into one class -> whats a nice elegant way to combine that all / how to "classify" it best?

(wanted) RESULT:

list1 = Lists.new(:listA, :double) # Lists: Storage for many lists
  # i would prefer: class DList < Lists(type= :double); end; list1 = DList.new(:listA) # how to do that?
list2 = Lists.new(:listB, :double)
list2.details => {type: :double, name: :listB, count: 0 /*Elements*/ }
Lists.count # 2 (Lists)

el1 = list1.new('abc')
el2 = list1.new('def')
el3 = ListA.new('ghi') # metaprogramming... # see below: #{Name}

list1.count # 3 Elements
list1.name # :listA
list1 # ['abc','def','ghi']
list1.map{|el| el } # ['abc','def','ghi']
list1.find('def').previous # 'abc'
list1.delete 'def'
list3 = list(1) + list(2) ## Lists.count+=1, because of list3=... ! ???
list2.destroy # removes Elements and list
Lists.count # 2

thank you!
    ---- (my try / forget the rest:) ---

class Lists
  @@allLists = {}

  def initialize(listname) # new list
        erg = [] # should be List.new !
      @@allLists[listname] = erg
    return erg
  end

  def delete(name)
    @@allLists -= @@allList[name]
  end

  def names
    @@allLists.keys
  end
  def count
    @@allLists.count
  end

end

class List
  def initialize(listname,type=:double) # new list(!)
    @name=listname
    @erg = [] # for example
      @@allLists[listname] << erg
    return @erg
  end

  def type # :no, :single or :double # -chained list (:no=array)
    @type
  end

  def name=newname # Name of List => How can I then use #{Name}.new ?
    @name=newname
  end
  def name
    @name
  end

  def destroy # self
    Lists.delete self.name
    @erg.map{|el| el.destroy } # free it ??
    @erg = nil
    self.destroy # free self ??
  end

  def add_new(obj) # Element!
    el = Element.new(obj)
    @erg[-1][1][1] = self # set "Pointer" in previous element to this one
    if self.type==:double then self[1][0] = @erg[-1] end # set prev ptr
    @erg << el # add element to list
  end

  def push
     add_new(obj)
  end

  def pop

  end

  def first
    @erg[0]
  end

  def last
    @erg[-1]
  end

  def insert_at
  end

  def delete_at
  end

  def next
    el.previous # ??? # call next from class Element
  end

  def previous
    el.next # ??? # class Element
  end

  @list_pos=-1
  def each
    if @list_pos<@erg.length then
          @list_pos+=1
          "return" @erg
    end
    ## @erg.each{|el| el ... } # how to return
  end

  def reset
    @list_pos=-1
  end

  def count # of elements
    self.length
  end
  def remove_element(pos)
      @erg[pos].delete # class Element

end

class Element
  def initialize(obj) # new element
    @erg = [obj,[previousEl,nextEl]]
  end
  def delete
      self=nil # how to destroy the whole instance?
  end

  def previousEl # of self
    @erg[1][0]
  end

  def nextEl # of self
    @erg[1][1]
  end

end

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<ruby-talk list: member options login page>

Hello,
Thanks for your answers!
It's more about learning (the handling of) Ruby, "lists" is just an example.
Factoring / other good things: Could you give me an illustration,
or - would it be possible to create it in common (in the community)? -
Example of "How to use Ruby the right (best) way"

Yes, count (and other details) are not written down in this example
(focussing on the big/important thinks). -> How to .destroy??
Why is a factory class better than a super-class?
What about the organisation of the classses? (which methods in which
class?; see below),
The aim is to reuse most of the code. so no thing should be done twice
(therefore array/single-/double-linked with one super-class). -- It's not a
So I want the "best possible Ruby-Program"*) for that
*)...1) nice/good 2)short code. 3) innovative [show the features of
Ruby], but easy to understand, 4) low mem/5) cpu - usage [something
foregotten?? ] :slight_smile:
Any ideas ?

thank you
Opti

···

Am 15.08.21 um 23:47 schrieb Dmitriy Non:

Hey,

List is a relatively primitive data structure by itself. It all comes down to what you wanna use it for.
Generally, I prefer to implement lists as a pair `(value; rest of the list)`. You don't really need
anything else in terms of the data structure itself.

From your code under "(wanted) RESULT:" I can tell that you want to have, basically, a stateful
singleton factory (Lists.new being the factory and `Lists.count` pointing out that it's stateful and keeps track of its calls).
Also you, seemingly, want to sit on two chairs by making your factory create both normal list and
bi-directional one (:double argument). This seems like an overcomplication; separate them?
Some of the results in the comments don't even make sense to me (e.g. list.destroy doesn't
change Lists.count)

My advice is to try and revise your requirements first. Do you really need all these methods?
If you really do you should try and distribute responsibilities over multiple classes so every one is
simple and predictable in its nature.

My personal code style would probably be a somewhat mix of functional and object-oriented programming:
- `List.new(head, tail)` - head being a value and tail being another list. This is a behaviourless struct.
- `ListOperations::....` - a module with operations over lists like iteration, search, removing.
   All being immutable and returning a new list (where needed).

The above is basically all the basis you need. Now you need to implement the stuff specific for *your* case.
If you need a stateful factory - create one.
If you need a some kind of stateful wrapper over List, you can create one (just a class that contains a list
and performs operations on it).

The most important part - try to distribute responsibilities between small parts and just combine (compose)
them with each other. This way your code will have some sort of tree-like hierarchy and you'll probably
have easier time working with it (because you will be able to navigate it from top to bottom as opposed to
having a one big mess).

I hope it'll give you some ideas. But first of all carefuly think about what you actually want before
designing/coding anything. Work backwards.

P.S. some additional comments:
- technically, you don't need to delete anything in ruby. As soon as there're no references to an object it
   will be deleted, basically. This means that `destroy` is not an object's responsibility. You probably
   got this idea from Rails' ActiveRecord where its instances do all sorts of stuff. But in reality,
   those are just factory/etc methods that could (and, some would argue, should) be in a separate class.
- I believe using class variables (`@@my_var`) is a bad practice. Consider something else. In my experience,
   you never need singletons. And even if you do, it's usually more intuitive to use Java-style singletons
   (MyClass.get_instance, see `Singleton` module from stdlib).
- You mix camel-case and snake-case naming. Not sure if it's intentional but it's certainly not conventional.

--------------------------
Dmitry Non
https://nondv.wtf
https://weird-programming.dev

On 15 Aug 2021, at 11:18, Die Optimisten <inform@die-optimisten.net> wrote:

Hi!

I want to implement a single/double chained list,
what I've done looks to much complicated (better to do a whole rewrite!)
- so: how would you do that (elegant!)
Where (in which class) to put which methods?
  -three classes?? class1: Container for Lists, .new=>List, methods list1+list2, list1==list2
                                 class2: Methods of list (List-Operations), methods: list1.name=...; list1.push el
                                 class3: ListElement +links, methods: Element.new, el1==el2
             class2+3 could be in one class, but list.new seems not to be compatible to element.new
                 (both list.new_element and list.new should be def initialize..., the get a new class-object!!)
             classes 1+2 could also be merged into 1 class (class+object-methods)
             BUT classes 1,2,3 can't be merged into one class -> whats a nice elegant way to combine that all / how to "classify" it best?

(wanted) RESULT:

list1 = Lists.new(:listA, :double) # Lists: Storage for many lists
   # i would prefer: class DList < Lists(type= :double); end; list1 = DList.new(:listA) # how to do that?
list2 = Lists.new(:listB, :double)
list2.details => {type: :double, name: :listB, count: 0 /*Elements*/ }
Lists.count # 2 (Lists)

el1 = list1.new('abc')
el2 = list1.new('def')
el3 = ListA.new('ghi') # metaprogramming... # see below: #{Name}

list1.count # 3 Elements
list1.name # :listA
list1 # ['abc','def','ghi']
list1.map{|el| el } # ['abc','def','ghi']
list1.find('def').previous # 'abc'
list1.delete 'def'
list3 = list(1) + list(2) ## Lists.count+=1, because of list3=... ! ???
list2.destroy # removes Elements and list
Lists.count # 2

thank you!
     ---- (my try / forget the rest:) ---

class Lists
   @@allLists = {}

   def initialize(listname) # new list
         erg = [] # should be List.new !
       @@allLists[listname] = erg
     return erg
   end

   def delete(name)
     @@allLists -= @@allList[name]
   end

   def names
     @@allLists.keys
   end
   def count
     @@allLists.count
   end

end

class List
   def initialize(listname,type=:double) # new list(!)
     @name=listname
     @erg = [] # for example
       @@allLists[listname] << erg
     return @erg
   end

   def type # :no, :single or :double # -chained list (:no=array)
     @type
   end

   def name=newname # Name of List => How can I then use #{Name}.new ?
     @name=newname
   end
   def name
     @name
   end

   def destroy # self
     Lists.delete self.name
     @erg.map{|el| el.destroy } # free it ??
     @erg = nil
     self.destroy # free self ??
   end

   def add_new(obj) # Element!
     el = Element.new(obj)
     @erg[-1][1][1] = self # set "Pointer" in previous element to this one
     if self.type==:double then self[1][0] = @erg[-1] end # set prev ptr
     @erg << el # add element to list
   end

   def push
      add_new(obj)
   end

   def pop

   end

   def first
     @erg[0]
   end

   def last
     @erg[-1]
   end

   def insert_at
   end

   def delete_at
   end

   def next
     el.previous # ??? # call next from class Element
   end

   def previous
     el.next # ??? # class Element
   end

   @list_pos=-1
   def each
     if @list_pos<@erg.length then
           @list_pos+=1
           "return" @erg
     end
     ## @erg.each{|el| el ... } # how to return
   end

   def reset
     @list_pos=-1
   end

   def count # of elements
     self.length
   end
   def remove_element(pos)
       @erg[pos].delete # class Element

end

class Element
   def initialize(obj) # new element
     @erg = [obj,[previousEl,nextEl]]
   end
   def delete
       self=nil # how to destroy the whole instance?
   end

   def previousEl # of self
     @erg[1][0]
   end

   def nextEl # of self
     @erg[1][1]
   end

end

Maybe - if it makes more sense, we can adapt the request, too!

Opti

For "how to use ruby the right/best way", this is a great book:

martin

···

On Mon, Aug 16, 2021 at 4:40 AM Die Optimisten <inform@die-optimisten.net> wrote:

Hello,
Thanks for your answers!
It's more about learning (the handling of) Ruby, "lists" is just an
example.
Factoring / other good things: Could you give me an illustration,
or - would it be possible to create it in common (in the community)? -
Example of "How to use Ruby the right (best) way"

Yes, count (and other details) are not written down in this example
(focussing on the big/important thinks). -> How to .destroy??
Why is a factory class better than a super-class?
What about the organisation of the classses? (which methods in which
class?; see below),
The aim is to reuse most of the code. so no thing should be done twice
(therefore array/single-/double-linked with one super-class). -- It's not a
So I want the "best possible Ruby-Program"*) for that
     *)...1) nice/good 2)short code. 3) innovative [show the features of
Ruby], but easy to understand, 4) low mem/5) cpu - usage [something
foregotten?? ] :slight_smile:
Any ideas ?

thank you
Opti

Am 15.08.21 um 23:47 schrieb Dmitriy Non:
> Hey,
>
> List is a relatively primitive data structure by itself. It all comes
down to what you wanna use it for.
> Generally, I prefer to implement lists as a pair `(value; rest of the
list)`. You don't really need
> anything else in terms of the data structure itself.
>
> From your code under "(wanted) RESULT:" I can tell that you want to
have, basically, a stateful
> singleton factory (Lists.new being the factory and `Lists.count`
pointing out that it's stateful and keeps track of its calls).
> Also you, seemingly, want to sit on two chairs by making your factory
create both normal list and
> bi-directional one (:double argument). This seems like an
overcomplication; separate them?
> Some of the results in the comments don't even make sense to me (e.g.
list.destroy doesn't
> change Lists.count)
>
> My advice is to try and revise your requirements first. Do you really
need all these methods?
> If you really do you should try and distribute responsibilities over
multiple classes so every one is
> simple and predictable in its nature.
>
> My personal code style would probably be a somewhat mix of functional
and object-oriented programming:
> - `List.new(head, tail)` - head being a value and tail being another
list. This is a behaviourless struct.
> - `ListOperations::....` - a module with operations over lists like
iteration, search, removing.
> All being immutable and returning a new list (where needed).
>
> The above is basically all the basis you need. Now you need to implement
the stuff specific for *your* case.
> If you need a stateful factory - create one.
> If you need a some kind of stateful wrapper over List, you can create
one (just a class that contains a list
> and performs operations on it).
>
> The most important part - try to distribute responsibilities between
small parts and just combine (compose)
> them with each other. This way your code will have some sort of
tree-like hierarchy and you'll probably
> have easier time working with it (because you will be able to navigate
it from top to bottom as opposed to
> having a one big mess).
>
> I hope it'll give you some ideas. But first of all carefuly think about
what you actually want before
> designing/coding anything. Work backwards.
>
> P.S. some additional comments:
> - technically, you don't need to delete anything in ruby. As soon as
there're no references to an object it
> will be deleted, basically. This means that `destroy` is not an
object's responsibility. You probably
> got this idea from Rails' ActiveRecord where its instances do all
sorts of stuff. But in reality,
> those are just factory/etc methods that could (and, some would argue,
should) be in a separate class.
> - I believe using class variables (`@@my_var`) is a bad practice.
Consider something else. In my experience,
> you never need singletons. And even if you do, it's usually more
intuitive to use Java-style singletons
> (MyClass.get_instance, see `Singleton` module from stdlib).
> - You mix camel-case and snake-case naming. Not sure if it's intentional
but it's certainly not conventional.
>
>
> --------------------------
> Dmitry Non
> https://nondv.wtf
> https://weird-programming.dev
>
>> On 15 Aug 2021, at 11:18, Die Optimisten <inform@die-optimisten.net> > wrote:
>>
>> Hi!
>>
>> I want to implement a single/double chained list,
>> what I've done looks to much complicated (better to do a whole rewrite!)
>> - so: how would you do that (elegant!)
>> Where (in which class) to put which methods?
>> -three classes?? class1: Container for Lists, .new=>List, methods
list1+list2, list1==list2
>> class2: Methods of list
(List-Operations), methods: list1.name=...; list1.push el
>> class3: ListElement +links, methods:
Element.new, el1==el2
>> class2+3 could be in one class, but list.new seems not to
be compatible to element.new
>> (both list.new_element and list.new should be def
initialize..., the get a new class-object!!)
>> classes 1+2 could also be merged into 1 class
(class+object-methods)
>> BUT classes 1,2,3 can't be merged into one class -> whats
a nice elegant way to combine that all / how to "classify" it best?
>>
>>
>> (wanted) RESULT:
>>
>> list1 = Lists.new(:listA, :double) # Lists: Storage for many lists
>> # i would prefer: class DList < Lists(type= :double); end; list1 =
DList.new(:listA) # how to do that?
>> list2 = Lists.new(:listB, :double)
>> list2.details => {type: :double, name: :listB, count: 0 /*Elements*/
}
>> Lists.count # 2 (Lists)
>>
>> el1 = list1.new('abc')
>> el2 = list1.new('def')
>> el3 = ListA.new('ghi') # metaprogramming... # see below: #{Name}
>>
>> list1.count # 3 Elements
>> list1.name # :listA
>> list1 # ['abc','def','ghi']
>> list1.map{|el| el } # ['abc','def','ghi']
>> list1.find('def').previous # 'abc'
>> list1.delete 'def'
>> list3 = list(1) + list(2) ## Lists.count+=1, because of list3=... !
???
>> list2.destroy # removes Elements and list
>> Lists.count # 2
>>
>> thank you!
>> ---- (my try / forget the rest:) ---
>>
>> class Lists
>> @@allLists = {}
>>
>> def initialize(listname) # new list
>> erg = [] # should be List.new !
>> @@allLists[listname] = erg
>> return erg
>> end
>>
>> def delete(name)
>> @@allLists -= @@allList[name]
>> end
>>
>> def names
>> @@allLists.keys
>> end
>> def count
>> @@allLists.count
>> end
>>
>> end
>>
>> class List
>> def initialize(listname,type=:double) # new list(!)
>> @name=listname
>> @erg = [] # for example
>> @@allLists[listname] << erg
>> return @erg
>> end
>>
>> def type # :no, :single or :double # -chained list (:no=array)
>> @type
>> end
>>
>> def name=newname # Name of List => How can I then use
#{Name}.new ?
>> @name=newname
>> end
>> def name
>> @name
>> end
>>
>> def destroy # self
>> Lists.delete self.name
>> @erg.map{|el| el.destroy } # free it ??
>> @erg = nil
>> self.destroy # free self ??
>> end
>>
>> def add_new(obj) # Element!
>> el = Element.new(obj)
>> @erg[-1][1][1] = self # set "Pointer" in previous element to
this one
>> if self.type==:double then self[1][0] = @erg[-1] end # set prev
ptr
>> @erg << el # add element to list
>> end
>>
>> def push
>> add_new(obj)
>> end
>>
>> def pop
>>
>> end
>>
>> def first
>> @erg[0]
>> end
>>
>> def last
>> @erg[-1]
>> end
>>
>> def insert_at
>> end
>>
>> def delete_at
>> end
>>
>> def next
>> el.previous # ??? # call next from class Element
>> end
>>
>> def previous
>> el.next # ??? # class Element
>> end
>>
>> @list_pos=-1
>> def each
>> if @list_pos<@erg.length then
>> @list_pos+=1
>> "return" @erg
>> end
>> ## @erg.each{|el| el ... } # how to return
>> end
>>
>> def reset
>> @list_pos=-1
>> end
>>
>> def count # of elements
>> self.length
>> end
>> def remove_element(pos)
>> @erg[pos].delete # class Element
>>
>> end
>>
>> class Element
>> def initialize(obj) # new element
>> @erg = [obj,[previousEl,nextEl]]
>> end
>> def delete
>> self=nil # how to destroy the whole instance?
>> end
>>
>> def previousEl # of self
>> @erg[1][0]
>> end
>>
>> def nextEl # of self
>> @erg[1][1]
>> end
>>
>> end

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<ruby-talk list: member options login page>