mll 0.2.0 → 0.3.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.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -15
  3. data/lib/mll.rb +34 -16
  4. data/mll.gemspec +1 -1
  5. data/spec/_spec.rb +144 -19
  6. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 70676b9e4d6334e3e8391c256aa11c3ea5e9c033
4
- data.tar.gz: 7e8b55eb690a4ee783358750fd25ca1045475508
3
+ metadata.gz: 0b28b0ef583cd90f87454f37cebdc8a3088ba42a
4
+ data.tar.gz: 05757c078b5eade518f1895e71c9bf3e0af97f5f
5
5
  SHA512:
6
- metadata.gz: 449a0ca50feab9413c62cc1a67d37bb4a349ab97f0c842f676cea2ddea06ba03b29d96d8200bd846c9700d3388f60112ab3b900408f5a47aa7aa4b38d78342fd
7
- data.tar.gz: 8f5f8a226918468f4e3f636df329f4520c686181fccca13c26b04bd493018156da4f79101b07a27dfbbfab32de5306b223505dbc52f914d5a8a44bad8b9dd780
6
+ metadata.gz: cf8caa79c3a7cc275b234c1dcb1d1bc6a0bc9a772f585bddc171cc8d4bd2dacff587cc37c963df7fbab53880c48ca62579ba5c63e109235836288611b6011f8a
7
+ data.tar.gz: 8c3053016c69c2ead9e8fd965a661167332e45b00841e15fbdd570325888e5c74e03c5ee89b339bcd665ae75d24bf37574e201686ae0bf3a3b9f3127a1ea9331
data/README.md CHANGED
@@ -1,29 +1,34 @@
1
1
  # MLL (Mathematica Language Library)
2
2
 
3
- Этот гем не ставит перед собой цель полностью имитировать типы данных, синтаксис Wolfram Mathematica Language, или научить Ruby крутым визуализациям. Целью является вложить в Ruby мощь стандартной библиотеки. Прежде всего, List Manipulation. В перспективе визуализация возможна при помощи других гемов.
3
+ ## What
4
4
 
5
- ## Usage
5
+ Этот гем не ставит перед собой цель полностью имитировать типы данных, синтаксис Wolfram Mathematica Language, или научить Ruby крутым визуализациям. Целью является вложить в Ruby мощь стандартной библиотеки. В перспективе визуализация возможна при помощи других гемов.
6
6
 
7
- ~~Планируется несколько способов использования этой библиотеки -- как доступ к ней через `MLL::`, так и манкипатчинг стандартных типов, таких как Numeric и Array.~~
7
+ ## Why
8
8
 
9
- ### Examples:
9
+ 1. Важной является реализация https://reference.wolfram.com/language/ref/Listable.html: автоматическое применение функции ко всем элементам аргумента, если тот является List-ом (Array-ем в среде Ruby).
10
+ 2. `::range`, в отличие от рубишного, может иметь отрицательный step.
11
+ 3. `::table`, в отличие от рубишного `.map`, может создавать многомерные массивы одним вызовом, а не только вложенными.
10
12
 
11
- MLL::range(3).to_a #=> [1, 2, 3]
12
- MLL::range(2, 3).to_a #=> [
13
- #<Enumerator: 1..2:step(1)>,
14
- #<Enumerator: 1..3:step(1)>,
15
- ]
16
- MLL::range(1..3) #=> [
17
- #<Enumerator: 1..1:step(1)>,
18
- #<Enumerator: 1..2:step(1)>,
19
- #<Enumerator: 1..3:step(1)>
20
- ]
13
+ ## How
14
+
15
+ MLL::range(2, 3) #=> 2..3
16
+ MLL::range([2, 3]) #=> [1..2, 1..3]
17
+ MLL::range(1..3) #=> [1..1, 1..2, 1..3]
18
+
19
+ MLL::table ->(i,j){ i+j }, [[1, 0, 1]], [[0, 2, 0]]
20
+ #=> [[1, 3, 1],
21
+ [0, 2, 0],
22
+ [1, 3, 1]]
23
+ MLL::table ->(i,j,k){ 100*i + 10*j + k }, 2, 3, 4
24
+ # => [[[111, 112, 113, 114], [121, 122, 123, 124], [131, 132, 133, 134]],
25
+ [[211, 212, 213, 214], [221, 222, 223, 224], [231, 232, 233, 234]]]
21
26
 
