Created
November 15, 2015 23:44
-
-
Save lbarasti/c35359ea3f8b946c6a5b to your computer and use it in GitHub Desktop.
Implements a stack as an immutable data structure using a functional approach
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module Stack | |
| include Enumerable | |
| class EmptyStack | |
| include Stack | |
| def empty?; true; end | |
| def pop; raise 'Cannot pop empty stack'; end | |
| def peek; raise 'Cannot peek empty stack' end | |
| alias_method :head, :peek | |
| alias_method :tail, :pop | |
| end | |
| class NonEmptyStack | |
| include Stack | |
| attr_reader :head, :tail | |
| def initialize head, tail | |
| @head, @tail = head, tail | |
| end | |
| def empty?; false; end | |
| alias_method :peek, :head | |
| alias_method :pop, :tail | |
| end | |
| def self.empty | |
| @@emptyStack ||= EmptyStack.new | |
| end | |
| def self.new *args | |
| args.reverse.inject(self.empty) { |stack, element| | |
| stack.push(element) | |
| } | |
| end | |
| def push(item) | |
| NonEmptyStack.new(item, self) | |
| end | |
| alias_method :<<, :push | |
| def each &block | |
| block or return enum_for(__method__) | |
| unless self.empty? | |
| block.call self.head | |
| self.tail.each &block | |
| end | |
| self | |
| end | |
| def replace_at index, value | |
| l_reversed, r = (0...index).inject([Stack.empty, self]){|pair, idx| | |
| left, right = pair | |
| [left.push(right.head), right.pop] | |
| } | |
| l_reversed.inject(r.pop.push(value)) {|stack, el| NonEmptyStack.new(el, stack)} | |
| end | |
| end | |
| # Stack.new(1,2,3).replace_at(0,0).replace_at(2,-1).push(5).pop.pop.map.to_a |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment