frypan 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/README.md +33 -0
- data/Rakefile +2 -0
- data/frypan.gemspec +3 -4
- data/lib/frypan.rb +191 -52
- data/lib/frypan/version.rb +1 -1
- data/tutorial/my_at.rb +17 -0
- data/tutorial/my_atd.rb +85 -0
- data/tutorial/sample_tcp_client.rb +8 -0
- data/tutorial/sample_tcp_server.rb +13 -0
- data/tutorial/tutorial.md +359 -0
- data/unit_test/test_frypan.rb +66 -0
- metadata +14 -14
- data/_README.md +0 -31
- data/bin/frypan +0 -55
- data/lib/frypan/database_sync_list.rb +0 -30
- data/lib/frypan/epg_parser.rb +0 -23
- data/lib/frypan/node.rb +0 -150
- data/lib/frypan/tuner.rb +0 -47
- data/unit_test/test_node.rb +0 -171
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 041c764b352e067de7265cb532797f1b3b5d5b7a
         | 
| 4 | 
            +
              data.tar.gz: d0f5212808ffb5d2eb2b6d7ea6d863c61c238e0d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 9e66378e9eb9f02eec905f668abe9da03271f13d09a6899c0ff6a8b039775dd39498d089f994bb2450bec754b85f56ce828d8e6f1e43d381b88cb11065c7b2e6
         | 