22
27
  ## Installation
23
28
 
24
29
  $ gem install mll
25
30
 
26
- ### Testing with RSpec before contributing
31
+ ## Testing with RSpec before contributing
27
32
 
28
33
  rspec
29
34
 
data/lib/mll.rb CHANGED
@@ -1,22 +1,22 @@
1
1
  module MLL
2
2
 
3
- def self.define_function_that_can_enumerate name, &block
4
- # http://stackoverflow.com/a/12792313/322020
5
- (class << self; self end).class_eval do
3
+ # https://reference.wolfram.com/language/ref/Listable.html
4
+ def self.define_listable_function name, &block
5
+ (class << self; self end).class_eval do # http://stackoverflow.com/a/12792313/322020
6
6
  define_method name do |*args|
7
- if args.size == 1 && args.first.respond_to?(:map)
8
- args.first.lazy.map &method(name)
9
- else
10
- block.call *args
11
- end
7
+ # p [name, args]
8
+ next block.call *args unless args[0].respond_to? :map
9
+ next args[0].lazy.map{ |i| send name, i, *args.drop(1) } unless args[1].respond_to? :map
10
+ # raise "idk how to list this function" if args.size > 2
11
+ next args[0].lazy.zip(args[1]).map{ |i,j| send name, i, j, *args.drop(2) }
12
12
  end
13
13
  end
14
14
  end
15
15
 
16
- define_function_that_can_enumerate :range do |*args|
16
+ define_listable_function :range do |*args|
17
17
  case args.size
18
18
  when 1 ; range 1, args[0] # TODO do smth with #table(-n)
19
- when 2 ; Range.new(args[0], args[1])
19
+ when 2 ; Range.new(args[0], args[1]).step
20
20
  when 3
21
21
  case args[2] <=> 0
22
22
  when 0 ; raise ArgumentError.new("step can't be zero")
@@ -24,34 +24,52 @@ module MLL
24
24
  else
25
25
  Enumerator.new do |e|
26
26
  from, to, step = *args
27
- while (step > 0) ? from <= to : from >= to
27
+ # while (step > 0) ? from <= to : from >= to
28
+ while from >= to
28
29
  e << from
29
30
  from += step
30
31
  end
31
32
  end
32
33
  end
33
34
  else
34
- raise ArgumentError.new("wrong number of arguments (#{args.size} for 1..3)") # unless (1..3).include? args.size
35
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 1..3)")
35
36
  end
36
37
  end
37
38
 
38
39
  def self.table f, *args
39
- # TODO make it lazy?
40
-
41
40
  [].tap do |result|
42
- [[result, args.map{ |r| range(*r).to_a }]].tap do |stack|
41
+ [[result, args.map{ |r| # add lazy?
42
+ r.respond_to?(:map) && r.first.respond_to?(:map) ?
43
+ r.first : range(*r)
44
+ }]].tap do |stack|
43
45
  stack.each do |ai, ri|
46
+ # TODO try to make #table lazy (Enumerator instead of Array)
47
+ # "no implicit conversion of Enumerator::Lazy into Array"
48
+ # "undefined method `replace' for #<Enumerator::Lazy: []>"
44
49
  ai.replace ri.first.map{ |i|
45
50
  if ri.size == 1
46
51
  f.call(*ai, i)
47
52
  else
48
53
  [*ai.dup, i].tap{ |t| stack << [t, ri.drop(1)] }
49
54
  end
50
- }
55
+ }#.to_a # WTF
51
56
  end
52
57
  end
53
58
  end
59
+ end
60
+
61
+ define_listable_function :divide do |a, b|
62
+ a / b
63
+ end
54
64
 
