1
2
3
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
56
57
58
59
60
61
62
63
64
65
66
67
68
|
local List = require 'pl.List'
local class = require 'pl.class'
local test = require 'pl.test'
local asserteq, T = test.asserteq, test.tuple
-- note that a _plain table_ is made directly into a list
local t = {10,20,30}
local ls = List(t)
asserteq(t,ls)
asserteq(List({}):reverse(), {})
asserteq(List({1}):reverse(), {1})
asserteq(List({1,2}):reverse(), {2,1})
asserteq(List({1,2,3}):reverse(), {3,2,1})
asserteq(List({1,2,3,4}):reverse(), {4,3,2,1})
-- you may derive classes from pl.List, and the result is covariant.
-- That is, slice() etc will return a list of the derived type, not List.
local NA = class(List)
local function mapm(a1,op,a2)
local M = type(a2)=='table' and List.map2 or List.map
return M(a1,op,a2)
end
--- elementwise arithmetric operations
function NA.__unm(a) return a:map '|X|-X' end
function NA.__pow(a,s) return a:map '|X,Y|X^Y' end
function NA.__add(a1,a2) return mapm(a1,'|X,Y|X+Y',a2) end
function NA.__sub(a1,a2) return mapm(a1,'|X,Y|X-Y',a2) end
function NA.__div(a1,a2) return mapm(a1,'|X,Y|X/Y',a2) end
function NA.__mul(a1,a2) return mapm(a2,'|X,Y|X*Y',a1) end
function NA:minmax ()
local min,max = math.huge,-math.huge
for i = 1,#self do
local val = self[i]
if val > max then max = val end
if val < min then min = val end
end
return min,max
end
function NA:sum ()
local res = 0
for i = 1,#self do
res = res + self[i]
end
return res
end
function NA:normalize ()
return self:transform('|X,Y|X/Y',self:sum())
end
n1 = NA{10,20,30}
n2 = NA{1,2,3}
ns = n1 + 2*n2
asserteq(List:class_of(ns),true)
asserteq(NA:class_of(ns),true)
asserteq(ns:is_a(NA),true)
asserteq(ns,{12,24,36})
min,max = ns:slice(1,2):minmax()
asserteq(T(min,max),T(12,24))
asserteq(n1:normalize():sum(),1,1e-8)
|