| 7 | 
            +
              data.tar.gz: 7b1df425490c8575c91498ae9da32fe7d03232b6a7c915d669020431619bc4173140a88cd4514f131d28ab25602bdc46c618cff2e50e3fb556f4cbcf78d3d3d4
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            # Frypan
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Very small and simple library to do Functional Reactive Programming in Ruby in a similar way to Elm.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## Installation
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Add this line to your application's Gemfile:
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ```ruby
         | 
| 10 | 
            +
            gem 'frypan'
         | 
| 11 | 
            +
            ```
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            And then execute:
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                $ bundle
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            Or install it yourself as:
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                $ gem install frypan
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            ## Short Tutorial
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            To experience FRP and understand how to use this library, we make an imitation of Linux's atd(8) and at(1).
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            [Click here to jump to Short Tutorial page.](https://github.com/sawaken/frypan/blob/master/tutorial/tutorial.md "Frypan - Short Tutorial")
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            ## Contributing
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            1. Fork it ( https://github.com/sawaken/frypan/fork )
         | 
| 30 | 
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         | 
| 31 | 
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         | 
| 32 | 
            +
            4. Push to the branch (`git push origin my-new-feature`)
         | 
| 33 | 
            +
            5. Create a new Pull Request
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/frypan.gemspec
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            #-*- mode:ruby -*-
         | 
| 2 2 | 
             
            # coding: utf-8
         | 
| 3 3 | 
             
            lib = File.expand_path('../lib', __FILE__)
         | 
| 4 4 | 
             
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| @@ -9,9 +9,8 @@ Gem::Specification.new do |spec| | |
| 9 9 | 
             
              spec.version       = Frypan::VERSION
         | 
| 10 10 | 
             
              spec.authors       = ["sawaken"]
         | 
| 11 11 | 
             
              spec.email         = ["sasasawada@gmail.com"]
         | 
| 12 | 
            -
              spec.summary       = %q{ | 
| 13 | 
            -
              spec. | 
| 14 | 
            -
              spec.homepage      = ""
         | 
| 12 | 
            +
              spec.summary       = %q{Very small and simple library to do Functional Reactive Programming in Ruby in a similar way to Elm.}
         | 
| 13 | 
            +
              spec.homepage      = "https://github.com/sawaken/tiny_frp2"
         | 
| 15 14 | 
             
              spec.license       = "MIT"
         | 
| 16 15 |  | 
| 17 16 | 
             
              spec.files         = `git ls-files -z`.split("\x0")
         | 
    
        data/lib/frypan.rb
    CHANGED
    
    | @@ -1,57 +1,196 @@ | |
| 1 1 | 
             
            require "frypan/version"
         | 
| 2 2 |  | 
| 3 3 | 
             
            module Frypan
         | 
| 4 | 
            -
             | 
| 5 | 
            -
              # | 
| 6 | 
            -
              # | 
| 7 | 
            -
             | 
| 8 | 
            -
               | 
| 9 | 
            -
                 | 
| 10 | 
            -
             | 
| 11 | 
            -
                 | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
                 | 
| 15 | 
            -
             | 
| 16 | 
            -
                 | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
                 | 
| 24 | 
            -
                 | 
| 25 | 
            -
                 | 
| 26 | 
            -
             | 
| 27 | 
            -
                 | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                 | 
| 36 | 
            -
                 | 
| 37 | 
            -
             | 
| 38 | 
            -
                 | 
| 39 | 
            -
             | 
| 40 | 
            -
                 | 
| 41 | 
            -
             | 
| 42 | 
            -
                 | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
                 | 
| 47 | 
            -
             | 
| 48 | 
            -
                 | 
| 49 | 
            -
             | 
| 50 | 
            -
                 | 
| 51 | 
            -
             | 
| 52 | 
            -
                 | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 4 | 
            +
             | 
| 5 | 
            +
              # Reactor : Object to calculate (Signal -> Value)
         | 
| 6 | 
            +
              # ----------------------------------------
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              class Reactor
         | 
| 9 | 
            +
                include Enumerable
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def initialize(signal, init_memos=[{}, {}])
         | 
| 12 | 
            +
                  @signal = signal
         | 
| 13 | 
            +
                  @init_memos = init_memos
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def loop(&block)
         | 
| 17 | 
            +
                  memos = @init_memos
         | 
| 18 | 
            +
                  while true
         | 
| 19 | 
            +
                    last_memo = @signal.__pull({}, *memos)
         | 
| 20 | 
            +
                    memos = [last_memo, memos[0]]
         | 
| 21 | 
            +
                    block.call(last_memo[@signal])
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                
         | 
| 25 | 
            +
                def each(&block)
         | 
| 26 | 
            +
                  loop(&block)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              # Signal : Abstraction of time-varing value
         | 
| 31 | 
            +
              # ----------------------------------------
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              class Signal
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                # Utility Class methods (public to library-user)
         | 
| 36 | 
            +
                # ----------------------------------------
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def self.const(val)
         | 
| 39 | 
            +
                  Const.new(val)
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def self.input(&proc)
         | 
| 43 | 
            +
                  Input.new(&proc)
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def self.async_input(buf_size=1, &proc)
         | 
| 47 | 
            +
                  InputThread.new(buf_size, &proc)[0]
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def self.lift(*arg_signals, &proc)
         | 
| 51 | 
            +
                  Lift.new(*arg_signals, &proc)
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def self.foldp(init_state, *arg_signals, &proc)
         | 
| 55 | 
            +
                  Foldp.new(init_state, *arg_signals, &proc)
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                # Utility Instance methods (public to library-user)
         | 
| 59 | 
            +
                # ----------------------------------------
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                def method_missing(name, *args, &proc)
         | 
| 62 | 
            +
                  Lift.new(self){|a| a.send(name, *args, &proc)}
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def lift(&proc)
         | 
| 66 | 
            +
                  Lift.new(self, &proc)
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                def foldp(init_state, &proc)
         | 
| 70 | 
            +
                  Foldp.new(init_state, self, &proc)
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                # Implementation of each Signals (library-user need not understand)
         | 
| 74 | 
            +
                # ----------------------------------------
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def __pull(memo0, memo1, memo2)
         | 
| 77 | 
            +
                  if memo0.has_key?(self)
         | 
| 78 | 
            +
                    memo0
         | 
| 79 | 
            +
                  else
         | 
| 80 | 
            +
                    __calc(__pull_deps(memo0, memo1, memo2), memo1, memo2)
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                def __pull_deps(memo0, memo1, memo2)
         | 
| 85 | 
            +
                  memo0
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                def __same(memo_a, memo_b)
         | 
| 89 | 
            +
                  memo_a.has_key?(self) && memo_b.has_key?(self) && memo_a[self] == memo_b[self]
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                class Const < Signal
         | 
| 93 | 
            +
                  def initialize(val)
         | 
| 94 | 
            +
                    @val = val
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  def __calc(memo0, memo1, memo2)
         | 
| 98 | 
            +
                    memo0.merge(self => @val)
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                class Input < Signal
         | 
| 103 | 
            +
                  def initialize(&proc)
         | 
| 104 | 
            +
                    @input_proc = proc
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  def __calc(memo0, memo1, memo2)
         | 
| 108 | 
            +
                    memo0.merge(self => @input_proc.call)
         | 
| 109 | 
            +
                  end
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                class InputThread < Signal
         | 
| 113 | 
            +
                  def initialize(buf_size=1, &proc)
         | 
| 114 | 
            +
                    @buf_size = buf_size
         | 
| 115 | 
            +
                    @proc = proc
         | 
| 116 | 
            +
                  end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                  def atom(thread, &block)
         | 
| 119 | 
            +
                    thread[:mutex].synchronize(&block)
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                  def make_thread
         | 
| 123 | 
            +
                    thread = ::Thread.new(@proc) do |proc| 
         | 
| 124 | 
            +
                      sleep
         | 
| 125 | 
            +
                      while true
         | 
| 126 | 
            +
                        input = proc.call
         | 
| 127 | 
            +
                        size = atom(Thread.current){
         | 
| 128 | 
            +
                          Thread.current[:inputs] << input
         | 
| 129 | 
            +
                          Thread.current[:inputs].size
         | 
| 130 | 
            +
                        }
         | 
| 131 | 
            +
                        sleep if size >= @buf_size
         | 
| 132 | 
            +
                      end
         | 
| 133 | 
            +
                    end
         | 
| 134 | 
            +
                    thread[:mutex] = Mutex.new
         | 
| 135 | 
            +
                    thread[:inputs] = []
         | 
| 136 | 
            +
                    thread.run
         | 
| 137 | 
            +
                    return thread
         | 
| 138 | 
            +
                  end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                  def get_inputs(thread)
         | 
| 141 | 
            +
                    atom(thread){
         | 
| 142 | 
            +
                      inputs = thread[:inputs]
         | 
| 143 | 
            +
                      thread[:inputs] = []
         | 
| 144 | 
            +
                      return inputs
         | 
| 145 | 
            +
                    }
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                  def __calc(memo0, memo1, memo2)
         | 
| 149 | 
            +
                    unless memo1.has_key?(self)
         | 
| 150 | 
            +
                      memo0.merge(self => [[], make_thread])
         | 
| 151 | 
            +
                    else
         | 
| 152 | 
            +
                      inputs = get_inputs(memo1[self][1])
         | 
| 153 | 
            +
                      memo1[self][1].run
         | 
| 154 | 
            +
                      return memo0.merge(self => [inputs, memo1[self][1]])
         | 
| 155 | 
            +
                    end
         | 
| 156 | 
            +
                  end
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                class Lift < Signal
         | 
| 160 | 
            +
                  def initialize(*arg_signals, &proc)
         | 
| 161 | 
            +
                    @arg_signals, @proc = arg_signals, proc
         | 
| 162 | 
            +
                  end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  def __pull_deps(memo0, memo1, memo2)
         | 
| 165 | 
            +
                    @arg_signals.inject(memo0){|acc, sig| sig.__pull(acc, memo1, memo2)}
         | 
| 166 | 
            +
                  end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                  def __calc(memo0, memo1, memo2)
         | 
| 169 | 
            +
                    if @arg_signals.all?{|sig| sig.__same(memo0, memo1)}
         | 
| 170 | 
            +
                      memo0.merge(self => memo1[self])
         | 
| 171 | 
            +
                    else
         | 
| 172 | 
            +
                      memo0.merge(self => @proc.call(*@arg_signals.map{|sig| memo0[sig]}))
         | 
| 173 | 
            +
                    end
         | 
| 174 | 
            +
                  end
         | 
| 175 | 
            +
                end
         | 
| 176 | 
            +
                
         | 
| 177 | 
            +
                class Foldp < Signal
         | 
| 178 | 
            +
                  def initialize(init_state, *arg_signals, &proc)
         | 
| 179 | 
            +
                    @init_state, @arg_signals, @proc = init_state, arg_signals, proc
         | 
| 180 | 
            +
                  end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                  def __pull_deps(memo0, memo1, memo2)
         | 
| 183 | 
            +
                    @arg_signals.inject(memo0){|acc, sig| sig.__pull(acc, memo1, memo2)}
         | 
| 184 | 
            +
                  end
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                  def __calc(memo0, memo1, memo2)
         | 
| 187 | 
            +
                    if __same(memo1, memo2) && @arg_signals.all?{|sig| sig.__same(memo0, memo1)}
         | 
| 188 | 
            +
                      memo0.merge(self => memo1[self])
         | 
| 189 | 
            +
                    else
         | 
| 190 | 
            +
                      state = memo1.has_key?(self) ? memo1[self] : @init_state
         | 
| 191 | 
            +
                      memo0.merge(self => @proc.call(state, *@arg_signals.map{|sig| memo0[sig]}))
         | 
| 192 | 
            +
                    end
         | 
| 193 | 
            +
                  end
         | 
| 194 | 
            +
                end
         | 
| 56 195 | 
             
              end
         | 
| 57 196 | 
             
            end
         | 
    
        data/lib/frypan/version.rb
    CHANGED
    
    
    
        data/tutorial/my_at.rb
    ADDED
    
    | @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'socket'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            loop do
         | 
| 6 | 
            +
              print "execution-command> "
         | 
| 7 | 
            +
              com = STDIN.gets
         | 
| 8 | 
            +
              print "execution-time> "
         | 
| 9 | 
            +
              time = STDIN.gets
         | 
| 10 | 
            +
              
         | 
| 11 | 
            +
              break unless com && time
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              socket = TCPSocket.open("localhost", 20000)
         | 
| 14 | 
            +
              socket.write(com + time)
         | 
| 15 | 
            +
              puts "response: #{socket.gets}"
         | 
| 16 | 
            +
              socket.close
         | 
| 17 | 
            +
            end
         | 
    
        data/tutorial/my_atd.rb
    ADDED
    
    | @@ -0,0 +1,85 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'frypan'
         | 
| 4 | 
            +
            require 'socket'
         | 
| 5 | 
            +
            require 'time'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            S = Frypan::Signal
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            socket = TCPServer.new(20000)
         | 
| 10 | 
            +
            puts "my_atd listening port: 20000..."
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            accepter = proc do
         | 
| 13 | 
            +
              connection = socket.accept
         | 
| 14 | 
            +
              c, t = connection.gets, connection.gets
         | 
| 15 | 
            +
              {command_str: c.chomp, time_str: t.chomp, connection: connection}
         | 
| 16 | 
            +
            end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            timer = proc do
         | 
| 19 | 
            +
              Time.now
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            update_commands = proc do |commands, ct, cs|
         | 
| 23 | 
            +
              {
         | 
| 24 | 
            +
                waitings: commands[:waitings].select{|c| c[:time] > ct} +
         | 
| 25 | 
            +
                cs.select{|c| acceptable?(c)}.map{|c| c.update(time: Time.parse(c[:time_str]))},
         | 
| 26 | 
            +
                launcheds: commands[:waitings].select{|c| c[:time] <= ct},
         | 
| 27 | 
            +
                rejecteds: cs.reject{|c| acceptable?(c)}
         | 
| 28 | 
            +
              }
         | 
| 29 | 
            +
            end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            output_formatize = proc do |coms, cs|
         | 
| 32 | 
            +
              ress = cs.map do |c|
         | 
| 33 | 
            +
                if coms[:rejecteds].include?(c)
         | 
| 34 | 
            +
                  msg = "Your specified time '#{c[:time_str]}' seems invalid.\n"
         | 
| 35 | 
            +
                else
         | 
| 36 | 
            +
                  msg = "OK.\n"
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
                {message: msg, connection: c[:connection]}
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
              {commands: coms[:launcheds].map{|c| c[:command_str]}, responses: ress}
         | 
| 41 | 
            +
            end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            exec_commands = proc do |commands|
         | 
| 44 | 
            +
              commands.each do |command|
         | 
| 45 | 
            +
                puts "execute command '#{command}'"
         | 
| 46 | 
            +
                pid =  Process.spawn(command, :out => STDOUT, :err => STDERR)
         | 
| 47 | 
            +
                puts "PID = #{pid}"
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            respond = proc do |responses|
         | 
| 52 | 
            +
              responses.each do |res|
         | 
| 53 | 
            +
                res[:connection].write(res[:message])
         | 
| 54 | 
            +
                res[:connection].close
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            output_processor = proc do |out|
         | 
| 59 | 
            +
              exec_commands.call(out[:commands])
         | 
| 60 | 
            +
              respond.call(out[:responses])
         | 
| 61 | 
            +
            end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            # helper method (pure function)
         | 
| 64 | 
            +
            def acceptable?(c)
         | 
| 65 | 
            +
              Time.parse(c[:time_str])
         | 
| 66 | 
            +
            rescue
         | 
| 67 | 
            +
              nil
         | 
| 68 | 
            +
            end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            # Input-Signal representing new clients.
         | 
| 71 | 
            +
            new_clients = S.async_input(5, &accepter)
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            # Input-Signal representing current time.
         | 
| 74 | 
            +
            current_time = S.input(&timer)
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            # Foldp-Signal representing registered commands.
         | 
| 77 | 
            +
            initial = {waitings: [], launcheds: [], rejecteds: []}
         | 
| 78 | 
            +
            commands = S.foldp(initial, current_time, new_clients, &update_commands)
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            # Lift-Signal representing output datas.
         | 
| 81 | 
            +
            main = S.lift(commands, new_clients, &output_formatize)
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            # FRP's main-loop.
         | 
| 84 | 
            +
            Frypan::Reactor.new(main).loop(&output_processor)
         | 
| 85 | 
            +
             |