65
+ def self.subdivide *args
66
+ case args.size
67
+ when 1 ; subdivide 1, args[0]
68
+ when 2 ; subdivide 0, args[0], args[1]
69
+ when 3 ; range(args[0], args[1], (args[1] - args[0]) * 1.0 / args[2])
70
+ else
71
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 1..3)")
72
+ end
55
73
  end
56
74
 
57
75
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "mll"
3
- spec.version = "0.2.0"
3
+ spec.version = "0.3.0"
4
4
  spec.authors = ["Victor Maslov"]
5
5
  spec.email = ["nakilon@gmail.com"]
6
6
  spec.summary = "Mathematica Language Library in Ruby"
@@ -1,9 +1,74 @@
1
1
  require_relative File.join "..", "lib", "mll"
2
2
 
3
3
 
4
+ # PERMANENT TODO test all implemented exceptions
5
+ # PERMANENT TODO test all types returned
6
+
7
+
4
8
  # http://reference.wolfram.com/language/guide/LanguageOverview.html
5
9
  describe MLL do
6
10
 
11
+ # http://reference.wolfram.com/language/guide/Syntax.html
12
+ describe "Syntax" do
13
+
14
+ # NO URL
15
+ describe "Mathematics & Operators" do
16
+
17
+ # http://reference.wolfram.com/language/ref/Divide.html
18
+ describe "#divide" do
19
+
20
+ describe "Basic Examples" do
21
+
22
+ example "n1 / n2" do
23
+ expect(MLL::divide(77,11)).to be_a Fixnum
24
+ expect(MLL::divide(77,11)).to eq 7
25
+ end
26
+
27
+ end
28
+
29
+ describe "Scope" do
30
+
31
+ example "list / n" do
32
+ expect(MLL::divide([2,3,4,5],2.0)).to be_a Enumerator
33
+ expect(MLL::divide([2,3,4,5],2.0).to_a).to eq [1,1.5,2,2.5]
34
+ end
35
+ example "list / list" do
36
+ expect(MLL::divide([2,3,4],[2,1,4])).to be_a Enumerator
37
+ expect(MLL::divide([2,3,4],[2,1,4]).to_a).to eq [1,3,1]
38
+ end
39
+
40
+ end
41
+
42
+ describe "Applications" do
43
+
44
+ example "foldlist(divide, 1, range(10))" do
45
+ pending "#foldlist is yet to be implemented"
46
+ fail
47
+ end
48
+
49
+ # TODO: "Successive ratios in a list:"
50
+
51
+ end
52
+
53
+ describe "Neat Examples" do
54
+
55
+ example "nest_list(lambda_with_divide), n" do
56
+ pending "#nestlist is yet to be implemented"
57
+ fail
58
+ end
59
+ example "table(divide, n1, n2)" do
60
+ expect(MLL::table(MLL.method(:divide), [[3,6]], 4.0)).to be_a Array
61
+ expect(MLL::table(MLL.method(:divide), [[6]], 4.0)).to eq [[6.0,3.0,2.0,1.5]]
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
7
72
  # http://reference.wolfram.com/language/guide/ListManipulation.html
8
73
  describe "List Manipulation" do
9
74
 
@@ -13,7 +78,7 @@ describe MLL do
13
78
  # http://reference.wolfram.com/language/ref/Range.html
14
79
  describe "#range" do
15
80
 
16
- # TODO negative step and add it to README.rb
81
+ # TODO take from docs more examples that involve other functions
17
82
 
18
83
  example "range( >3 args )" do
19
84
  expect{ MLL::range(1,2,3,4) }.to raise_error ArgumentError
@@ -22,22 +87,24 @@ describe MLL do
22
87
  describe "Basic Examples" do
23
88
 
24
89
  example "range(n)" do
25
- expect(MLL::range(4)).to be_a Range
90
+ expect(MLL::range(4)).to be_a Enumerator
26
91
  expect(MLL::range(4).to_a).to eq [1,2,3,4]
27
92
  end
28
- example "range(imin, imax)" do
29
- expect(MLL::range(2,5)).to be_a Range
93
+ example "range(min, max)" do
94
+ expect(MLL::range(2,5)).to be_a Enumerator
30
95
  expect(MLL::range(2,5).to_a).to eq [2,3,4,5]
