mll 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +58 -21
- data/Rakefile +1 -0
- data/lib/mll.rb +105 -68
- data/mll.gemspec +1 -1
- data/spec/_spec.rb +168 -40
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce709bc99f6cbd85ca763a4752346b0b5e4112cb
|
4
|
+
data.tar.gz: 0e6ba411ce044ecffbc476fcbefcb61a8cf18926
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6464f5860f02778245155c5f7ec98b61bde188482ef2fb90593baf1cf72fbede13ddd47654288745684d0fdc314cbe3e2609284fcb53cd329c6175b288686845
|
7
|
+
data.tar.gz: 00014f6f4d963c1512f844703b39888f084ebe1495e2fedffc3abe0bc29db2af3f78b40618c3280560414b6729c6d490cd2923faf6397fb26645a891f7f7b657
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# MLL (Mathematica Language Library)
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/mll.svg)](http://badge.fury.io/rb/mll)
|
4
|
+
|
3
5
|
## What
|
4
6
|
|
5
7
|
This gem isn't supposed to mimic all data types, exact syntax of Wolfram Mathematica or make Ruby able to make the same visualisations.
|
@@ -8,11 +10,13 @@ The main goal is to make Ruby more powerful by including the most used functions
|
|
8
10
|
|
9
11
|
## Why
|
10
12
|
|
13
|
+
0. `::map` can map Arrays at specified depth!
|
11
14
|
1. One of the most useful things is automatic zipping vectors (`Array`s) when you apply scalar functions to them. https://reference.wolfram.com/language/ref/Listable.html
|
12
15
|
2. unlike Ruby's `Range` class, `::range` can handle negative `step` and even have `float` starting value
|
13
|
-
3. unlike Ruby's `Array
|
14
|
-
4.
|
15
|
-
5.
|
16
|
+
3. unlike Ruby's `Array.new`, `::table` can create multidimensional arrays with a single call, not nested
|
17
|
+
4. `::fold_list` was wanted [here](http://stackoverflow.com/q/1475808/322020) in Ruby while being already implemented as [FoldList[]](http://reference.wolfram.com/language/ref/FoldList.html) in Mathematica and [scanl](http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:scanl) in Haskell
|
18
|
+
5. `::nest` (n times) and `::nest_list` for repetitive applying the same function -- `::nest_while` and `::nest_while_list` are going to be implemented later
|
19
|
+
6. `::tally` -- shortcut to a probably the most common usage of `#group_by` -- calculating total occurences.
|
16
20
|
|
17
21
|
## How
|
18
22
|
|
@@ -20,11 +24,20 @@ The main goal is to make Ruby more powerful by including the most used functions
|
|
20
24
|
MLL::range[[2, 3]] # => [1..2, 1..3]
|
21
25
|
MLL::range[ 1..3 ] # => [1..1, 1..2, 1..3]
|
22
26
|
|
23
|
-
MLL::table[ ->(i,j){ i+j }, [[1, 0, 1]], [[0, 2, 0]] ]
|
27
|
+
t = MLL::table[ ->(i,j){ i+j }, [[1, 0, 1]], [[0, 2, 0]] ]
|
24
28
|
# => [[1, 3, 1],
|
25
29
|
[0, 2, 0],
|
26
30
|
[1, 3, 1]]
|
27
|
-
MLL::
|
31
|
+
t = MLL::map[ ->(i){ [i] }, t, [2] ]
|
32
|
+
# => [[ [1], [3], [1] ],
|
33
|
+
[ [0], [2], [0] ],
|
34
|
+
[ [1], [3], [1] ]]
|
35
|
+
MLL::map[ ->(i){ -i }, t, [3] ]
|
36
|
+
# => [[ [-1], [-3], [-1] ],
|
37
|
+
[ [ 0], [-2], [ 0] ],
|
38
|
+
[ [-1], [-3], [-1] ]]
|
39
|
+
|
40
|
+
MLL::table[ MLL::times, 9, 9 ]
|
28
41
|
# => [[1, 2, 3, 4, 5, 6, 7, 8, 9],
|
29
42
|
[2, 4, 6, 8, 10, 12, 14, 16, 18],
|
30
43
|
[3, 6, 9, 12, 15, 18, 21, 24, 27],
|
@@ -34,6 +47,10 @@ The main goal is to make Ruby more powerful by including the most used functions
|
|
34
47
|
[7, 14, 21, 28, 35, 42, 49, 56, 63],
|
35
48
|
[8, 16, 24, 32, 40, 48, 56, 64, 72],
|
36
49
|
[9, 18, 27, 36, 45, 54, 63, 72, 81]]
|
50
|
+
# ::times means *
|
51
|
+
# ::divide means /
|
52
|
+
# ::subtract means -
|
53
|
+
# ::plus means +
|
37
54
|
|
38
55
|
MLL::fold_list[ MLL::times, MLL::range[10] ]
|
39
56
|
# => [1,2,6,24,120,720,5040,40320,362880,3628800]
|
@@ -42,10 +59,6 @@ The main goal is to make Ruby more powerful by including the most used functions
|
|
42
59
|
# even of different dimensions with basic operations
|
43
60
|
MLL::times[ [[1,2],[3,4]], [5,6] ]
|
44
61
|
# => [[5,10], [18,24]]
|
45
|
-
# ::times means *
|
46
|
-
# ::divide means /
|
47
|
-
# ::subtract means -
|
48
|
-
# ::plus means +
|
49
62
|
|
50
63
|
# http://en.wikipedia.org/wiki/Collatz_conjecture
|
51
64
|
MLL::nest_list[ ->(i){ i.even? ? i/2 : (i*3+1)/2 }, 20, 10 ]
|
@@ -57,7 +70,12 @@ The main goal is to make Ruby more powerful by including the most used functions
|
|
57
70
|
MLL::subdivide[ 5, 10, 4 ]
|
58
71
|
# => [5.0, 6.25, 7.5, 8.75, 10.0]
|
59
72
|
|
60
|
-
|
73
|
+
MLL::tally[ "the quick brown fox jumps over the lazy dog".chars ]
|
74
|
+
# => {"t"=>2, "h"=>2, "e"=>3, " "=>8, "q"=>1, "u"=>2, "i"=>1, "c"=>1, "k"=>1,
|
75
|
+
"b"=>1, "r"=>2, "o"=>4, "w"=>1, "n"=>1, "f"=>1, "x"=>1, "j"=>1, "m"=>1,
|
76
|
+
"p"=>1, "s"=>1, "v"=>1, "l"=>1, "a"=>1, "z"=>1, "y"=>1, "d"=>1, "g"=>1}
|
77
|
+
|
78
|
+
Note that to see some of above examples working in the same way you need `.to_a`, `.map(&:to_a)` or even `.to_a.map(&:to_a)` since lazyness is intensively used.
|
61
79
|
|
62
80
|
## Installation
|
63
81
|
|
@@ -77,15 +95,19 @@ or
|
|
77
95
|
|
78
96
|
```
|
79
97
|
module MLL
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
98
|
+
class << self
|
99
|
+
def fold_list
|
100
|
+
lambda do |f, x, list = nil|
|
101
|
+
# TODO use Ruby#inject ?
|
102
|
+
def map
|
103
|
+
# TODO validate depths
|
104
|
+
# TODO break on passing all depths
|
105
|
+
def table
|
106
|
+
lambda do |f, *args|
|
107
|
+
[].tap do |result|
|
108
|
+
}]].tap do |stack|
|
109
|
+
stack.each do |ai, ri|
|
110
|
+
# TODO try to make #table lazy (Enumerator instead of Array)
|
89
111
|
# TODO not sure if we need any other kind of Listability except of #range[[Array]]
|
90
112
|
```
|
91
113
|
|
@@ -100,14 +122,29 @@ describe MLL do
|
|
100
122
|
describe "List Manipulation" do
|
101
123
|
describe "Constructing Lists" do
|
102
124
|
describe "#table" do
|
103
|
-
describe "Scope" do
|
125
|
+
describe "Scope:" do
|
104
126
|
# TODO: "Make a triangular array:"
|
105
127
|
describe "#range" do
|
106
128
|
# TODO take from docs more examples that involve other functions
|
107
129
|
describe "Applying Functions to Lists" do
|
108
130
|
describe "#fold_list" do
|
109
|
-
describe "Applications" do
|
131
|
+
describe "Applications:" do
|
110
132
|
# TODO maybe move it to README.md
|
133
|
+
describe "#map" do
|
134
|
+
# TODO we'll need less nested mappings when we implement stop on depths depletion
|
135
|
+
describe "Details and Options:" do
|
136
|
+
example "levels n1 though n2" do
|
137
|
+
expect(map[->(i){ [i] }, [1,[2,[3,[4,[5,6]]]]], [2,4]].
|
138
|
+
# TODO smth _<>
|
139
|
+
# TODO "Level corresponds to the whole expression"
|
140
|
+
# TODO currying "Map[f][expr] is equivalent to Map[f,expr]"
|
141
|
+
describe "Scope:" do
|
142
|
+
# TODO "Map on all levels, starting at level" ant other about Infinity
|
143
|
+
describe "Properties & Relations:" do
|
144
|
+
# TODO #mapall
|
145
|
+
# TODO #mapthread ?
|
146
|
+
# TODO #mapindexed ?
|
147
|
+
# TODO "negative levels"
|
111
148
|
# TODO http://reference.wolfram.com/language/guide/ElementsOfLists.html
|
112
149
|
# TODO http://reference.wolfram.com/language/guide/RearrangingAndRestructuringLists.html
|
113
150
|
# TODO http://reference.wolfram.com/language/guide/MathematicalAndCountingOperationsOnLists.html
|
data/Rakefile
CHANGED
data/lib/mll.rb
CHANGED
@@ -1,77 +1,114 @@
|
|
1
1
|
module MLL
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def tally
|
6
|
+
lambda do |list, test = ->(i,j){ i == j } | # TODO implement #sameq ?
|
7
|
+
h = Hash.new{ 0 }
|
8
|
+
keys = []
|
9
|
+
list.each do |item|
|
10
|
+
h[item] += 1 if keys.each do |key|
|
11
|
+
if test[key, item]
|
12
|
+
h[key] += 1
|
13
|
+
break
|
14
|
+
end
|
15
|
+
end
|
16
|
+
keys << item
|
9
17
|
end
|
18
|
+
h
|
10
19
|
end
|
11
20
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
|
22
|
+
def nest_list
|
23
|
+
lambda do |f, expr, n|
|
24
|
+
Enumerator.new do |e|
|
25
|
+
e << expr
|
26
|
+
n.times do
|
27
|
+
e << expr = f.call(expr)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
# def self.nest *args
|
33
|
+
# nest_list(*args).last
|
34
|
+
# end
|
35
|
+
def nest
|
36
|
+
lambda do |f, expr, n|
|
37
|
+
n.times{ expr = f.call expr }
|
38
|
+
expr
|
39
|
+
end
|
20
40
|
end
|
21
|
-
end
|
22
41
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
def fold_list
|
43
|
+
lambda do |f, x, list = nil|
|
44
|
+
x, *list = x.to_a unless list
|
45
|
+
# TODO use Ruby#inject ?
|
46
|
+
Enumerator.new do |e|
|
47
|
+
e << x
|
48
|
+
list.each do |i|
|
49
|
+
e << x = f.call(x, i)
|
50
|
+
end
|
31
51
|
end
|
32
52
|
end
|
33
53
|
end
|
34
|
-
end
|
35
54
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
55
|
+
def map
|
56
|
+
# TODO validate depths
|
57
|
+
# TODO break on passing all depths
|
58
|
+
lambda do |f, list, depths = [1]|
|
59
|
+
depths = Range.new(*depths) if depths.size == 2
|
60
|
+
depths = Range.new(1,depths) if depths.is_a? Integer
|
61
|
+
g = lambda do |list, depth|
|
62
|
+
next list unless list.respond_to? :map
|
63
|
+
temp = list.lazy.map{ |i| g[i, depth + 1] }
|
64
|
+
temp = temp.map &f if depths.include? depth
|
65
|
+
temp
|
66
|
+
end
|
67
|
+
g[list, 1]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def table
|
72
|
+
lambda do |f, *args|
|
73
|
+
[].tap do |result|
|
74
|
+
[[result, args.map{ |r| # add lazy?
|
75
|
+
r.respond_to?(:map) && r.first.respond_to?(:map) ?
|
76
|
+
r.first : range[*r]
|
77
|
+
}]].tap do |stack|
|
78
|
+
stack.each do |ai, ri|
|
79
|
+
# TODO try to make #table lazy (Enumerator instead of Array)
|
80
|
+
# "no implicit conversion of Enumerator::Lazy into Array"
|
81
|
+
# "undefined method `replace' for #<Enumerator::Lazy: []>"
|
82
|
+
ai.replace ri.first.map{ |i|
|
83
|
+
if ri.size == 1
|
84
|
+
f.call(*ai, i)
|
85
|
+
else
|
86
|
+
[*ai.dup, i].tap{ |t| stack << [t, ri.drop(1)] }
|
87
|
+
end
|
88
|
+
}
|
89
|
+
end
|
54
90
|
end
|
55
91
|
end
|
56
92
|
end
|
57
93
|
end
|
58
|
-
end
|
59
94
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
95
|
+
def define_listable_function name, &block
|
96
|
+
(class << self; self end).class_eval do
|
97
|
+
define_method name do
|
98
|
+
lambda do |*args|
|
99
|
+
case args.map{ |i| i.respond_to? :map }
|
100
|
+
when [true] ; args.first.lazy.map &method(name).call
|
101
|
+
when [true, true] ; args.first.lazy.zip(args.last).map{ |i, j| send(name)[i, j] }
|
102
|
+
when [true, false] ; args.first.lazy.map{ |i| send(name)[i, args.last] }
|
103
|
+
when [false, true] ; args.last.lazy.map{ |i| send(name)[args.first, i] }
|
104
|
+
else
|
105
|
+
block.call *args
|
106
|
+
end
|
71
107
|
end
|
72
108
|
end
|
73
109
|
end
|
74
110
|
end
|
111
|
+
|
75
112
|
end
|
76
113
|
|
77
114
|
# TODO not sure if we need any other kind of Listability except of #range[[Array]]
|
@@ -98,6 +135,20 @@ module MLL
|
|
98
135
|
end
|
99
136
|
end
|
100
137
|
|
138
|
+
def self.subdivide
|
139
|
+
lambda do |*args|
|
140
|
+
case args.size
|
141
|
+
when 1 ; subdivide[1, args[0]]
|
142
|
+
when 2 ; subdivide[0, args[0], args[1]]
|
143
|
+
when 3
|
144
|
+
# raise ArgumentError.new("can't divide into 0 parts") if args[2].zero?
|
145
|
+
range[args[0], args[1], (args[1] - args[0]) * 1.0 / args[2]]
|
146
|
+
else
|
147
|
+
raise ArgumentError.new("wrong number of arguments (#{args.size} for 1..3)")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
101
152
|
define_listable_function(:subtract) { |*args| raise ArgumentError.new("need two arguments") unless args.size == 2 ; args[0] - args[1] }
|
102
153
|
define_listable_function(:divide) { |*args| raise ArgumentError.new("need two arguments") unless args.size == 2 ; args[0] / args[1] }
|
103
154
|
define_listable_function(:_plus) { |*args| raise ArgumentError.new("need two arguments") unless args.size == 2 ; args[0] + args[1] }
|
@@ -120,18 +171,4 @@ module MLL
|
|
120
171
|
define_orderless_function(:plus, 0) { |a, b| _plus.call a, b }
|
121
172
|
define_orderless_function(:times, 1) { |a, b| _times.call a, b }
|
122
173
|
|
123
|
-
def self.subdivide
|
124
|
-
lambda do |*args|
|
125
|
-
case args.size
|
126
|
-
when 1 ; subdivide[1, args[0]]
|
127
|
-
when 2 ; subdivide[0, args[0], args[1]]
|
128
|
-
when 3
|
129
|
-
# raise ArgumentError.new("can't divide into 0 parts") if args[2].zero?
|
130
|
-
range[args[0], args[1], (args[1] - args[0]) * 1.0 / args[2]]
|
131
|
-
else
|
132
|
-
raise ArgumentError.new("wrong number of arguments (#{args.size} for 1..3)")
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
174
|
end
|
data/mll.gemspec
CHANGED
data/spec/_spec.rb
CHANGED
@@ -38,7 +38,7 @@ describe MLL do
|
|
38
38
|
expect{ subtract[0,0,0] }.to raise_error ArgumentError
|
39
39
|
end
|
40
40
|
|
41
|
-
describe "Basic Examples" do
|
41
|
+
describe "Basic Examples:" do
|
42
42
|
|
43
43
|
example "subtract numbers" do
|
44
44
|
expect(subtract[10,3]).to eq 7
|
@@ -46,7 +46,7 @@ describe MLL do
|
|
46
46
|
|
47
47
|
end
|
48
48
|
|
49
|
-
describe "Scope" do
|
49
|
+
describe "Scope:" do
|
50
50
|
|
51
51
|
example "threads element‐wise over lists" do
|
52
52
|
expect(subtract[[1,2,3,4],0.5]).to be_a Enumerator
|
@@ -79,7 +79,7 @@ describe MLL do
|
|
79
79
|
expect{ divide[0,0,0] }.to raise_error ArgumentError
|
80
80
|
end
|
81
81
|
|
82
|
-
describe "Basic Examples" do
|
82
|
+
describe "Basic Examples:" do
|
83
83
|
|
84
84
|
example "divide numbers" do
|
85
85
|
expect(divide[77,11]).to eq 7
|
@@ -87,7 +87,7 @@ describe MLL do
|
|
87
87
|
|
88
88
|
end
|
89
89
|
|
90
|
-
describe "Scope" do
|
90
|
+
describe "Scope:" do
|
91
91
|
|
92
92
|
example "threads element‐wise over lists" do
|
93
93
|
expect(divide[[2,3,4,5],2.0]).to be_a Enumerator
|
@@ -108,7 +108,7 @@ describe MLL do
|
|
108
108
|
|
109
109
|
end
|
110
110
|
|
111
|
-
describe "Applications" do
|
111
|
+
describe "Applications:" do
|
112
112
|
|
113
113
|
example "successive ratios in a list" do
|
114
114
|
skip "waiting for Rationals to be used"
|
@@ -121,7 +121,7 @@ describe MLL do
|
|
121
121
|
# http://reference.wolfram.com/language/ref/Plus.html
|
122
122
|
describe "#plus" do
|
123
123
|
|
124
|
-
describe "Details" do
|
124
|
+
describe "Details:" do
|
125
125
|
|
126
126
|
example "#plus[] is taken to be 0" do
|
127
127
|
expect(plus[]).to eq 0
|
@@ -132,7 +132,7 @@ describe MLL do
|
|
132
132
|
|
133
133
|
end
|
134
134
|
|
135
|
-
describe "Basic Examples" do
|
135
|
+
describe "Basic Examples:" do
|
136
136
|
|
137
137
|
example "sums numbers" do
|
138
138
|
expect(plus[2,3,4]).to eq 9
|
@@ -149,7 +149,7 @@ describe MLL do
|
|
149
149
|
|
150
150
|
end
|
151
151
|
|
152
|
-
describe "Scope" do
|
152
|
+
describe "Scope:" do
|
153
153
|
|
154
154
|
example "threads element‐wise over lists" do
|
155
155
|
expect(plus[[10,20,30],[1,2,3]]).to be_a Enumerator
|
@@ -164,7 +164,7 @@ describe MLL do
|
|
164
164
|
|
165
165
|
end
|
166
166
|
|
167
|
-
describe "Possible Issues" do
|
167
|
+
describe "Possible Issues:" do
|
168
168
|
|
169
169
|
# idk why not in 'Properties & Relations'
|
170
170
|
example "accumulate makes a cumulative sum" do
|
@@ -179,7 +179,7 @@ describe MLL do
|
|
179
179
|
# http://reference.wolfram.com/language/ref/Times.html
|
180
180
|
describe "#times" do
|
181
181
|
|
182
|
-
describe "Details" do
|
182
|
+
describe "Details:" do
|
183
183
|
|
184
184
|
example "#times[] is taken to be 1" do
|
185
185
|
expect(times[]).to eq 1
|
@@ -190,7 +190,7 @@ describe MLL do
|
|
190
190
|
|
191
191
|
end
|
192
192
|
|
193
|
-
describe "Basic Examples" do
|
193
|
+
describe "Basic Examples:" do
|
194
194
|
|
195
195
|
example "multiplies numbers" do
|
196
196
|
expect(times[2,3,4]).to eq 24
|
@@ -206,7 +206,7 @@ describe MLL do
|
|
206
206
|
|
207
207
|
end
|
208
208
|
|
209
|
-
describe "Scope" do
|
209
|
+
describe "Scope:" do
|
210
210
|
|
211
211
|
example "threads element‐wise over lists" do
|
212
212
|
expect(times[[2,3],[4,5]]).to be_a Enumerator
|
@@ -236,7 +236,7 @@ describe MLL do
|
|
236
236
|
# http://reference.wolfram.com/language/ref/Table.html
|
237
237
|
describe "#table" do
|
238
238
|
|
239
|
-
describe "Details" do
|
239
|
+
describe "Details:" do
|
240
240
|
|
241
241
|
example "#table[expr,spec1,spec2] is effectively equivalent to #table[#table[expr,spec2],spec1]" do
|
242
242
|
expect(table[->(i,j){ [i,j] }, 2, 3]).to eq table[->(i){ table[->(j){ [i,j] }, 3] }, 2]
|
@@ -244,7 +244,7 @@ describe MLL do
|
|
244
244
|
|
245
245
|
end
|
246
246
|
|
247
|
-
describe "Basic Examples" do
|
247
|
+
describe "Basic Examples:" do
|
248
248
|
|
249
249
|
example "a table of the first 10 squares" do
|
250
250
|
expect(table[->(i){ i**2 }, 10]).to be_a Array
|
@@ -271,7 +271,7 @@ describe MLL do
|
|
271
271
|
]
|
272
272
|
end
|
273
273
|
|
274
|
-
describe "Scope" do
|
274
|
+
describe "Scope:" do
|
275
275
|
|
276
276
|
# TODO: "Make a triangular array:"
|
277
277
|
|
@@ -284,7 +284,7 @@ describe MLL do
|
|
284
284
|
|
285
285
|
end
|
286
286
|
|
287
|
-
describe "Applications" do
|
287
|
+
describe "Applications:" do
|
288
288
|
|
289
289
|
example "column table(binomial, )" do
|
290
290
|
skip "#binomial and #column are yet to be implemented"
|
@@ -309,7 +309,7 @@ describe MLL do
|
|
309
309
|
expect{ range[1,2,0] }.to raise_error ArgumentError
|
310
310
|
end
|
311
311
|
|
312
|
-
describe "Details" do
|
312
|
+
describe "Details:" do
|
313
313
|
|
314
314
|
example "the arguments need not be integers" do
|
315
315
|
expect(range[0.25,2.9,1.25]).to be_a Enumerator
|
@@ -318,7 +318,7 @@ describe MLL do
|
|
318
318
|
|
319
319
|
end
|
320
320
|
|
321
|
-
describe "Basic Examples" do
|
321
|
+
describe "Basic Examples:" do
|
322
322
|
|
323
323
|
example "range(n)" do
|
324
324
|
expect(range[4]).to be_a Enumerator
|
@@ -344,7 +344,7 @@ describe MLL do
|
|
344
344
|
expect(range[3,1,-1].to_a).to eq [3,2,1]
|
345
345
|
end
|
346
346
|
|
347
|
-
describe "Generalizations & Extensions" do
|
347
|
+
describe "Generalizations & Extensions:" do
|
348
348
|
|
349
349
|
example "use a list of range specifications" do
|
350
350
|
expect(range[[5,2,6,3]]).to be_a Enumerator
|
@@ -356,7 +356,7 @@ describe MLL do
|
|
356
356
|
|
357
357
|
end
|
358
358
|
|
359
|
-
describe "Applications" do
|
359
|
+
describe "Applications:" do
|
360
360
|
|
361
361
|
example "produce a geometric sequence" do
|
362
362
|
skip "#power is yet to be implemented"
|
@@ -366,7 +366,7 @@ describe MLL do
|
|
366
366
|
|
367
367
|
end
|
368
368
|
|
369
|
-
describe "Properties & Relations" do
|
369
|
+
describe "Properties & Relations:" do
|
370
370
|
|
371
371
|
example "#range[imin,imax,di] is equivalent to #table[i,[imin,imax,di]]" do
|
372
372
|
expect(range[2,8,3].to_a).to eq table[->(i){ i }, [2,8,3]]
|
@@ -386,7 +386,7 @@ describe MLL do
|
|
386
386
|
expect(range[1..3].to_a.map(&:to_a)).to eq [[1],[1,2],[1,2,3]]
|
387
387
|
end
|
388
388
|
|
389
|
-
describe "Neat Examples" do
|
389
|
+
describe "Neat Examples:" do
|
390
390
|
|
391
391
|
example "make nested ranges" do
|
392
392
|
range[range[range[3]]].tap do |o|
|
@@ -418,7 +418,7 @@ describe MLL do
|
|
418
418
|
# expect{ subdivide[0] }.to raise_error ArgumentError
|
419
419
|
# end
|
420
420
|
|
421
|
-
describe "Details" do
|
421
|
+
describe "Details:" do
|
422
422
|
|
423
423
|
example "generates a list of length n+1" do
|
424
424
|
expect(subdivide[5]).to be_a Enumerator
|
@@ -427,7 +427,7 @@ describe MLL do
|
|
427
427
|
|
428
428
|
end
|
429
429
|
|
430
|
-
describe "Basic Examples" do
|
430
|
+
describe "Basic Examples:" do
|
431
431
|
|
432
432
|
example "subdivide the unit interval into 4 equal parts" do
|
433
433
|
expect(subdivide[4]).to be_a Enumerator
|
@@ -450,7 +450,7 @@ describe MLL do
|
|
450
450
|
|
451
451
|
end
|
452
452
|
|
453
|
-
describe "Properties & Relations" do
|
453
|
+
describe "Properties & Relations:" do
|
454
454
|
|
455
455
|
example "subdivide[xmin,xmax,n] is equivalent to xmin+(xmax-xmin)Range[0,n]/n" do
|
456
456
|
expect(subdivide[2,10,4].to_a).to eq plus[2,divide[times[10-2,range[0,4]],4]].to_a
|
@@ -468,7 +468,7 @@ describe MLL do
|
|
468
468
|
expect(nest_list[->(*args){}, 0, 5].to_a.size).to eq 6
|
469
469
|
end
|
470
470
|
|
471
|
-
describe "Basic Examples" do
|
471
|
+
describe "Basic Examples:" do
|
472
472
|
|
473
473
|
example "???" do
|
474
474
|
skip "#cos (or #sqrt or anything unar is yet to be implemented"
|
@@ -476,7 +476,7 @@ describe MLL do
|
|
476
476
|
|
477
477
|
end
|
478
478
|
|
479
|
-
describe "Scope" do
|
479
|
+
describe "Scope:" do
|
480
480
|
|
481
481
|
example "nesting can return a single number" do
|
482
482
|
skip "#sqrt is yet to be implemented"
|
@@ -484,7 +484,7 @@ describe MLL do
|
|
484
484
|
|
485
485
|
end
|
486
486
|
|
487
|
-
describe "Applications" do
|
487
|
+
describe "Applications:" do
|
488
488
|
|
489
489
|
example "powers of 2" do
|
490
490
|
expect(nest_list[->(i){ 2*i }, 1, 10]).to be_a Enumerator
|
@@ -500,7 +500,7 @@ describe MLL do
|
|
500
500
|
end
|
501
501
|
example "random walk" do
|
502
502
|
expect(( r = Random.new(0); nest_list[->(i){ i+[-1,1][r.rand(2)] }, 0, 20] )).to be_a Enumerator
|
503
|
-
expect(( r = Random.new(0); nest_list[->(i){ i+[-1,1][r.rand(2)] }, 0, 20].to_a
|
503
|
+
expect(( r = Random.new(0); nest_list[->(i){ i+[-1,1][r.rand(2)] }, 0, 20] ).to_a).to eq [0,-1,0,1,0,1,2,3,4,5,6,7,6,5,6,5,4,3,2,1,2]
|
504
504
|
end
|
505
505
|
example "successively rotate a list" do
|
506
506
|
expect(nest_list[->(i){ i.rotate 1 }, [1,2,3,4], 4]).to be_a Enumerator
|
@@ -509,7 +509,7 @@ describe MLL do
|
|
509
509
|
|
510
510
|
end
|
511
511
|
|
512
|
-
describe "Properties & Relations" do
|
512
|
+
describe "Properties & Relations:" do
|
513
513
|
|
514
514
|
example "#nest gives the last element of #nest_list" do
|
515
515
|
expect(nest_list[->(i){ i*2 }, 3, 4].to_a.last).to eq nest[->(i){ i*2 }, 3, 4]
|
@@ -536,7 +536,7 @@ describe MLL do
|
|
536
536
|
# http://reference.wolfram.com/language/ref/FoldList.html
|
537
537
|
describe "#fold_list" do
|
538
538
|
|
539
|
-
describe "Details" do
|
539
|
+
describe "Details:" do
|
540
540
|
|
541
541
|
example "with a length n list, #fold_list generates a list of length n+1" do
|
542
542
|
skip "waiting got Wolfram team to fix the reported bug"
|
@@ -548,7 +548,7 @@ describe MLL do
|
|
548
548
|
|
549
549
|
end
|
550
550
|
|
551
|
-
describe "Basic Examples" do
|
551
|
+
describe "Basic Examples:" do
|
552
552
|
|
553
553
|
example "cumulative sums of the elements of the list" do
|
554
554
|
expect(fold_list[plus,5,[1,2,3,4]]).to be_a Enumerator
|
@@ -565,12 +565,12 @@ describe MLL do
|
|
565
565
|
|
566
566
|
end
|
567
567
|
|
568
|
-
describe "Applications" do
|
568
|
+
describe "Applications:" do
|
569
569
|
|
570
570
|
# TODO maybe move it to README.md
|
571
571
|
example "generate a random walk" do
|
572
572
|
expect(( r = Random.new(0); fold_list[plus, 0, Array.new(20){ [-1,1][r.rand(2)] }] )).to be_a Enumerator
|
573
|
-
expect(( r = Random.new(0); fold_list[plus, 0, Array.new(20){ [-1,1][r.rand(2)] }].to_a
|
573
|
+
expect(( r = Random.new(0); fold_list[plus, 0, Array.new(20){ [-1,1][r.rand(2)] }] ).to_a).to eq [0,-1,0,1,0,1,2,3,4,5,6,7,6,5,6,5,4,3,2,1,2]
|
574
574
|
end
|
575
575
|
|
576
576
|
example "find successively deeper parts in an expression" do
|
@@ -580,7 +580,7 @@ describe MLL do
|
|
580
580
|
|
581
581
|
end
|
582
582
|
|
583
|
-
describe "Properties & Relations" do
|
583
|
+
describe "Properties & Relations:" do
|
584
584
|
|
585
585
|
example "makes a list of length n+1" do
|
586
586
|
expect(fold_list[->{}, 0, [*1..10]]).to be_a Enumerator
|
@@ -601,7 +601,7 @@ describe MLL do
|
|
601
601
|
|
602
602
|
end
|
603
603
|
|
604
|
-
describe "Neat Examples" do
|
604
|
+
describe "Neat Examples:" do
|
605
605
|
|
606
606
|
example "compute the minimum number of coins of different value needed to make up an amount" do
|
607
607
|
skip "at least #mod is yet to be implemented"
|
@@ -611,6 +611,85 @@ describe MLL do
|
|
611
611
|
|
612
612
|
end
|
613
613
|
|
614
|
+
# http://reference.wolfram.com/language/ref/Map.html
|
615
|
+
describe "#map" do
|
616
|
+
|
617
|
+
# TODO we'll need less nested mappings when we implement stop on depths depletion
|
618
|
+
|
619
|
+
describe "Details and Options:" do
|
620
|
+
|
621
|
+
example "levels n1 though n2" do
|
622
|
+
expect(map[->(i){ [i] }, [1,[2,[3,[4,[5,6]]]]], [2,4]]).to be_a Enumerator
|
623
|
+
expect(map[->(i){ [i] }, [1,[2,[3,[4,[5,6]]]]], [2,4]].
|
624
|
+
to_a.map{ |i| i.respond_to?(:to_a) ? i.
|
625
|
+
to_a.map{ |i| i.respond_to?(:to_a) ? i.
|
626
|
+
to_a.map{ |i| i.respond_to?(:to_a) ? i.
|
627
|
+
to_a.map{ |i| i.respond_to?(:to_a) ? i.
|
628
|
+
to_a.map{ |i| i.respond_to?(:to_a) ? i.
|
629
|
+
to_a.map{ |i| i.respond_to?(:to_a) ? i.
|
630
|
+
to_a.map{ |i| i.respond_to?(:to_a) ? i.to_a : i } : i } : i } : i } : i } : i } : i }
|
631
|
+
# TODO smth _<>
|
632
|
+
).to eq [1,[[2],[[[3],[[[4],[[5,6]]]]]]]]
|
633
|
+
end
|
634
|
+
|
635
|
+
# TODO "Level corresponds to the whole expression"
|
636
|
+
# TODO currying "Map[f][expr] is equivalent to Map[f,expr]"
|
637
|
+
|
638
|
+
end
|
639
|
+
|
640
|
+
describe "Basic Examples:" do
|
641
|
+
|
642
|
+
example "???" do
|
643
|
+
expect(map[range, [1,2,3]]).to be_a Enumerator
|
644
|
+
expect(map[range, [1,2,3]].to_a.map(&:to_a)).to eq [[1],[1,2],[1,2,3]]
|
645
|
+
end
|
646
|
+
example "use explicit pure functions" do
|
647
|
+
expect(map[->(i){ i**2 }, [1,2,3,4]]).to be_a Enumerator
|
648
|
+
expect(map[->(i){ i**2 }, [1,2,3,4]].to_a).to eq [1,4,9,16]
|
649
|
+
end
|
650
|
+
example "map at top level" do
|
651
|
+
expect(map[->(i){ [i] }, [[1,2],[3,4,5]]]).to be_a Enumerator
|
652
|
+
expect(map[->(i){ [i] }, [[1,2],[3,4,5]]].to_a.map{ |i| i.to_a.map &:to_a }).to eq [[[1,2]],[[3,4,5]]]
|
653
|
+
end
|
654
|
+
example "map at level 2" do
|
655
|
+
expect(map[->(i){ [i] }, [[1,2],[3,4,5]], [2]]).to be_a Enumerator
|
656
|
+
expect(map[->(i){ [i] }, [[1,2],[3,4,5]], [2]].to_a.map(&:to_a)).to eq [[[1],[2]],[[3],[4],[5]]]
|
657
|
+
end
|
658
|
+
example "map at levels 1 and 2" do
|
659
|
+
expect(map[->(i){ [i] }, [[1,2],[3,4,5]], 2]).to be_a Enumerator
|
660
|
+
expect(map[->(i){ [i] }, [[1,2],[3,4,5]], 2].to_a.map{ |i| i.to_a.map(&:to_a) }).to eq [[[[1],[2]]],[[[3],[4],[5]]]]
|
661
|
+
end
|
662
|
+
|
663
|
+
end
|
664
|
+
|
665
|
+
describe "Scope:" do
|
666
|
+
# TODO "Map on all levels, starting at level" ant other about Infinity
|
667
|
+
end
|
668
|
+
|
669
|
+
describe "Properties & Relations:" do
|
670
|
+
|
671
|
+
example "leaves are visited before roots" do
|
672
|
+
skip "waiting for infinite map to be implemented"
|
673
|
+
log = []
|
674
|
+
map[log.method(:<<), [[1,2],[3,4,5]]]
|
675
|
+
expect(log).to eq [1,2,[1,2],3,4,5,[3,4,5],[[1,2],[3,4,5]]]
|
676
|
+
end
|
677
|
+
|
678
|
+
# TODO #mapall
|
679
|
+
|
680
|
+
# TODO #mapthread ?
|
681
|
+
# TODO #mapindexed ?
|
682
|
+
|
683
|
+
# TODO "negative levels"
|
684
|
+
|
685
|
+
example "#scan does the same as #map, but without returning a result" do
|
686
|
+
skip "#scan is yet to be implemented"
|
687
|
+
end
|
688
|
+
|
689
|
+
end
|
690
|
+
|
691
|
+
end
|
692
|
+
|
614
693
|
end
|
615
694
|
|
616
695
|
# TODO http://reference.wolfram.com/language/guide/ElementsOfLists.html
|
@@ -630,7 +709,7 @@ describe MLL do
|
|
630
709
|
# http://reference.wolfram.com/language/ref/Nest.html
|
631
710
|
describe "#nest" do
|
632
711
|
|
633
|
-
describe "Basic Examples" do
|
712
|
+
describe "Basic Examples:" do
|
634
713
|
|
635
714
|
example "the function to nest can be a pure function" do
|
636
715
|
expect(nest[->(i){ (1+i)**2 }, 1, 3]).to eq 676
|
@@ -638,7 +717,7 @@ describe MLL do
|
|
638
717
|
|
639
718
|
end
|
640
719
|
|
641
|
-
describe "Scope" do
|
720
|
+
describe "Scope:" do
|
642
721
|
|
643
722
|
example "nesting can return a single number" do
|
644
723
|
skip "#sqrt is yet to be implemented"
|
@@ -646,7 +725,7 @@ describe MLL do
|
|
646
725
|
|
647
726
|
end
|
648
727
|
|
649
|
-
describe "Applications" do
|
728
|
+
describe "Applications:" do
|
650
729
|
|
651
730
|
example "newton iterations for" do
|
652
731
|
skip "waiting for Rationals to be used"
|
@@ -657,7 +736,7 @@ describe MLL do
|
|
657
736
|
|
658
737
|
end
|
659
738
|
|
660
|
-
describe "Properties & Relations" do
|
739
|
+
describe "Properties & Relations:" do
|
661
740
|
|
662
741
|
example "Ruby#inject automatically inserts second arguments from a list" do
|
663
742
|
expect(nest[->(i){ i*2 }, 3, 4]).to eq ([2]*4).inject(3){ |i,j| i*j }
|
@@ -673,6 +752,55 @@ describe MLL do
|
|
673
752
|
|
674
753
|
end
|
675
754
|
|
755
|
+
# http://reference.wolfram.com/language/guide/NumericalData.html
|
756
|
+
describe "Numerical Data" do
|
757
|
+
|
758
|
+
# http://reference.wolfram.com/language/ref/Tally.html
|
759
|
+
describe "#tally" do
|
760
|
+
|
761
|
+
describe "Details:" do
|
762
|
+
|
763
|
+
example "#tally[list] is equivalent to #tally[list,#sameq]" do
|
764
|
+
skip "#sameq is yet to be implemented"
|
765
|
+
end
|
766
|
+
|
767
|
+
end
|
768
|
+
|
769
|
+
describe "Basic Examples:" do
|
770
|
+
|
771
|
+
example "obtain tallies for a list" do
|
772
|
+
expect(tally[[1, 1, 2, 1, 3, 2, 1]]).to be_a Hash
|
773
|
+
expect(tally[[1, 1, 2, 1, 3, 2, 1]]).to eq({1=>4, 2=>2, 3=>1})
|
774
|
+
end
|
775
|
+
|
776
|
+
example "use test argument to count elements with the same class" do
|
777
|
+
expect(tally[[[1,2], [1,2,3,4], 1, [1,2,3,4], 1], ->(i,j){ i.class == j.class }]).to be_a Hash
|
778
|
+
expect(tally[[[1,2], [1,2,3,4], 1, [1,2,3,4], 1], ->(i,j){ i.class == j.class }]).to eq({[1,2]=>3, 1=>2})
|
779
|
+
end
|
780
|
+
|
781
|
+
example "count the instances of randomly generated integers" do
|
782
|
+
expect(( r = Random.new(0); tally[Array.new(50){ r.rand 10 }] )).to be_a Hash
|
783
|
+
expect(( r = Random.new(0); tally[Array.new(50){ r.rand 10 }] )).to eq({5=>4, 0=>6, 3=>10, 7=>7, 9=>5, 2=>4, 4=>3, 6=>2, 8=>5, 1=>4})
|
784
|
+
end
|
785
|
+
|
786
|
+
end
|
787
|
+
|
788
|
+
describe "Properties & Relations:" do
|
789
|
+
|
790
|
+
example "elements with highest frequencies are given by #commonest" do
|
791
|
+
skip "#commonest is yet to be implemented"
|
792
|
+
end
|
793
|
+
|
794
|
+
example "#tally is a discrete analog of #bincounts" do
|
795
|
+
skip "#bincounts is yet to be implemented"
|
796
|
+
end
|
797
|
+
|
798
|
+
end
|
799
|
+
|
800
|
+
end
|
801
|
+
|
802
|
+
end
|
803
|
+
|
676
804
|
end
|
677
805
|
|
678
806
|
# TODO http://reference.wolfram.com/language/guide/HandlingArraysOfData.html
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mll
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Maslov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|