elixir.rb 0.0.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15fb2272872a876e03b59892cfb9d9cced68d84d
4
- data.tar.gz: 333f401ceba52b483d13b4e1c461e06efe7c5b91
3
+ metadata.gz: d7b6ce1986007232752ade7baa4a4384e3ac0bcd
4
+ data.tar.gz: 8e9026a46c431118f6def60109111258db33f20a
5
5
  SHA512:
6
- metadata.gz: fd7906c50277830fca9aecccfbeea3aa0080f1b641f3391681b0adbcb827a8ea82ab215eb6538d46fa7829bf2d52f3e3a48499bcdc9fd3a886851b9de4b438e8
7
- data.tar.gz: 3468e8bcc516a445b4d44cd9ed3fee8d2d8a20dced5b59b6e9df9db13b2b96461235c0ed651766f16fddc19eb95f47647023c0b544024bb929d4a4f99feded96
6
+ metadata.gz: 682c9489155dd9a8b437eedbc7cd76907739748593309d3c82c4f8e9dfec7cafb7f5744889d5d82152b93f32bff6fc5f05ef936f941b65f2abb6a3e957e87bc4
7
+ data.tar.gz: 6c6addc1416853eb98ffaf0caa85d8c0321c1c54d8c231aeae6665cc68450294c4d799158b7474b1af1e9e230e38dc2352e6c56ca3dd771793a1d4457d616c22
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
- ## 0.0.0 (2015-06-26)
3
+ ## 0.1.0 (2015-07-07)
4
4
 
5
- * Primordial ooze
5
+ A partial implementation of the following Elixir modules:
6
+ * Agent
7
+ * Atom
8
+ * Base
9
+ * Dict
10
+ * Enum
11
+ * File
12
+ * Float
13
+ * Integer
14
+ * List
15
+ * OptionParser
16
+ * Path
17
+ * Range
18
+ * Set
19
+ * Stream
20
+ * String
21
+ * System
22
+ * Task
23
+ * Tuple
24
+ * Version
data/README.md CHANGED
@@ -1,6 +1,28 @@
1
1
  # Elixir.rb
2
2
 