31
96
  end
32
- example "range(imin, imax, id)" do
97
+ example "range(min, max, step)" do
33
98
  expect(MLL::range(1,2,3)).to be_a Enumerator
34
99
  expect(MLL::range(1,2,0.5).to_a).to eq [1,1.5,2] # can be precision problems
35
100
  expect(MLL::range(2,6,2).to_a).to eq [2,4,6]
36
101
  expect(MLL::range(-4,9,3).to_a).to eq [-4,-1,2,5,8]
37
- # Ruby can't negative Range#step, haha!
102
+ end
103
+ example "range(max, min, -step)" do
38
104
  expect(MLL::range(10,-5,-2).to_a).to eq [10,8,6,4,2,0,-2,-4]
39
105
  expect(MLL::range(3,1,-1).to_a).to eq [3,2,1]
40
106
  end
107
+
41
108
  end
42
109
 
43
110
  describe "Generalizations & Extensions" do
@@ -45,7 +112,7 @@ describe MLL do
45
112
  example "range([n1, n2, n3, n4])" do
46
113
  expect(MLL::range([5,2,6,3])).to be_a Enumerator
47
114
  MLL::range([5,2,6,3]).each do |i|
48
- expect(i).to be_a Range
115
+ expect(i).to be_a Enumerator
49
116
  end
50
117
  expect(MLL::range([5,2,6,3]).to_a.map(&:to_a)).to eq [[1,2,3,4,5],[1,2],[1,2,3,4,5,6],[1,2,3]]
51
118
  end
@@ -63,10 +130,10 @@ describe MLL do
63
130
 
64
131
  describe "Neat Examples" do
65
132
 
66
- example "range(imin..imax)" do
67
- expect(MLL::range(MLL::range(3))).to be_a Enumerator
68
- MLL::range(MLL::range(3)).each do |i|
69
- expect(i).to be_a Range
133
+ example "range(min..max)" do
134
+ expect(MLL::range(1..3)).to be_a Enumerator
135
+ MLL::range(1..3).each do |i|
136
+ expect(i).to be_a Enumerator
70
137
  end
71
138
  expect(MLL::range(1..3).to_a.map(&:to_a)).to eq [[1],[1,2],[1,2,3]]
72
139
  end
@@ -77,7 +144,7 @@ describe MLL do
77
144
  o.each do |i|
78
145
  expect(i).to be_a Enumerator
79
146
  i.each do |j|
80
- expect(j).to be_a Range
147
+ expect(j).to be_a Enumerator
81
148
  end
82
149
  end
83
150
  end
@@ -95,27 +162,85 @@ describe MLL do
95
162
 
96
163
  # http://reference.wolfram.com/language/ref/Table.html
97
164
  describe "#table" do
165
+ # TODO type checks
98
166
 
99
167
  describe "Basic Examples" do
100
168
 
101
- example "table(lambda, [n])" do
102
- expect(MLL::table(->(i){ i**2 }, [10])).to eq [1,4,9,16,25,36,49,64,81,100]
169
+ example "table(lambda, n)" do
170
+ expect(MLL::table(->(i){ i**2 }, 10)).to be_a Array
171
+ expect(MLL::table(->(i){ i**2 }, 10)).to eq [1,4,9,16,25,36,49,64,81,100]
103
172
  end
104
- example "table(lambda, [imin, imax, id])" do
173
+ example "table(lambda, [min, max, step])" do
174
+ expect(MLL::table(->(i){ i+2 }, [0, 20, 2])).to be_a Array
105
175
  expect(MLL::table(->(i){ i+2 }, [0, 20, 2])).to eq [2,4,6,8,10,12,14,16,18,20,22]
106
176
  end
