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.
- checksums.yaml +4 -4
- data/README.md +20 -15
- data/lib/mll.rb +34 -16
- data/mll.gemspec +1 -1
- data/spec/_spec.rb +144 -19
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b28b0ef583cd90f87454f37cebdc8a3088ba42a
|
4
|
+
data.tar.gz: 05757c078b5eade518f1895e71c9bf3e0af97f5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
3
|
+
## What
|
4
4
|
|
5
|
-
|
5
|
+
Этот гем не ставит перед собой цель полностью имитировать типы данных, синтаксис Wolfram Mathematica Language, или научить Ruby крутым визуализациям. Целью является вложить в Ruby мощь стандартной библиотеки. В перспективе визуализация возможна при помощи других гемов.
|
6
6
|
|
7
|
-
|
7
|
+
## Why
|
8
8
|
|
9
|
-
|
9
|
+
1. Важной является реализация https://reference.wolfram.com/language/ref/Listable.html: автоматическое применение функции ко всем элементам аргумента, если тот является List-ом (Array-ем в среде Ruby).
|
10
|
+
2. `::range`, в отличие от рубишного, может иметь отрицательный step.
|
11
|
+
3. `::table`, в отличие от рубишного `.map`, может создавать многомерные массивы одним вызовом, а не только вложенными.
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
4
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
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)")
|
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|
|
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
|
data/mll.gemspec
CHANGED
data/spec/_spec.rb
CHANGED
@@ -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
|
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
|
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(
|
29
|
-
expect(MLL::range(2,5)).to be_a
|
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(
|
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
|
-
|
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
|
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(
|
67
|
-
expect(MLL::range(
|
68
|
-
MLL::range(
|
69
|
-
expect(i).to be_a
|
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
|
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,
|
102
|
-
expect(MLL::table(->(i){ i**2 },
|
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, [
|
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,
|
108
|
-
|
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,
|
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 },
|
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
|