3
- The Elixir standard library implemented in Ruby. This is currently just a code spike that implements parts of Enum and Stream.
3
+ The [Elixir](http://elixir-lang.org) standard library in [Ruby](https://www.ruby-lang.org)!
4
+
5
+ So far there are partial implementations of the following Elixir modules:
6
+
7
+ * Agent
8
+ * Atom
9
+ * Base
10
+ * Dict
11
+ * Enum
12
+ * File
13
+ * Float
14
+ * Integer
15
+ * List
16
+ * OptionParser
17
+ * Path
18
+ * Range
19
+ * Set
20
+ * Stream
21
+ * String
22
+ * System
23
+ * Task
24
+ * Tuple
25
+ * Version
4
26
 
5
27
  ## Installation
6
28
 
@@ -8,7 +30,9 @@ The Elixir standard library implemented in Ruby. This is currently just a code s
8
30
  gem install elixir.rb
9
31
  ```
10
32
 
11
- ## Usage
33
+ ## Examples
34
+
35
+ [Stream.unfold/2](http://elixir-lang.org/docs/stable/elixir/Stream.html#unfold/2)
12
36
 
13
37
  ```ruby
14
38
  require 'elixir/stream'
@@ -19,19 +43,41 @@ Fib = Stream.unfold [0, 1] do |a, b|
19
43
  [a, [b, a + b]]
20
44
  end
21
45
 
46
+ Fib.size
47
+ #=> Infinity
48
+
22
49
  Fib.take 5
23
50
  #=> [0, 1, 1, 2, 3]
24
51
  ```
25
52
 
53
+ [Agent](http://elixir-lang.org/docs/stable/elixir/Agent.html) and [Task](http://elixir-lang.org/docs/stable/elixir/Task.html)
54
+
26
55
  ```ruby
27
- require 'elixir/enum'
56
+ require 'elixir/agent'
57
+ require 'elixir/task'
28
58
 
29
59
  include Elixir
30
60
 
31
- Enum.filter [1, 2, 3], &:odd?
32
- #=> [1, 3]
61
+ status, agent = Agent.start { 0 }
62
+ #=> [:ok, #<Concurrent::Atomic:...>]
63
+
64
+ Agent.cast(agent) { |value| value + 42 }
65
+ #=> :ok
66
+
67
+ Agent.get(agent, &:next)
68
+ #=> 43
69
+
70
+ task = Task.async ->{ sleep 0.5; Agent.get(agent, &:itself) }
71
+ #<Concurrent::IVar:...>
72
+
73
+ Task.await(task)
74
+ #=> 42
33
75
  ```
34
76
 
77
+ ## Requirements
78
+
79
+ Ruby 2.2+
80
+
35
81
  ## Development
36
82
 
37
83
  Install Elixir.rb and its deps:
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
- require 'bundler/gem_tasks'
2
1
  require 'rake/testtask'
3
2
 
4
3
  Rake::TestTask.new :test do |t|
@@ -1,22 +1,26 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path '../lib', File.basename(__FILE__)
2
+ lib = File.expand_path '../lib', __FILE__
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
4
5
  require 'elixir/version'
5
6
 
6
7
  Gem::Specification.new do |gem|
7
8
  gem.name = 'elixir.rb'
8
9
  gem.version = Elixir::VERSION
9
10
  gem.author = 'Shannon Skipper'
10
- gem.license = 'MIT'
11
11
  gem.email = ['shannonskipper@gmail.com']
12
+ gem.license = 'MIT'
12
13
 
13
- gem.summary = 'The Elixir standard library implemented in Ruby. This is currently just a code spike with parts of Enum and Stream.'
14
- gem.description = 'A Ruby implementation of part of the Elixir standard library.'
14
+ gem.summary = 'The Elixir standard library in Ruby.'
15
+ gem.description = 'An implementation of parts of the Elixir standard library in Ruby.'
15
16
  gem.homepage = 'https://github.com/havenwood/elixir.rb'
16
17
 
17
18
  gem.files = `git ls-files -z`.split("\x0").reject { |path| path.start_with? 'test' }
18
19
  gem.require_paths = ['lib']
19
20
 
20
- gem.add_development_dependency 'rake', '~> 10.0'
21
- gem.add_development_dependency 'minitest', '~> 5.7'
21
+ gem.add_dependency 'base32', '~> 0.3', '>= 0.3.2'
22
+ gem.add_dependency 'concurrent-ruby', '~> 0.8', '>= 0.8.0'
23
+
24
+ gem.add_development_dependency 'rake', '~> 10.4', '>= 10.4.2'
25
+ gem.add_development_dependency 'minitest', '~> 5.7', '>= 5.7.0'
22
26
  end
@@ -1,5 +1,21 @@
1
+ require 'elixir/agent'
2
+ require 'elixir/atom'
3
+ require 'elixir/base'
4
+ require 'elixir/dict'
1
5
  require 'elixir/enum'
6
+ require 'elixir/file'
7
+ require 'elixir/float'
8
+ require 'elixir/integer'
9
+ require 'elixir/list'
10
+ require 'elixir/option_parser'
11
+ require 'elixir/path'
12
+ require 'elixir/range'
13
+ require 'elixir/set'
2
14
  require 'elixir/stream'
15
+ require 'elixir/string'
16
+ require 'elixir/system'
17
+ require 'elixir/task'
18
+ require 'elixir/tuple'
3
19
  require 'elixir/version'
4
20
 
5
21
  module Elixir
@@ -0,0 +1,42 @@
1
+ require 'concurrent'
2
+
3
+ module Elixir
4
+ module Agent
5
+ module_function
6
+
7
+ def cast agent, &fun
8
+ agent.try_update do |value|
9
+ ->{ fun.call value.call }
10
+ end
11
+
12
+ :ok
13
+ end
14
+
15
+ def get agent, &fun
16
+ fun.call agent.get.call
17
+ end
18
+
19
+ def get_and_update agent, &fun
20
+ old_lambda = agent.get
21
+ old_value = old_lambda.call
22
+ new_lambda = ->{ fun.call old_value }
23
+ agent.compare_and_set old_lambda, new_lambda
24
+
25
+ old_value
26
+ end
27
+
28
+ def start &fun
29
+ [:ok, Concurrent::Atomic.new(fun)]
30
+ end
31
+
32
+ def update agent, &fun
33
+ agent.update do |value|
34
+ ->{ fun.call value.call }
35
+ end
36
+
37
+ :ok
38
+ end
39
+
40
+ # TODO: Timeouts and explain what's lacking in the Ruby implementation.
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ module Elixir
2
+ module Atom
3
+ module_function
4
+
5
+ def to_char_list symbol
6
+ symbol.to_s.chars
7
+ end
8
+
9
+ def to_string symbol
10
+ symbol.to_s
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,99 @@
1
+ require 'base32'
2
+ require 'base64'
3
+
4
+ module Elixir
5
+ module Base
6
+ UPPERCASE = /[[:upper:]]/.freeze
7
+ LOWERCASE = /[[:lower:]]/.freeze
8
+
9
+ module_function
10
+
11
+ def decode16 string, char_case: :upper
12
+ case char_case
13
+ when :upper
14
+ return :error if string =~ LOWERCASE
15
+ when :lower
16
+ return :error if string =~ UPPERCASE
17
+ end
18
+
19
+ [:ok, [string].pack('H*')] rescue :error
20
+ end
21
+
22
+ def decode16! string, char_case: :upper
23
+ case char_case
24
+ when :upper
25
+ raise ArgumentError if string =~ LOWERCASE
26
+ when :lower
27
+ raise ArgumentError if string =~ UPPERCASE
28
+ end
29
+
30
+ [string].pack 'H*'
31
+ end
32
+
33
+ def decode32 string, char_case: :upper
34
+ case char_case
35
+ when :upper
36
+ return :error if string =~ LOWERCASE
37
+ when :lower
38
+ return :error if string =~ UPPERCASE
39
+ end
40
+
41
+ [:ok, Base32.decode(string)] rescue :error
42
+ end
43
+
44
+ def decode32! string, char_case: :upper
45
+ case char_case
46
+ when :upper
47
+ raise ArgumentError if string =~ LOWERCASE
48
+ when :lower
49
+ raise ArgumentError if string =~ UPPERCASE
50
+ end
51
+
52
+ Base32.decode string
53
+ end
54
+
55
+ def decode64 string
56
+ [:ok, Base64.strict_decode64(string)] rescue :error
57
+ end
58
+
59
+ def decode64! string
60
+ Base64.strict_decode64 string
61
+ end
62
+
63
+ def encode16 data, char_case: :upper
64
+ encoded = data.unpack('H*').first
65
+
66
+ char_case == :upper ? encoded.upcase : encoded
67
+ end
68
+
69
+ def encode32 data, char_case: :upper
70
+ encoded = Base32.encode data
71
+
72
+ char_case == :upper ? encoded.upcase : encoded
73
+ end
74
+
75
+ def encode64 data
76
+ Base64.strict_encode64(data)
77
+ end
78
+
79
+ def hex_encode32 string, char_case: :upper
80
+ # TODO
81
+ end
82
+
83
+ def hex_decode32 string, char_case: :upper
84
+ # TODO
85
+ end
86
+
87
+ def hex_decode32! string, char_case: :upper
88
+ # TODO
89
+ end
90
+
91
+ def url_decode64 string
92
+ # TODO
93
+ end
94
+
95
+ def url_decode64! string
96
+ # TODO
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,87 @@
1
+ module Elixir
2
+ module Dict
3
+ module_function
4
+
5
+ def delete list, key
6
+ list.delete key
7
+
8
+ list
9
+ end
10
+
11
+ def drop list, keys
12
+ keys.each do |key|
13
+ list.delete key
14
+ end
15
+
16
+ list
17
+ end
18
+
19
+ def equal? dict1, dict2
20
+ dict1.eql? dict2
21
+ end
22
+
23
+ def fetch dict, key
24
+ dict.fetch(key) rescue nil
25
+ end
26
+
27
+ def fetch!
28
+ dict.fetch key
29
+ end
30
+
31
+ def get dict, key, default = nil
32
+ # TODO
33
+ end
34
+
35
+ def hash_key? dict, key
36
+ # TODO
37
+ end
38
+
39
+ def keys dict
40
+ # TODO
41
+ end
42
+
43
+ def merge dict1, dict2, fun = -> _k, _v1, v2 { v2 }
44
+ # TODO
45
+ end
46
+
47
+ def pop dict, key, default = nil
48
+ # TODO
49
+ end
50
+
51
+ def put dict, key, val
52
+ # TODO
53
+ end
54
+
55
+ def put_new dict, key, val
56
+ # TODO
57
+ end
58
+
59
+ def size dict
60
+ # TODO
61
+ end
62
+
63
+ def split dict, keys
64
+ # TODO
65
+ end
66
+
67
+ def take dict, keys
68
+ # TODO
69
+ end
70
+
71
+ def to_list dict
72
+ # TODO
73
+ end
74
+
75
+ def update dict, key, initial, fun
76
+ # TODO
77
+ end
78
+
79
+ def update! dict, key, fun
80
+ # TODO
81
+ end
82
+
83
+ def values dict
84
+ # TODO
85
+ end
86
+ end
87
+ end
@@ -15,6 +15,7 @@ module Elixir
15
15
  end
16
16
 
17
17
  def chunk collection, n, step: nil, pad: nil
18
+ # TODO
18
19
  end
19
20
 
20
21
  def chunk_by collection, &block
@@ -37,14 +38,22 @@ module Elixir
37
38
  collection.drop_while &block
38
39
  end
39
40
 
41
+ def each collection, &block
42
+ collection.each &block
43
+
44
+ :ok
45
+ end
46
+
40
47
  def empty? collection
41
48
  collection.empty?
42
49
  end
43
50
 
44
51
  def fetch collection, n
52
+ # TODO
45
53
  end
46
54
 
47
55
  def fetch! collection, n
56
+ # TODO
48
57
  end
49
58
 
50
59
  def filter collection, &block
@@ -52,6 +61,7 @@ module Elixir
52
61
  end
53
62
 
54
63
  def filter_map collection, filter, mapper
64
+ # TODO
55
65
  end
56
66
 
57
67
  def find collection, ifnone = nil, &block
@@ -59,9 +69,11 @@ module Elixir
59
69
  end
60
70
 
61
71
  def find_index collection, &block
72
+ # TODO
62
73
  end
63
74
 
64
75
  def find_value collection, ifnone = nil, &block
76
+ # TODO
65
77
  end
66
78
 
67
79
  def flat_map collection, &block
@@ -69,15 +81,19 @@ module Elixir
69
81
  end
70
82
 
71
83
  def flat_map_reduce collection, acc, &block
84
+ # TODO
72
85
  end
73
86
 
74
- def group_by collection, dict = {}, &block
87
+ def group_by collection, &block
88
+ collection.group_by(&block).map { |k, v| [k.to_s.to_sym, v] }.to_h
75
89
  end
76
90
 
77
91
  def intersperse collection, element
92
+ collection.each_with_object(element).to_a.flatten 1
78
93
  end
79
94
 
80
95
  def into collection, list, transform = nil
96
+ # TODO
81
97
  end
82
98
 
83
99
  def join collection, joiner = ''
@@ -89,16 +105,19 @@ module Elixir
89
105
  end
90
106
 
91
107
  def map_join collection, joiner = '', &block
108
+ collection.map(&block).join joiner
92
109
  end
93
110
 
94
111
  def map_reduce collection, acc, &block
112
+ # TODO
95
113
  end
96
114
 
97
115
  def max collection
98
- collection.max
116
+ collection.max or raise 'empty error'
99
117
  end
100
118
 
101
119
  def max_by collection, &block
120
+ collection.max_by &block
102
121
  end
103
122
 
104
123
  def member? collection, value
@@ -106,7 +125,7 @@ module Elixir
106
125
  end
107
126
 
108
127
  def min collection
109
- collection.min
128
+ collection.min or raise 'empty error'
110
129
  end
111
130
 
112
131
  def min_by collection, &block
@@ -134,6 +153,7 @@ module Elixir
134
153
  end
135
154
 
136
155
  def scan collection, acc = 0, &block
156
+ # TODO
137
157
  end
138
158
 
139
159
  def shuffle collection
@@ -141,6 +161,7 @@ module Elixir
141
161
  end
142
162
 
143
163
  def slice collection, x, count = nil
164
+ # TODO
144
165
  end
145
166
 
146
167
  def sort collection, &block
@@ -148,13 +169,15 @@ module Elixir
148
169
  end
149
170
 
150
171
  def sort_by collection, mapper, sorter = nil
172
+ # TODO
151
173
  end
152
174
 
153
175
  def split collection, count
154
-
176
+ # TODO
155
177
  end
156
178
 
157
179
  def split_while collection, &block
180
+ # TODO
158
181
  end
159
182
 
160
183
  def sum collection
@@ -166,10 +189,11 @@ module Elixir
166
189
  end
167
190
 
168
191
  def take_every collection, nth
169
- collection.step by: nth
192
+ collection.each_slice(nth).map &:first
170
193
  end
171
194
 
172
195
  def take_while collection, &block
196
+ # TODO
173
197
  end
174
198
 
175
199
  def to_list collection