107
- example "table(lambda, [n1], [n2])" do
108
- expect(MLL::table(->(i, j){ 10*i + j }, [4], [3])).to eq [[11,12,13],[21,22,23],[31,32,33],[41,42,43]]
177
+ example "table(lambda, n1, n2)" do
178
+ # TODO example to README.rb about multiplication table
179
+ expect(MLL::table(->(i, j){ 10*i + j }, 4, 3)).to be_a Array
180
+ expect(MLL::table(->(i, j){ 10*i + j }, 4, 3)).to eq [[11,12,13],[21,22,23],[31,32,33],[41,42,43]]
181
+ end
182
+ example "table(lambda, n1, min..max, [max, min, -step])" do
183
+ expect(MLL::table(->(i,j,k){ [i,j,k] }, 3, 2..3, [5, 1, -2])).to be_a Array
184
+ expect(MLL::table(->(i,j,k){ [i,j,k] }, 3, 2..3, [5, 1, -2])).to eq \
185
+ [
186
+ [[[1, 2, 5], [1, 2, 3], [1, 2, 1]], [[1, 3, 5], [1, 3, 3], [1, 3, 1]]],
187
+ [[[2, 2, 5], [2, 2, 3], [2, 2, 1]], [[2, 3, 5], [2, 3, 3], [2, 3, 1]]],
188
+ [[[3, 2, 5], [3, 2, 3], [3, 2, 1]], [[3, 3, 5], [3, 3, 3], [3, 3, 1]]]
189
+ ]
109
190
  end
110
191
 
111
- example "matrix_form table(lambda, [n1], [n2])" do
192
+ example "matrix_form table(lambda, n1, n2)" do
112
193
  pending "#matrix_form is yet to be implemented"
113
- expect(MLL::matrix_form MLL::table(->(i, j){ 10*i + j }, [4], [3])).to eq "
194
+ expect(MLL::matrix_form MLL::table(->(i, j){ 10*i + j }, 4, 3)).to eq "
114
195
  "
115
196
  end
116
197
 
117
198
  end
118
199
 
200
+ describe "Scope" do
201
+
202
+ # TODO: "Make a triangular array:"
203
+
204
+ example "table(lambda, [list1], [list2])" do
205
+ expect(MLL::table(->(base, power){ base ** power }, [[1,2,4]], [[1,3,4]])).to be_a Array
206
+ expect(MLL::table(->(base, power){ base ** power }, [[1,2,4]], [[1,3,4]])).to eq [[1,1,1],[2,8,16],[4,64,256]]
207
+ expect(MLL::table(->(i,j){ i+j }, [[1]], [[2]])).to be_a Array
208
+ expect(MLL::table(->(i,j){ i+j }, [[1]], [[2]])).to eq [[3]]
209
+ end
210
+
211
+ end
212
+
213
+ describe "Applications" do
214
+
215
+ example "column table(binomial, )" do
216
+ pending "#binomial and #column are yet to be implemented"
217
+ fail
218
+ end
219
+
220
+ end
221
+
222
+ end
223
+
224
+ # http://reference.wolfram.com/language/ref/Subdivide.html
225
+ describe "#subdivide" do
226
+
227
+ example "subdivide(n)" do
228
+ expect(MLL::subdivide(4)).to be_a Enumerator
229
+ expect(MLL::subdivide(4).to_a).to eq [0,0.25,0.5,0.75,1]
230
+ end
231
+ example "subdivide(max, n)" do
232
+ expect(MLL::subdivide(10,5)).to be_a Enumerator
233
+ expect(MLL::subdivide(10,5).to_a).to eq [0,2,4,6,8,10]
234
+ end
235
+ example "subdivide(min, max, n)" do
236
+ expect(MLL::subdivide(-1,1,8)).to be_a Enumerator
237
+ expect(MLL::subdivide(-1,1,8).to_a).to eq [-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1]
238
+ end
239
+ example "subdivide(max, min, n)" do
240
+ expect(MLL::subdivide(1,-1,8)).to be_a Enumerator
241
+ expect(MLL::subdivide(1,-1,8).to_a).to eq [1,0.75,0.5,0.25,0,-0.25,-0.5,-0.75,-1]
242
+ end
243
+
119
244
  end
120
245
 
121
246
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mll
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Maslov