class Campa::List

A minimalist implementation of a Linked List.

An instance of it represents a function ivocation in the context of a {Evaler#call} or a {Evaler#eval} call.

The importance of adding the adjective “minimalist” in this description is to give already the idea that this implementation does not come with some algorithms (deleting, for example) since for this also minimal Lisp implementation this won't be necessary.

Constants

EMPTY

Attributes

first[RW]

Public Class Methods

new(*elements) click to toggle source

@param elements [Array<Object>] elements linked on the current {List}

# File lib/campa/list.rb, line 19
def initialize(*elements)
  @first = nil
  @head = nil
  @tail = EMPTY

  with elements
end

Public Instance Methods

==(other) click to toggle source

Stablishes equality by comparing each element in the {List}.

@param other [List] to be compared @return [Boolean] true if of both {List} have equal (#==) elements

# File lib/campa/list.rb, line 78
def ==(other)
  return false if !other.is_a?(List)

  node = first
  other_node = other.first

  loop do
    # If both node and other_node are nil
    # we managed to walk the whole list.
    # Since there was no early return (with false)
    # this means all nodes are equal.
    return node.nil? if other_node.nil?
    return false if node != other_node

    node = node.next_node
    other_node = other_node.next_node
  end
end
each(&block) click to toggle source

Yields each element starting from head.

# File lib/campa/list.rb, line 66
def each(&block)
  return if self == EMPTY

  block.call(head)
  tail.each(&block) if tail != EMPTY
end
head() click to toggle source

First element of the current {List}.

Return nil if the current list is {EMPTY}.

@return [Object, nil]

# File lib/campa/list.rb, line 46
def head
  return nil if self == EMPTY

  first.value
end
inspect() click to toggle source

Uses {Printer} to represent the current {List} in a human readable form.

@example

List.new(1, 2, 3).inspect #=> "(1 2 3)"
# File lib/campa/list.rb, line 102
def inspect
  @printer ||= Printer.new
  @printer.call(self)
end
push(element) click to toggle source

Creates a new {List} with the parameter passed in front of it.

@example

List.new(2, 3).push(1) #=> List.new(1, 2, 3)

@param element [Object] any thing to be pushed into the {List} @return [List] new {List} with new element in front of it

# File lib/campa/list.rb, line 35
def push(element)
  self.class.new.tap do |l|
    l.first = Node.new(value: element, next_node: first)
  end
end
tail() click to toggle source

Creates a new list with all elements of the current one BUT the head.

@example

List.new(1, 2, 3).tail #=> List.new(2, 3)

@return [List] with the “rest” of the elements on this {List}

# File lib/campa/list.rb, line 59
def tail
  return EMPTY if first.nil? || first.next_node.nil?

  self.class.new.tap { |l| l.first = @first.next_node }
end

Private Instance Methods

with(elements) click to toggle source
# File lib/campa/list.rb, line 113
def with(elements)
  return if elements.empty?

  elements.reduce(nil) do |previous, current|
    new_node = Node.new(value: current)
    if previous.nil?
      self.first = new_node
    else
      previous.next_node = new_node
    end
  end
end