mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: replace generic <>
with []
- part 2 (#16536)
This commit is contained in:
parent
b19b97e7b1
commit
ef5be22f81
@ -125,7 +125,7 @@ fn main() {
|
||||
}
|
||||
// webhook server mode
|
||||
if flag_options.serve {
|
||||
vweb.run<WebhookServer>(&WebhookServer{}, flag_options.port)
|
||||
vweb.run[WebhookServer](&WebhookServer{}, flag_options.port)
|
||||
} else {
|
||||
// cmd mode
|
||||
mut gen_vc := new_gen_vc(flag_options)
|
||||
|
@ -336,7 +336,7 @@ fn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr {
|
||||
}
|
||||
tls_bench.no_cstep = true
|
||||
tls_bench.njobs = ts.benchmark.njobs
|
||||
mut relative_file := os.real_path(p.get_item<string>(idx))
|
||||
mut relative_file := os.real_path(p.get_item[string](idx))
|
||||
mut cmd_options := [ts.vargs]
|
||||
mut run_js := false
|
||||
|
||||
|
@ -109,23 +109,23 @@ fn defer_fn() {
|
||||
}
|
||||
|
||||
// generic function
|
||||
fn g_fn<T>(p T) T {
|
||||
fn g_fn[T](p T) T {
|
||||
return p
|
||||
}
|
||||
|
||||
// generic struct
|
||||
struct GenericStruct<T> {
|
||||
struct GenericStruct[T] {
|
||||
point Point
|
||||
mut:
|
||||
model T
|
||||
}
|
||||
|
||||
// generic interface
|
||||
interface Gettable<T> {
|
||||
interface Gettable[T] {
|
||||
get() T
|
||||
}
|
||||
|
||||
// generic sumtype
|
||||
struct None {}
|
||||
|
||||
type MyOption<T> = Error | None | T
|
||||
type MyOption[T] = Error | None | T
|
||||
|
@ -228,7 +228,7 @@ fn (t Tree) token_node(tok_kind token.Kind) &Node {
|
||||
}
|
||||
|
||||
// enum type node
|
||||
fn (t Tree) enum_node<T>(value T) &Node {
|
||||
fn (t Tree) enum_node[T](value T) &Node {
|
||||
return t.string_node('enum:${int(value)}(${value})')
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ fn (vd VDoc) work_processor(mut work sync.Channel, mut wg sync.WaitGroup) {
|
||||
|
||||
fn (vd VDoc) render_parallel(out Output) {
|
||||
vjobs := runtime.nr_jobs()
|
||||
mut work := sync.new_channel<ParallelDoc>(u32(vd.docs.len))
|
||||
mut work := sync.new_channel[ParallelDoc](u32(vd.docs.len))
|
||||
mut wg := sync.new_waitgroup()
|
||||
for i in 0 .. vd.docs.len {
|
||||
p_doc := ParallelDoc{vd.docs[i], out}
|
||||
|
14
doc/docs.md
14
doc/docs.md
@ -2719,10 +2719,10 @@ In general, V's references are similar to Go pointers and C++ references.
|
||||
For example, a generic tree structure definition would look like this:
|
||||
|
||||
```v
|
||||
struct Node<T> {
|
||||
struct Node[T] {
|
||||
val T
|
||||
left &Node<T>
|
||||
right &Node<T>
|
||||
left &Node[T]
|
||||
right &Node[T]
|
||||
}
|
||||
```
|
||||
|
||||
@ -3787,7 +3787,7 @@ receiver argument `r` uses a generic type `T`.
|
||||
|
||||
Another example:
|
||||
```v
|
||||
fn compare<T>(a T, b T) int {
|
||||
fn compare[T](a T, b T) int {
|
||||
if a < b {
|
||||
return -1
|
||||
}
|
||||
@ -3797,15 +3797,15 @@ fn compare<T>(a T, b T) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// compare<int>
|
||||
// compare[int]
|
||||
println(compare(1, 0)) // Outputs: 1
|
||||
println(compare(1, 1)) // 0
|
||||
println(compare(1, 2)) // -1
|
||||
// compare<string>
|
||||
// compare[string]
|
||||
println(compare('1', '0')) // Outputs: 1
|
||||
println(compare('1', '1')) // 0
|
||||
println(compare('1', '2')) // -1
|
||||
// compare<f64>
|
||||
// compare[f64]
|
||||
println(compare(1.1, 1.0)) // Outputs: 1
|
||||
println(compare(1.1, 1.1)) // 0
|
||||
println(compare(1.1, 1.2)) // -1
|
||||
|
@ -2,38 +2,38 @@
|
||||
|
||||
struct Empty {}
|
||||
|
||||
struct Node<T> {
|
||||
struct Node[T] {
|
||||
value T
|
||||
left Tree<T>
|
||||
right Tree<T>
|
||||
left Tree[T]
|
||||
right Tree[T]
|
||||
}
|
||||
|
||||
type Tree<T> = Empty | Node<T>
|
||||
type Tree[T] = Empty | Node[T]
|
||||
|
||||
// return size(number of nodes) of BST
|
||||
fn (tree Tree<T>) size<T>() int {
|
||||
fn (tree Tree[T]) size[T]() int {
|
||||
return match tree {
|
||||
Empty { 0 }
|
||||
Node<T> { 1 + tree.left.size() + tree.right.size() }
|
||||
Node[T] { 1 + tree.left.size() + tree.right.size() }
|
||||
}
|
||||
}
|
||||
|
||||
// insert a value to BST
|
||||
fn (tree Tree<T>) insert<T>(x T) Tree<T> {
|
||||
fn (tree Tree[T]) insert[T](x T) Tree[T] {
|
||||
return match tree {
|
||||
Empty {
|
||||
Node<T>{x, tree, tree}
|
||||
Node[T]{x, tree, tree}
|
||||
}
|
||||
Node<T> {
|
||||
Node[T] {
|
||||
if x == tree.value {
|
||||
tree
|
||||
} else if x < tree.value {
|
||||
Node<T>{
|
||||
Node[T]{
|
||||
...tree
|
||||
left: tree.left.insert(x)
|
||||
}
|
||||
} else {
|
||||
Node<T>{
|
||||
Node[T]{
|
||||
...tree
|
||||
right: tree.right.insert(x)
|
||||
}
|
||||
@ -43,12 +43,12 @@ fn (tree Tree<T>) insert<T>(x T) Tree<T> {
|
||||
}
|
||||
|
||||
// whether able to find a value in BST
|
||||
fn (tree Tree<T>) search<T>(x T) bool {
|
||||
fn (tree Tree[T]) search[T](x T) bool {
|
||||
return match tree {
|
||||
Empty {
|
||||
false
|
||||
}
|
||||
Node<T> {
|
||||
Node[T] {
|
||||
if x == tree.value {
|
||||
true
|
||||
} else if x < tree.value {
|
||||
@ -61,12 +61,12 @@ fn (tree Tree<T>) search<T>(x T) bool {
|
||||
}
|
||||
|
||||
// find the minimal value of a BST
|
||||
fn (tree Tree<T>) min<T>() T {
|
||||
fn (tree Tree[T]) min[T]() T {
|
||||
return match tree {
|
||||
Empty {
|
||||
T(1e9)
|
||||
}
|
||||
Node<T> {
|
||||
Node[T] {
|
||||
if tree.value < tree.left.min() {
|
||||
tree.value
|
||||
} else {
|
||||
@ -77,25 +77,25 @@ fn (tree Tree<T>) min<T>() T {
|
||||
}
|
||||
|
||||
// delete a value in BST (if nonexistant do nothing)
|
||||
fn (tree Tree<T>) delete<T>(x T) Tree<T> {
|
||||
fn (tree Tree[T]) delete[T](x T) Tree[T] {
|
||||
return match tree {
|
||||
Empty {
|
||||
tree
|
||||
}
|
||||
Node<T> {
|
||||
Node[T] {
|
||||
if tree.left !is Empty && tree.right !is Empty {
|
||||
if x < tree.value {
|
||||
Node<T>{
|
||||
Node[T]{
|
||||
...tree
|
||||
left: tree.left.delete(x)
|
||||
}
|
||||
} else if x > tree.value {
|
||||
Node<T>{
|
||||
Node[T]{
|
||||
...tree
|
||||
right: tree.right.delete(x)
|
||||
}
|
||||
} else {
|
||||
Node<T>{
|
||||
Node[T]{
|
||||
...tree
|
||||
value: tree.right.min()
|
||||
right: tree.right.delete(tree.right.min())
|
||||
@ -105,7 +105,7 @@ fn (tree Tree<T>) delete<T>(x T) Tree<T> {
|
||||
if x == tree.value {
|
||||
tree.left
|
||||
} else {
|
||||
Node<T>{
|
||||
Node[T]{
|
||||
...tree
|
||||
left: tree.left.delete(x)
|
||||
}
|
||||
@ -114,7 +114,7 @@ fn (tree Tree<T>) delete<T>(x T) Tree<T> {
|
||||
if x == tree.value {
|
||||
tree.right
|
||||
} else {
|
||||
Node<T>{
|
||||
Node[T]{
|
||||
...tree
|
||||
right: tree.right.delete(x)
|
||||
}
|
||||
@ -125,7 +125,7 @@ fn (tree Tree<T>) delete<T>(x T) Tree<T> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut tree := Tree<f64>(Empty{})
|
||||
mut tree := Tree[f64](Empty{})
|
||||
vals := [0.2, 0.0, 0.5, 0.3, 0.6, 0.8, 0.9, 1.0, 0.1, 0.4, 0.7]
|
||||
for i in vals {
|
||||
tree = tree.insert(i)
|
||||
|
@ -15,7 +15,7 @@ fn (a KeyVal) < (b KeyVal) bool {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut bst := datatypes.BSTree<KeyVal>{}
|
||||
mut bst := datatypes.BSTree[KeyVal]{}
|
||||
bst.insert(KeyVal{ key: 1, val: 12 })
|
||||
println(bst.in_order_traversal())
|
||||
|
||||
|
@ -7,11 +7,11 @@ struct User {
|
||||
|
||||
fn main() {
|
||||
data := 'name=Alice\nage=18'
|
||||
user := decode<User>(data)
|
||||
user := decode[User](data)
|
||||
println(user)
|
||||
}
|
||||
|
||||
fn decode<T>(data string) T {
|
||||
fn decode[T](data string) T {
|
||||
mut result := T{}
|
||||
// compile-time `for` loop
|
||||
// T.fields gives an array of a field metadata type
|
||||
|
@ -23,7 +23,7 @@ mut:
|
||||
|
||||
// building a map of with all edges etc of a graph, represented from a matrix adjacency
|
||||
// Input: matrix adjacency --> Output: edges list of src, dest and weight
|
||||
fn build_map_edges_from_graph<T>(g [][]T) map[T]EDGE {
|
||||
fn build_map_edges_from_graph[T](g [][]T) map[T]EDGE {
|
||||
n := g.len // TOTAL OF NODES for this graph -- its dimmension
|
||||
mut edges_map := map[int]EDGE{} // a graph represented by map of edges
|
||||
|
||||
@ -52,7 +52,7 @@ fn print_sol(dist []int) {
|
||||
// The main function that finds shortest distances from src
|
||||
// to all other vertices using Bellman-Ford algorithm. The
|
||||
// function also detects negative weight cycle
|
||||
fn bellman_ford<T>(graph [][]T, src int) {
|
||||
fn bellman_ford[T](graph [][]T, src int) {
|
||||
mut edges := build_map_edges_from_graph(graph)
|
||||
// this function was done to adapt a graph representation
|
||||
// by a adjacency matrix, to list of adjacency (using a MAP)
|
||||
|
@ -36,7 +36,7 @@ mut:
|
||||
|
||||
// Function to push according to priority ... the lower priority is goes ahead
|
||||
// The "push" always sorted in pq
|
||||
fn push_pq<T>(mut prior_queue []T, data int, priority int) {
|
||||
fn push_pq[T](mut prior_queue []T, data int, priority int) {
|
||||
mut temp := []T{}
|
||||
lenght_pq := prior_queue.len
|
||||
|
||||
@ -57,7 +57,7 @@ fn push_pq<T>(mut prior_queue []T, data int, priority int) {
|
||||
}
|
||||
|
||||
// Change the priority of a value/node ... exist a value, change its priority
|
||||
fn updating_priority<T>(mut prior_queue []T, search_data int, new_priority int) {
|
||||
fn updating_priority[T](mut prior_queue []T, search_data int, new_priority int) {
|
||||
mut i := 0
|
||||
mut lenght_pq := prior_queue.len
|
||||
|
||||
@ -76,7 +76,7 @@ fn updating_priority<T>(mut prior_queue []T, search_data int, new_priority int)
|
||||
}
|
||||
|
||||
// a single departure or remove from queue
|
||||
fn departure_priority<T>(mut prior_queue []T) int {
|
||||
fn departure_priority[T](mut prior_queue []T) int {
|
||||
mut x := prior_queue[0].data
|
||||
prior_queue.delete(0) // or .delete_many(0, 1 )
|
||||
return x
|
||||
@ -84,7 +84,7 @@ fn departure_priority<T>(mut prior_queue []T) int {
|
||||
|
||||
// give a NODE v, return a list with all adjacents
|
||||
// Take care, only positive EDGES
|
||||
fn all_adjacents<T>(g [][]T, v int) []int {
|
||||
fn all_adjacents[T](g [][]T, v int) []int {
|
||||
mut temp := []int{}
|
||||
for i in 0 .. (g.len) {
|
||||
if g[v][i] > 0 {
|
||||
@ -95,7 +95,7 @@ fn all_adjacents<T>(g [][]T, v int) []int {
|
||||
}
|
||||
|
||||
// print the costs from origin up to all nodes
|
||||
fn print_solution<T>(dist []T) {
|
||||
fn print_solution[T](dist []T) {
|
||||
print('Vertex \tDistance from Source')
|
||||
for node in 0 .. (dist.len) {
|
||||
print('\n ${node} ==> \t ${dist[node]}')
|
||||
@ -103,7 +103,7 @@ fn print_solution<T>(dist []T) {
|
||||
}
|
||||
|
||||
// print all paths and their cost or weight
|
||||
fn print_paths_dist<T>(path []T, dist []T) {
|
||||
fn print_paths_dist[T](path []T, dist []T) {
|
||||
print('\n Read the nodes from right to left (a path): \n')
|
||||
|
||||
for node in 1 .. (path.len) {
|
||||
|
@ -30,7 +30,7 @@ mut:
|
||||
|
||||
// Function to push according to priority ... the lower priority is goes ahead
|
||||
// The "push" always sorted in pq
|
||||
fn push_pq<T>(mut prior_queue []T, data int, priority int) {
|
||||
fn push_pq[T](mut prior_queue []T, data int, priority int) {
|
||||
mut temp := []T{}
|
||||
lenght_pq := prior_queue.len
|
||||
|
||||
@ -50,7 +50,7 @@ fn push_pq<T>(mut prior_queue []T, data int, priority int) {
|
||||
}
|
||||
|
||||
// Change the priority of a value/node ... exist a value, change its priority
|
||||
fn updating_priority<T>(mut prior_queue []T, search_data int, new_priority int) {
|
||||
fn updating_priority[T](mut prior_queue []T, search_data int, new_priority int) {
|
||||
mut i := 0
|
||||
mut lenght_pq := prior_queue.len
|
||||
|
||||
@ -72,7 +72,7 @@ fn updating_priority<T>(mut prior_queue []T, search_data int, new_priority int)
|
||||
}
|
||||
|
||||
// a single departure or remove from queue
|
||||
fn departure_priority<T>(mut prior_queue []T) int {
|
||||
fn departure_priority[T](mut prior_queue []T) int {
|
||||
mut x := prior_queue[0].data
|
||||
prior_queue.delete(0) // or .delete_many(0, 1 )
|
||||
return x
|
||||
@ -80,7 +80,7 @@ fn departure_priority<T>(mut prior_queue []T) int {
|
||||
|
||||
// give a NODE v, return a list with all adjacents
|
||||
// Take care, only positive EDGES
|
||||
fn all_adjacents<T>(g [][]T, v int) []int {
|
||||
fn all_adjacents[T](g [][]T, v int) []int {
|
||||
mut temp := []int{}
|
||||
for i in 0 .. (g.len) {
|
||||
if g[v][i] > 0 {
|
||||
|
@ -11,7 +11,7 @@ struct Story {
|
||||
}
|
||||
|
||||
fn worker_fetch(mut p pool.PoolProcessor, cursor int, worker_id int) voidptr {
|
||||
id := p.get_item<int>(cursor)
|
||||
id := p.get_item[int](cursor)
|
||||
resp := http.get('https://hacker-news.firebaseio.com/v0/item/${id}.json') or {
|
||||
println('failed to fetch data from /v0/item/${id}.json')
|
||||
return pool.no_result
|
||||
|
@ -11,12 +11,12 @@ fn main() {
|
||||
arr << rand.intn(gen_max) or { 0 }
|
||||
}
|
||||
println('length of random array is ${arr.len}')
|
||||
println('before quick sort whether array is sorted: ${is_sorted<int>(arr)}')
|
||||
quick_sort<int>(mut arr, 0, arr.len - 1)
|
||||
println('after quick sort whether array is sorted: ${is_sorted<int>(arr)}')
|
||||
println('before quick sort whether array is sorted: ${is_sorted[int](arr)}')
|
||||
quick_sort[int](mut arr, 0, arr.len - 1)
|
||||
println('after quick sort whether array is sorted: ${is_sorted[int](arr)}')
|
||||
}
|
||||
|
||||
fn quick_sort<T>(mut arr []T, l int, r int) {
|
||||
fn quick_sort[T](mut arr []T, l int, r int) {
|
||||
if l >= r {
|
||||
return
|
||||
}
|
||||
@ -28,11 +28,11 @@ fn quick_sort<T>(mut arr []T, l int, r int) {
|
||||
}
|
||||
}
|
||||
arr[l], arr[sep] = arr[sep], arr[l]
|
||||
quick_sort<T>(mut arr, l, sep - 1)
|
||||
quick_sort<T>(mut arr, sep + 1, r)
|
||||
quick_sort[T](mut arr, l, sep - 1)
|
||||
quick_sort[T](mut arr, sep + 1, r)
|
||||
}
|
||||
|
||||
fn is_sorted<T>(arr []T) bool {
|
||||
fn is_sorted[T](arr []T) bool {
|
||||
for i in 0 .. arr.len - 1 {
|
||||
if arr[i] > arr[i + 1] {
|
||||
return false
|
||||
|
@ -11,7 +11,7 @@ module arrays
|
||||
|
||||
// min returns the minimum value in the array
|
||||
// Example: arrays.min([1,2,3,0,9]) // => 0
|
||||
pub fn min<T>(array []T) !T {
|
||||
pub fn min[T](array []T) !T {
|
||||
if array.len == 0 {
|
||||
return error('.min called on an empty array')
|
||||
}
|
||||
@ -26,7 +26,7 @@ pub fn min<T>(array []T) !T {
|
||||
|
||||
// max returns the maximum value in the array
|
||||
// Example: arrays.max([1,2,3,0,9]) // => 9
|
||||
pub fn max<T>(array []T) !T {
|
||||
pub fn max[T](array []T) !T {
|
||||
if array.len == 0 {
|
||||
return error('.max called on an empty array')
|
||||
}
|
||||
@ -41,7 +41,7 @@ pub fn max<T>(array []T) !T {
|
||||
|
||||
// idx_min returns the index of the minimum value in the array
|
||||
// Example: arrays.idx_min([1,2,3,0,9]) // => 3
|
||||
pub fn idx_min<T>(array []T) !int {
|
||||
pub fn idx_min[T](array []T) !int {
|
||||
if array.len == 0 {
|
||||
return error('.idx_min called on an empty array')
|
||||
}
|
||||
@ -58,7 +58,7 @@ pub fn idx_min<T>(array []T) !int {
|
||||
|
||||
// idx_max returns the index of the maximum value in the array
|
||||
// Example: arrays.idx_max([1,2,3,0,9]) // => 4
|
||||
pub fn idx_max<T>(array []T) !int {
|
||||
pub fn idx_max[T](array []T) !int {
|
||||
if array.len == 0 {
|
||||
return error('.idx_max called on an empty array')
|
||||
}
|
||||
@ -76,7 +76,7 @@ pub fn idx_max<T>(array []T) !int {
|
||||
// merge two sorted arrays (ascending) and maintain sorted order
|
||||
// Example: arrays.merge([1,3,5,7], [2,4,6,8]) // => [1,2,3,4,5,6,7,8]
|
||||
[direct_array_access]
|
||||
pub fn merge<T>(a []T, b []T) []T {
|
||||
pub fn merge[T](a []T, b []T) []T {
|
||||
mut m := []T{len: a.len + b.len}
|
||||
mut ia := 0
|
||||
mut ib := 0
|
||||
@ -114,7 +114,7 @@ pub fn merge<T>(a []T, b []T) []T {
|
||||
//
|
||||
// NOTE: An error will be generated if the type annotation is omitted.
|
||||
// Example: arrays.group<int>([1,2,3],[4,5,6]) // => [[1, 4], [2, 5], [3, 6]]
|
||||
pub fn group<T>(arrays ...[]T) [][]T {
|
||||
pub fn group[T](arrays ...[]T) [][]T {
|
||||
mut length := if arrays.len > 0 { arrays[0].len } else { 0 }
|
||||
// calculate length of output by finding shortest input array
|
||||
for ndx in 1 .. arrays.len {
|
||||
@ -142,7 +142,7 @@ pub fn group<T>(arrays ...[]T) [][]T {
|
||||
|
||||
// chunk array into a single array of arrays where each element is the next `size` elements of the original
|
||||
// Example: arrays.chunk([1, 2, 3, 4, 5, 6, 7, 8, 9], 2)) // => [[1, 2], [3, 4], [5, 6], [7, 8], [9]]
|
||||
pub fn chunk<T>(array []T, size int) [][]T {
|
||||
pub fn chunk[T](array []T, size int) [][]T {
|
||||
// allocate chunk array
|
||||
mut chunks := [][]T{cap: array.len / size + if array.len % size == 0 { 0 } else { 1 }}
|
||||
|
||||
@ -177,7 +177,7 @@ pub struct WindowAttribute {
|
||||
//
|
||||
// Example: arrays.window([1, 2, 3, 4], size: 2) // => [[1, 2], [2, 3], [3, 4]]
|
||||
// Example: arrays.window([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], size: 3, step: 2) // => [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9]]
|
||||
pub fn window<T>(array []T, attr WindowAttribute) [][]T {
|
||||
pub fn window[T](array []T, attr WindowAttribute) [][]T {
|
||||
// allocate snapshot array
|
||||
mut windows := [][]T{cap: array.len - attr.size + 1}
|
||||
|
||||
@ -200,7 +200,7 @@ pub fn window<T>(array []T, attr WindowAttribute) [][]T {
|
||||
// which means you can only pass array of numbers for now.
|
||||
// TODO: Fix generic operator overloading detection issue.
|
||||
// Example: arrays.sum<int>([1, 2, 3, 4, 5])? // => 15
|
||||
pub fn sum<T>(array []T) !T {
|
||||
pub fn sum[T](array []T) !T {
|
||||
if array.len == 0 {
|
||||
return error('Cannot sum up array of nothing.')
|
||||
} else {
|
||||
@ -223,7 +223,7 @@ pub fn sum<T>(array []T) !T {
|
||||
// returns an error if the array is empty.
|
||||
// See also: [fold](#fold).
|
||||
// Example: arrays.reduce([1, 2, 3, 4, 5], fn (t1 int, t2 int) int { return t1 * t2 })! // => 120
|
||||
pub fn reduce<T>(array []T, reduce_op fn (acc T, elem T) T) !T {
|
||||
pub fn reduce[T](array []T, reduce_op fn (acc T, elem T) T) !T {
|
||||
if array.len == 0 {
|
||||
return error('Cannot reduce array of nothing.')
|
||||
} else {
|
||||
@ -245,7 +245,7 @@ pub fn reduce<T>(array []T, reduce_op fn (acc T, elem T) T) !T {
|
||||
// returns the accumulated value in `acc`.
|
||||
// returns an error if the array is empty.
|
||||
// See also: [fold_indexed](#fold_indexed).
|
||||
pub fn reduce_indexed<T>(array []T, reduce_op fn (idx int, acc T, elem T) T) !T {
|
||||
pub fn reduce_indexed[T](array []T, reduce_op fn (idx int, acc T, elem T) T) !T {
|
||||
if array.len == 0 {
|
||||
return error('Cannot reduce array of nothing.')
|
||||
} else {
|
||||
@ -265,7 +265,7 @@ pub fn reduce_indexed<T>(array []T, reduce_op fn (idx int, acc T, elem T) T) !T
|
||||
|
||||
// filter_indexed filters elements based on `predicate` function
|
||||
// being invoked on each element with its index in the original array.
|
||||
pub fn filter_indexed<T>(array []T, predicate fn (idx int, elem T) bool) []T {
|
||||
pub fn filter_indexed[T](array []T, predicate fn (idx int, elem T) bool) []T {
|
||||
mut result := []T{cap: array.len}
|
||||
|
||||
for i, e in array {
|
||||
@ -287,7 +287,7 @@ pub fn filter_indexed<T>(array []T, predicate fn (idx int, elem T) bool) []T {
|
||||
// fn (r int, t string) int { return r + t.len })
|
||||
// assert r == 5
|
||||
// ```
|
||||
pub fn fold<T, R>(array []T, init R, fold_op fn (acc R, elem T) R) R {
|
||||
pub fn fold[T, R](array []T, init R, fold_op fn (acc R, elem T) R) R {
|
||||
mut value := init
|
||||
|
||||
for e in array {
|
||||
@ -299,7 +299,7 @@ pub fn fold<T, R>(array []T, init R, fold_op fn (acc R, elem T) R) R {
|
||||
|
||||
// fold_indexed sets `acc = init`, then successively calls `acc = fold_op(idx, acc, elem)` for each element in `array`.
|
||||
// returns `acc`.
|
||||
pub fn fold_indexed<T, R>(array []T, init R, fold_op fn (idx int, acc R, elem T) R) R {
|
||||
pub fn fold_indexed[T, R](array []T, init R, fold_op fn (idx int, acc R, elem T) R) R {
|
||||
mut value := init
|
||||
|
||||
for i, e in array {
|
||||
@ -311,7 +311,7 @@ pub fn fold_indexed<T, R>(array []T, init R, fold_op fn (idx int, acc R, elem T)
|
||||
|
||||
// flatten flattens n + 1 dimensional array into n dimensional array
|
||||
// Example: arrays.flatten<int>([[1, 2, 3], [4, 5]]) // => [1, 2, 3, 4, 5]
|
||||
pub fn flatten<T>(array [][]T) []T {
|
||||
pub fn flatten[T](array [][]T) []T {
|
||||
// calculate required capacity
|
||||
mut required_size := 0
|
||||
|
||||
@ -335,7 +335,7 @@ pub fn flatten<T>(array [][]T) []T {
|
||||
|
||||
// flat_map creates a new array populated with the flattened result of calling transform function
|
||||
// being invoked on each element of `list`.
|
||||
pub fn flat_map<T, R>(array []T, transform fn (elem T) []R) []R {
|
||||
pub fn flat_map[T, R](array []T, transform fn (elem T) []R) []R {
|
||||
mut result := [][]R{cap: array.len}
|
||||
|
||||
for v in array {
|
||||
@ -347,7 +347,7 @@ pub fn flat_map<T, R>(array []T, transform fn (elem T) []R) []R {
|
||||
|
||||
// flat_map_indexed creates a new array populated with the flattened result of calling the `transform` function
|
||||
// being invoked on each element with its index in the original array.
|
||||
pub fn flat_map_indexed<T, R>(array []T, transform fn (idx int, elem T) []R) []R {
|
||||
pub fn flat_map_indexed[T, R](array []T, transform fn (idx int, elem T) []R) []R {
|
||||
mut result := [][]R{cap: array.len}
|
||||
|
||||
for i, v in array {
|
||||
@ -359,7 +359,7 @@ pub fn flat_map_indexed<T, R>(array []T, transform fn (idx int, elem T) []R) []R
|
||||
|
||||
// map_indexed creates a new array populated with the result of calling the `transform` function
|
||||
// being invoked on each element with its index in the original array.
|
||||
pub fn map_indexed<T, R>(array []T, transform fn (idx int, elem T) R) []R {
|
||||
pub fn map_indexed[T, R](array []T, transform fn (idx int, elem T) R) []R {
|
||||
mut result := []R{cap: array.len}
|
||||
|
||||
for i, v in array {
|
||||
@ -371,7 +371,7 @@ pub fn map_indexed<T, R>(array []T, transform fn (idx int, elem T) R) []R {
|
||||
|
||||
// group_by groups together elements, for which the `grouping_op` callback produced the same result.
|
||||
// Example: arrays.group_by<int, string>(['H', 'el', 'lo'], fn (v string) int { return v.len }) // => {1: ['H'], 2: ['el', 'lo']}
|
||||
pub fn group_by<K, V>(array []V, grouping_op fn (val V) K) map[K][]V {
|
||||
pub fn group_by[K, V](array []V, grouping_op fn (val V) K) map[K][]V {
|
||||
mut result := map[K][]V{}
|
||||
|
||||
for v in array {
|
||||
@ -394,7 +394,7 @@ pub fn group_by<K, V>(array []V, grouping_op fn (val V) K) map[K][]V {
|
||||
// Example: arrays.concat([1, 2, 3], 4, 5, 6) == [1, 2, 3, 4, 5, 6] // => true
|
||||
// Example: arrays.concat([1, 2, 3], ...[4, 5, 6]) == [1, 2, 3, 4, 5, 6] // => true
|
||||
// Example: arr << [4, 5, 6] // does what you need if arr is mutable
|
||||
pub fn concat<T>(a []T, b ...T) []T {
|
||||
pub fn concat[T](a []T, b ...T) []T {
|
||||
mut m := []T{cap: a.len + b.len}
|
||||
|
||||
m << a
|
||||
@ -405,7 +405,7 @@ pub fn concat<T>(a []T, b ...T) []T {
|
||||
|
||||
// returns the smallest element >= val, requires `array` to be sorted
|
||||
// Example: arrays.lower_bound([2, 4, 6, 8], 3)? // => 4
|
||||
pub fn lower_bound<T>(array []T, val T) !T {
|
||||
pub fn lower_bound[T](array []T, val T) !T {
|
||||
if array.len == 0 {
|
||||
return error('.lower_bound called on an empty array')
|
||||
}
|
||||
@ -428,7 +428,7 @@ pub fn lower_bound<T>(array []T, val T) !T {
|
||||
|
||||
// returns the largest element <= val, requires `array` to be sorted
|
||||
// Example: arrays.upper_bound([2, 4, 6, 8], 3)! // => 2
|
||||
pub fn upper_bound<T>(array []T, val T) !T {
|
||||
pub fn upper_bound[T](array []T, val T) !T {
|
||||
if array.len == 0 {
|
||||
return error('.upper_bound called on an empty array')
|
||||
}
|
||||
@ -453,7 +453,7 @@ pub fn upper_bound<T>(array []T, val T) !T {
|
||||
// Binary searches on sorted lists can be faster than other array searches because at maximum
|
||||
// the algorithm only has to traverse log N elements
|
||||
// Example: arrays.binary_search([1, 2, 3, 4], 4)? // => 3
|
||||
pub fn binary_search<T>(array []T, target T) !int {
|
||||
pub fn binary_search[T](array []T, target T) !int {
|
||||
mut left := 0
|
||||
mut right := array.len - 1
|
||||
for ; left <= right; {
|
||||
@ -480,12 +480,12 @@ pub fn binary_search<T>(array []T, target T) !int {
|
||||
// arrays.rotate_left(mut x, 2)
|
||||
// println(x) // [3, 4, 5, 6, 1, 2]
|
||||
// ```
|
||||
pub fn rotate_left<T>(mut array []T, mid int) {
|
||||
pub fn rotate_left[T](mut array []T, mid int) {
|
||||
assert mid <= array.len && mid >= 0
|
||||
k := array.len - mid
|
||||
p := &T(array.data)
|
||||
unsafe {
|
||||
ptr_rotate<T>(mid, &T(usize(voidptr(p)) + usize(sizeof(T)) * usize(mid)), k)
|
||||
ptr_rotate[T](mid, &T(usize(voidptr(p)) + usize(sizeof(T)) * usize(mid)), k)
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,27 +498,27 @@ pub fn rotate_left<T>(mut array []T, mid int) {
|
||||
// arrays.rotate_right(mut x, 2)
|
||||
// println(x) // [5, 6, 1, 2, 3, 4]
|
||||
// ```
|
||||
pub fn rotate_right<T>(mut array []T, k int) {
|
||||
pub fn rotate_right[T](mut array []T, k int) {
|
||||
assert k <= array.len && k >= 0
|
||||
mid := array.len - k
|
||||
p := &T(array.data)
|
||||
unsafe {
|
||||
ptr_rotate<T>(mid, &T(usize(voidptr(p)) + usize(sizeof(T)) * usize(mid)), k)
|
||||
ptr_rotate[T](mid, &T(usize(voidptr(p)) + usize(sizeof(T)) * usize(mid)), k)
|
||||
}
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
fn ptr_rotate<T>(left_ int, mid &T, right_ int) {
|
||||
fn ptr_rotate[T](left_ int, mid &T, right_ int) {
|
||||
mut left := usize(left_)
|
||||
mut right := usize(right_)
|
||||
for {
|
||||
delta := if left < right { left } else { right }
|
||||
|
||||
if delta <= raw_array_cap<T>() {
|
||||
if delta <= raw_array_cap[T]() {
|
||||
break
|
||||
}
|
||||
unsafe {
|
||||
swap_nonoverlapping<T>(&T(usize(voidptr(mid)) - left * usize(sizeof(T))),
|
||||
swap_nonoverlapping[T](&T(usize(voidptr(mid)) - left * usize(sizeof(T))),
|
||||
&T(usize(voidptr(mid)) + usize(right - delta) * usize(sizeof(T))), int(delta))
|
||||
}
|
||||
if left <= right {
|
||||
@ -530,7 +530,7 @@ fn ptr_rotate<T>(left_ int, mid &T, right_ int) {
|
||||
|
||||
unsafe {
|
||||
sz := usize(sizeof(T))
|
||||
rawarray := C.malloc(raw_array_malloc_size<T>())
|
||||
rawarray := C.malloc(raw_array_malloc_size[T]())
|
||||
dim := &T(usize(voidptr(mid)) - left * sz + right * sz)
|
||||
if left <= right {
|
||||
C.memcpy(rawarray, voidptr(usize(voidptr(mid)) - left * sz), left * sz)
|
||||
@ -565,7 +565,7 @@ const (
|
||||
extra_size = 32 * sizeof(usize)
|
||||
)
|
||||
|
||||
fn raw_array_cap<T>() usize {
|
||||
fn raw_array_cap[T]() usize {
|
||||
if sizeof(T) > arrays.extra_size {
|
||||
return 1
|
||||
} else {
|
||||
@ -573,7 +573,7 @@ fn raw_array_cap<T>() usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_array_malloc_size<T>() usize {
|
||||
fn raw_array_malloc_size[T]() usize {
|
||||
if sizeof(T) > arrays.extra_size {
|
||||
return usize(sizeof(T)) * 2
|
||||
} else {
|
||||
@ -614,7 +614,7 @@ fn memswap(x voidptr, y voidptr, len usize) {
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
fn swap_nonoverlapping<T>(x_ &T, y_ &T, count int) {
|
||||
fn swap_nonoverlapping[T](x_ &T, y_ &T, count int) {
|
||||
x := voidptr(x_)
|
||||
y := voidptr(y_)
|
||||
|
||||
@ -627,12 +627,12 @@ fn swap_nonoverlapping<T>(x_ &T, y_ &T, count int) {
|
||||
// copy copies the `src` array elements to the `dst` array.
|
||||
// The number of the elements copied is the minimum of the length of both arrays.
|
||||
// Returns the number of elements copied.
|
||||
pub fn copy<T>(mut dst []T, src []T) int {
|
||||
pub fn copy[T](mut dst []T, src []T) int {
|
||||
min := if dst.len < src.len { dst.len } else { src.len }
|
||||
if min <= 0 {
|
||||
return 0
|
||||
}
|
||||
if can_copy_bits<T>() {
|
||||
if can_copy_bits[T]() {
|
||||
blen := min * int(sizeof(T))
|
||||
unsafe { vmemmove(&T(dst.data), src.data, blen) }
|
||||
} else {
|
||||
@ -646,7 +646,7 @@ pub fn copy<T>(mut dst []T, src []T) int {
|
||||
// determines if T can be copied using `memcpy`
|
||||
// false if autofree needs to intervene
|
||||
// false if type is not copyable e.g. map
|
||||
fn can_copy_bits<T>() bool {
|
||||
fn can_copy_bits[T]() bool {
|
||||
// references, C pointers, integers, floats, runes
|
||||
if T.name[0] in [`&`, `b`, `c`, `f`, `i`, `r`, `u`, `v`] {
|
||||
return true
|
||||
@ -657,7 +657,7 @@ fn can_copy_bits<T>() bool {
|
||||
// carray_to_varray copies a C byte array into a V array of type `T`.
|
||||
// See also: `cstring_to_vstring`
|
||||
[unsafe]
|
||||
pub fn carray_to_varray<T>(c_array voidptr, c_array_len int) []T {
|
||||
pub fn carray_to_varray[T](c_array voidptr, c_array_len int) []T {
|
||||
mut v_array := []T{len: c_array_len}
|
||||
unsafe { vmemcpy(v_array.data, c_array, c_array_len * int(sizeof(T))) }
|
||||
return v_array
|
||||
|
@ -65,10 +65,10 @@ fn test_merge() {
|
||||
b := [2, 4, 4, 5, 6, 8]
|
||||
c := []int{}
|
||||
d := []int{}
|
||||
assert merge<int>(a, b) == [1, 2, 3, 4, 4, 5, 5, 5, 6, 7, 8]
|
||||
assert merge<int>(c, d) == []
|
||||
assert merge<int>(a, c) == a
|
||||
assert merge<int>(d, b) == b
|
||||
assert merge[int](a, b) == [1, 2, 3, 4, 4, 5, 5, 5, 6, 7, 8]
|
||||
assert merge[int](c, d) == []
|
||||
assert merge[int](a, c) == a
|
||||
assert merge[int](d, b) == b
|
||||
}
|
||||
|
||||
fn test_fixed_array_assignment() {
|
||||
@ -94,14 +94,14 @@ fn test_fixed_array_assignment() {
|
||||
|
||||
fn test_array_flat_map() {
|
||||
a := ['Hello V', 'Hello World', 'V Lang']
|
||||
assert flat_map<string, string>(a, fn (e string) []string {
|
||||
assert flat_map[string, string](a, fn (e string) []string {
|
||||
return e.split(' ')
|
||||
}) == ['Hello', 'V', 'Hello', 'World', 'V', 'Lang']
|
||||
}
|
||||
|
||||
fn test_array_flat_map_indexed() {
|
||||
a := ['AB', 'CD', 'EF']
|
||||
assert flat_map_indexed<string, string>(a, fn (i int, e string) []string {
|
||||
assert flat_map_indexed[string, string](a, fn (i int, e string) []string {
|
||||
mut arr := [i.str()]
|
||||
arr << e.split('')
|
||||
return arr
|
||||
@ -110,7 +110,7 @@ fn test_array_flat_map_indexed() {
|
||||
|
||||
fn test_map_indexed() {
|
||||
a := [1, 2, 3]
|
||||
assert map_indexed<int, int>(a, fn (i int, e int) int {
|
||||
assert map_indexed[int, int](a, fn (i int, e int) int {
|
||||
return i + e * e
|
||||
}) == [1, 5, 11]
|
||||
}
|
||||
@ -119,59 +119,59 @@ fn test_group() {
|
||||
x := [4, 5, 6]
|
||||
y := [2, 1, 3]
|
||||
|
||||
z := group<int>(x, y)
|
||||
z := group[int](x, y)
|
||||
assert z == [[4, 2], [5, 1], [6, 3]]
|
||||
x2 := [8, 9]
|
||||
z2 := group<int>(x2, y)
|
||||
z2 := group[int](x2, y)
|
||||
assert z2 == [[8, 2], [9, 1]]
|
||||
assert group<int>(x, []int{}) == [][]int{}
|
||||
assert group[int](x, []int{}) == [][]int{}
|
||||
}
|
||||
|
||||
fn test_chunk() {
|
||||
x := [1, 2, 3, 4, 5]
|
||||
y := ['a', 'b', 'c', 'd', 'e', 'f']
|
||||
|
||||
z1 := chunk<int>(x, 2)
|
||||
z1 := chunk[int](x, 2)
|
||||
assert z1 == [[1, 2], [3, 4], [5]]
|
||||
z2 := chunk<string>(y, 3)
|
||||
z2 := chunk[string](y, 3)
|
||||
assert z2 == [['a', 'b', 'c'], ['d', 'e', 'f']]
|
||||
assert chunk<int>([]int{}, 2) == [][]int{}
|
||||
assert chunk[int]([]int{}, 2) == [][]int{}
|
||||
}
|
||||
|
||||
fn test_window() {
|
||||
x := [1, 2, 3, 4, 5, 6]
|
||||
|
||||
assert window<int>(x, size: 3) == [[1, 2, 3], [2, 3, 4], [3, 4, 5],
|
||||
assert window[int](x, size: 3) == [[1, 2, 3], [2, 3, 4], [3, 4, 5],
|
||||
[4, 5, 6]]
|
||||
assert window<int>(x, size: 3, step: 2) == [[1, 2, 3], [3, 4, 5]]
|
||||
assert window<int>([]int{}, size: 2) == [][]int{}
|
||||
assert window[int](x, size: 3, step: 2) == [[1, 2, 3], [3, 4, 5]]
|
||||
assert window[int]([]int{}, size: 2) == [][]int{}
|
||||
}
|
||||
|
||||
fn test_sum() {
|
||||
x := [1, 2, 3, 4, 5]
|
||||
|
||||
assert sum<int>(x) or { 0 } == 15
|
||||
assert sum<f64>([1.0, 2.5, 3.5, 4.0]) or { 0 } == 11.0
|
||||
assert sum<int>([]int{}) or { 0 } == 0
|
||||
assert sum[int](x) or { 0 } == 15
|
||||
assert sum[f64]([1.0, 2.5, 3.5, 4.0]) or { 0 } == 11.0
|
||||
assert sum[int]([]int{}) or { 0 } == 0
|
||||
}
|
||||
|
||||
fn test_reduce() {
|
||||
x := [1, 2, 3, 4, 5]
|
||||
|
||||
assert reduce<int>(x, fn (t1 int, t2 int) int {
|
||||
assert reduce[int](x, fn (t1 int, t2 int) int {
|
||||
return t1 + t2
|
||||
}) or { 0 } == 15
|
||||
assert reduce<string>(['H', 'e', 'l', 'l', 'o'], fn (t1 string, t2 string) string {
|
||||
assert reduce[string](['H', 'e', 'l', 'l', 'o'], fn (t1 string, t2 string) string {
|
||||
return t1 + t2
|
||||
}) or { '' } == 'Hello' // For the sake please use array's join instead.
|
||||
assert reduce<int>([]int{}, fn (t1 int, t2 int) int {
|
||||
assert reduce[int]([]int{}, fn (t1 int, t2 int) int {
|
||||
return 0
|
||||
}) or { -1 } == -1
|
||||
}
|
||||
|
||||
fn test_reduce_indexed() {
|
||||
x := [1, 2, 3, 4, 5]
|
||||
assert reduce_indexed<int>(x, fn (idx int, t1 int, t2 int) int {
|
||||
assert reduce_indexed[int](x, fn (idx int, t1 int, t2 int) int {
|
||||
return idx + t1 + t2
|
||||
}) or { 0 } == 25
|
||||
}
|
||||
@ -179,7 +179,7 @@ fn test_reduce_indexed() {
|
||||
fn test_filter_indexed() {
|
||||
x := [0, 1, 2, 3, 4, 5]
|
||||
|
||||
assert filter_indexed<int>(x, fn (idx int, e int) bool {
|
||||
assert filter_indexed[int](x, fn (idx int, e int) bool {
|
||||
return idx % 2 == 0
|
||||
}) == [0, 2, 4]
|
||||
}
|
||||
@ -187,13 +187,13 @@ fn test_filter_indexed() {
|
||||
fn test_fold() {
|
||||
x := [1, 2, 3, 4, 5]
|
||||
|
||||
assert fold<int, int>(x, 5, fn (r int, t int) int {
|
||||
assert fold[int, int](x, 5, fn (r int, t int) int {
|
||||
return r + t
|
||||
}) == 20
|
||||
assert fold<string, int>(['H', 'e', 'l', 'l', 'l'], 0, fn (r int, t string) int {
|
||||
assert fold[string, int](['H', 'e', 'l', 'l', 'l'], 0, fn (r int, t string) int {
|
||||
return r + t[0]
|
||||
}) == 497
|
||||
assert fold<int, int>([]int{}, -1, fn (t1 int, t2 int) int {
|
||||
assert fold[int, int]([]int{}, -1, fn (t1 int, t2 int) int {
|
||||
return 0
|
||||
}) == -1
|
||||
}
|
||||
@ -201,7 +201,7 @@ fn test_fold() {
|
||||
fn test_fold_indexed() {
|
||||
x := [1, 2, 3, 4, 5]
|
||||
|
||||
assert fold_indexed<int, int>(x, 5, fn (idx int, r int, t int) int {
|
||||
assert fold_indexed[int, int](x, 5, fn (idx int, r int, t int) int {
|
||||
return idx + r + t
|
||||
}) == 30
|
||||
}
|
||||
@ -209,20 +209,20 @@ fn test_fold_indexed() {
|
||||
fn test_flatten() {
|
||||
x := [[1, 2, 3], [4, 5, 6]]
|
||||
|
||||
assert flatten<int>(x) == [1, 2, 3, 4, 5, 6]
|
||||
assert flatten<int>([[]int{}]) == []
|
||||
assert flatten[int](x) == [1, 2, 3, 4, 5, 6]
|
||||
assert flatten[int]([[]int{}]) == []
|
||||
}
|
||||
|
||||
fn test_group_by() {
|
||||
x := ['H', 'el', 'l', 'o ']
|
||||
|
||||
assert group_by<int, string>(x, fn (v string) int {
|
||||
assert group_by[int, string](x, fn (v string) int {
|
||||
return v.len
|
||||
}) == {
|
||||
1: ['H', 'l']
|
||||
2: ['el', 'o ']
|
||||
}
|
||||
assert group_by<int, int>([]int{}, fn (v int) int {
|
||||
assert group_by[int, int]([]int{}, fn (v int) int {
|
||||
return 0
|
||||
}) == map[int][]int{}
|
||||
}
|
||||
@ -329,15 +329,15 @@ fn test_copy() {
|
||||
}
|
||||
|
||||
fn test_can_copy_bits() {
|
||||
assert can_copy_bits<u8>()
|
||||
assert can_copy_bits<int>()
|
||||
assert can_copy_bits<voidptr>()
|
||||
assert can_copy_bits<&u8>()
|
||||
assert can_copy_bits[u8]()
|
||||
assert can_copy_bits[int]()
|
||||
assert can_copy_bits[voidptr]()
|
||||
assert can_copy_bits[&u8]()
|
||||
// autofree needs to intercept assign
|
||||
assert !can_copy_bits<string>()
|
||||
assert !can_copy_bits<[]int>()
|
||||
assert !can_copy_bits[string]()
|
||||
assert !can_copy_bits[[]int]()
|
||||
// map not copyable
|
||||
assert !can_copy_bits<map[string]int>()
|
||||
assert !can_copy_bits[map[string]int]()
|
||||
}
|
||||
|
||||
type Str = string
|
||||
|
@ -155,7 +155,7 @@ pub fn (instance BitField) extract(start int, len int) u64 {
|
||||
// insert sets bit numbers from 'start' to 'len' length with
|
||||
// the value converted from the number 'value'.
|
||||
// 0000 (1, 2, 0b10) => 0100
|
||||
pub fn (mut instance BitField) insert<T>(start int, len int, _value T) {
|
||||
pub fn (mut instance BitField) insert[T](start int, len int, _value T) {
|
||||
// panic?
|
||||
if start < 0 {
|
||||
return
|
||||
@ -190,7 +190,7 @@ pub fn (instance BitField) extract_lowest_bits_first(start int, len int) u64 {
|
||||
// insert sets bit numbers from 'start' to 'len' length with
|
||||
// the value converted from the number 'value'.
|
||||
// 0000 (1, 2, 0b10) => 0010
|
||||
pub fn (mut instance BitField) insert_lowest_bits_first<T>(start int, len int, _value T) {
|
||||
pub fn (mut instance BitField) insert_lowest_bits_first[T](start int, len int, _value T) {
|
||||
// panic?
|
||||
if start < 0 {
|
||||
return
|
||||
|
@ -1570,7 +1570,7 @@ fn test_clone_of_same_elem_size_array() {
|
||||
assert arr2 == [Abc{1, 2, 3}, Abc{2, 3, 4}]
|
||||
}
|
||||
|
||||
pub fn example<T>(mut arr []T) []T {
|
||||
pub fn example[T](mut arr []T) []T {
|
||||
return arr.clone()
|
||||
}
|
||||
|
||||
|
@ -1482,7 +1482,7 @@ fn test_clone_of_same_elem_size_array() {
|
||||
assert arr2 == [Abc{1, 2, 3}, Abc{2, 3, 4}]
|
||||
}
|
||||
|
||||
pub fn example<T>(mut arr []T) []T {
|
||||
pub fn example[T](mut arr []T) []T {
|
||||
return arr.clone()
|
||||
}
|
||||
|
||||
|
@ -14,46 +14,46 @@ pub fn JS.Promise.race(JS.Array) JS.Promise
|
||||
|
||||
// The Promise object represents the eventual completion (or failure)
|
||||
// of an asynchronous operation and its resulting value.
|
||||
pub struct Promise<T> {
|
||||
pub struct Promise[T] {
|
||||
mut:
|
||||
promise JS.Promise [noinit]
|
||||
}
|
||||
|
||||
pub fn promise_new<T>(executor fn (resolve fn (T), reject fn (JS.Any))) Promise<T> {
|
||||
pub fn promise_new[T](executor fn (resolve fn (T), reject fn (JS.Any))) Promise[T] {
|
||||
promise := JS.Promise.prototype.constructor(executor)
|
||||
return Promise<T>{promise}
|
||||
return Promise[T]{promise}
|
||||
}
|
||||
|
||||
pub fn (p Promise<T>) then(on_fullfilled fn (T), on_rejected fn (JS.Any)) {
|
||||
pub fn (p Promise[T]) then(on_fullfilled fn (T), on_rejected fn (JS.Any)) {
|
||||
p.promise.then(on_fullfilled, on_rejected)
|
||||
}
|
||||
|
||||
// catch method returns a Promise and deals with rejected cases only.
|
||||
pub fn (p Promise<T>) catch(callback fn (error JS.Any)) Promise<T> {
|
||||
pub fn (p Promise[T]) catch(callback fn (error JS.Any)) Promise[T] {
|
||||
promise := p.promise.catch(callback)
|
||||
return Promise<T>{promise}
|
||||
return Promise[T]{promise}
|
||||
}
|
||||
|
||||
pub fn (p Promise<T>) finally<U>(callback fn ()) Promise<JS.Any> {
|
||||
pub fn (p Promise[T]) finally[U](callback fn ()) Promise[JS.Any] {
|
||||
promise := p.promise.finally(callback)
|
||||
return Promise<JS.Any>{promise}
|
||||
return Promise[JS.Any]{promise}
|
||||
}
|
||||
|
||||
// reject<E> returns promise which was rejected because of specified error
|
||||
pub fn promise_reject(error JS.Any) Promise<JS.Any> {
|
||||
pub fn promise_reject(error JS.Any) Promise[JS.Any] {
|
||||
promise := JS.Promise.reject(error)
|
||||
return Promise<JS.Any>{promise}
|
||||
return Promise[JS.Any]{promise}
|
||||
}
|
||||
|
||||
// resolve<E> returns promise which was resolved with specified value
|
||||
pub fn promise_resolve<T>(result T) Promise<T> {
|
||||
pub fn promise_resolve[T](result T) Promise[T] {
|
||||
promise := JS.Promise.resolve(result)
|
||||
return Promise<T>{promise}
|
||||
return Promise[T]{promise}
|
||||
}
|
||||
|
||||
// race returns returns a promise that fulfills or rejects as soon as one of
|
||||
// the promises in an iterable fulfills or rejects, with the value or reason from that promise.
|
||||
pub fn promise_race<T>(promises []Promise<T>) Promise<T> {
|
||||
pub fn promise_race[T](promises []Promise[T]) Promise[T] {
|
||||
promises_ := JS.Array.prototype.constructor()
|
||||
|
||||
for elem in promises {
|
||||
@ -61,7 +61,7 @@ pub fn promise_race<T>(promises []Promise<T>) Promise<T> {
|
||||
}
|
||||
|
||||
promise := JS.Promise.race(promises_)
|
||||
return Promise<T>{promise}
|
||||
return Promise[T]{promise}
|
||||
}
|
||||
|
||||
pub fn JS.Promise.all(JS.Array) JS.Promise
|
||||
|
@ -130,7 +130,7 @@ fn works_check_on_sign_input_string(item string) bool {
|
||||
}
|
||||
|
||||
fn worker_for_string_content(mut p pool.PoolProcessor, idx int, worker_id int) &SignResult {
|
||||
item := p.get_item<string>(idx)
|
||||
item := p.get_item[string](idx)
|
||||
// println('worker_s worker_id: $worker_id | idx: $idx ')
|
||||
res := works_check_on_sign_input_string(item)
|
||||
mut sr := &SignResult{
|
||||
@ -155,8 +155,8 @@ fn test_input_from_djb_ed25519_crypto_sign_input_with_syncpool() {
|
||||
callback: worker_for_string_content
|
||||
maxjobs: 4
|
||||
)
|
||||
pool_s.work_on_items<string>(contents)
|
||||
for i, x in pool_s.get_results<SignResult>() {
|
||||
pool_s.work_on_items[string](contents)
|
||||
for i, x in pool_s.get_results[SignResult]() {
|
||||
// println("i: $i = $x.result")
|
||||
assert x.result == true
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ your actual elements. For example:
|
||||
```v
|
||||
import datatypes
|
||||
|
||||
mut stack := datatypes.Stack<int>{}
|
||||
mut stack := datatypes.Stack[int]{}
|
||||
stack.push(1)
|
||||
println(stack)
|
||||
```
|
||||
|
@ -2,36 +2,36 @@ module datatypes
|
||||
|
||||
/// Internal rapresentation of the tree node
|
||||
[heap]
|
||||
struct BSTreeNode<T> {
|
||||
struct BSTreeNode[T] {
|
||||
mut:
|
||||
// Mark a node as initialized
|
||||
is_init bool
|
||||
// Value of the node
|
||||
value T
|
||||
// The parent of the node
|
||||
parent &BSTreeNode<T> = unsafe { 0 }
|
||||
parent &BSTreeNode[T] = unsafe { 0 }
|
||||
// The left side with value less than the
|
||||
// value of this node
|
||||
left &BSTreeNode<T> = unsafe { 0 }
|
||||
left &BSTreeNode[T] = unsafe { 0 }
|
||||
// The right side with value grater than the
|
||||
// value of thiss node
|
||||
right &BSTreeNode<T> = unsafe { 0 }
|
||||
right &BSTreeNode[T] = unsafe { 0 }
|
||||
}
|
||||
|
||||
// Create new root bst node
|
||||
fn new_root_node<T>(value T) &BSTreeNode<T> {
|
||||
return &BSTreeNode<T>{
|
||||
fn new_root_node[T](value T) &BSTreeNode[T] {
|
||||
return &BSTreeNode[T]{
|
||||
is_init: true
|
||||
value: value
|
||||
parent: new_none_node<T>(true)
|
||||
left: new_none_node<T>(false)
|
||||
right: new_none_node<T>(false)
|
||||
parent: new_none_node[T](true)
|
||||
left: new_none_node[T](false)
|
||||
right: new_none_node[T](false)
|
||||
}
|
||||
}
|
||||
|
||||
// new_node creates a new bst node with a parent reference.
|
||||
fn new_node<T>(parent &BSTreeNode<T>, value T) &BSTreeNode<T> {
|
||||
return &BSTreeNode<T>{
|
||||
fn new_node[T](parent &BSTreeNode[T], value T) &BSTreeNode[T] {
|
||||
return &BSTreeNode[T]{
|
||||
is_init: true
|
||||
value: value
|
||||
parent: parent
|
||||
@ -39,19 +39,19 @@ fn new_node<T>(parent &BSTreeNode<T>, value T) &BSTreeNode<T> {
|
||||
}
|
||||
|
||||
// new_none_node creates a dummy node.
|
||||
fn new_none_node<T>(init bool) &BSTreeNode<T> {
|
||||
return &BSTreeNode<T>{
|
||||
fn new_none_node[T](init bool) &BSTreeNode[T] {
|
||||
return &BSTreeNode[T]{
|
||||
is_init: init
|
||||
}
|
||||
}
|
||||
|
||||
// bind to an actual instance of a node.
|
||||
fn (mut node BSTreeNode<T>) bind(mut to_bind BSTreeNode<T>, left bool) {
|
||||
fn (mut node BSTreeNode[T]) bind(mut to_bind BSTreeNode[T], left bool) {
|
||||
node.left = to_bind.left
|
||||
node.right = to_bind.right
|
||||
node.value = to_bind.value
|
||||
node.is_init = to_bind.is_init
|
||||
to_bind = new_none_node<T>(false)
|
||||
to_bind = new_none_node[T](false)
|
||||
}
|
||||
|
||||
// Pure Binary Seach Tree implementation
|
||||
@ -59,13 +59,13 @@ fn (mut node BSTreeNode<T>) bind(mut to_bind BSTreeNode<T>, left bool) {
|
||||
// Pure V implementation of the Binary Search Tree
|
||||
// Time complexity of main operation O(log N)
|
||||
// Space complexity O(N)
|
||||
pub struct BSTree<T> {
|
||||
pub struct BSTree[T] {
|
||||
mut:
|
||||
root &BSTreeNode<T> = unsafe { 0 }
|
||||
root &BSTreeNode[T] = unsafe { 0 }
|
||||
}
|
||||
|
||||
// insert give the possibility to insert an element in the BST.
|
||||
pub fn (mut bst BSTree<T>) insert(value T) bool {
|
||||
pub fn (mut bst BSTree[T]) insert(value T) bool {
|
||||
if bst.is_empty() {
|
||||
bst.root = new_root_node(value)
|
||||
return true
|
||||
@ -74,7 +74,7 @@ pub fn (mut bst BSTree<T>) insert(value T) bool {
|
||||
}
|
||||
|
||||
// insert_helper walks the tree and inserts the given node.
|
||||
fn (mut bst BSTree<T>) insert_helper(mut node BSTreeNode<T>, value T) bool {
|
||||
fn (mut bst BSTree[T]) insert_helper(mut node BSTreeNode[T], value T) bool {
|
||||
if node.value < value {
|
||||
if unsafe { node.right != 0 } && node.right.is_init {
|
||||
return bst.insert_helper(mut node.right, value)
|
||||
@ -92,13 +92,13 @@ fn (mut bst BSTree<T>) insert_helper(mut node BSTreeNode<T>, value T) bool {
|
||||
}
|
||||
|
||||
// contains checks if an element with a given `value` is inside the BST.
|
||||
pub fn (bst &BSTree<T>) contains(value T) bool {
|
||||
pub fn (bst &BSTree[T]) contains(value T) bool {
|
||||
return bst.contains_helper(bst.root, value)
|
||||
}
|
||||
|
||||
// contains_helper is a helper function to walk the tree, and return
|
||||
// the absence or presence of the `value`.
|
||||
fn (bst &BSTree<T>) contains_helper(node &BSTreeNode<T>, value T) bool {
|
||||
fn (bst &BSTree[T]) contains_helper(node &BSTreeNode[T], value T) bool {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return false
|
||||
}
|
||||
@ -112,14 +112,14 @@ fn (bst &BSTree<T>) contains_helper(node &BSTreeNode<T>, value T) bool {
|
||||
}
|
||||
|
||||
// remove removes an element with `value` from the BST.
|
||||
pub fn (mut bst BSTree<T>) remove(value T) bool {
|
||||
pub fn (mut bst BSTree[T]) remove(value T) bool {
|
||||
if bst.is_empty() {
|
||||
return false
|
||||
}
|
||||
return bst.remove_helper(mut bst.root, value, false)
|
||||
}
|
||||
|
||||
fn (mut bst BSTree<T>) remove_helper(mut node BSTreeNode<T>, value T, left bool) bool {
|
||||
fn (mut bst BSTree[T]) remove_helper(mut node BSTreeNode[T], value T, left bool) bool {
|
||||
if !node.is_init {
|
||||
return false
|
||||
}
|
||||
@ -136,11 +136,11 @@ fn (mut bst BSTree<T>) remove_helper(mut node BSTreeNode<T>, value T, left bool)
|
||||
} else {
|
||||
mut parent := node.parent
|
||||
if left {
|
||||
parent.left = new_none_node<T>(false)
|
||||
parent.left = new_none_node[T](false)
|
||||
} else {
|
||||
parent.right = new_none_node<T>(false)
|
||||
parent.right = new_none_node[T](false)
|
||||
}
|
||||
node = new_none_node<T>(false)
|
||||
node = new_none_node[T](false)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -152,9 +152,9 @@ fn (mut bst BSTree<T>) remove_helper(mut node BSTreeNode<T>, value T, left bool)
|
||||
}
|
||||
|
||||
// get_max_from_right returns the max element of the BST following the right branch.
|
||||
fn (bst &BSTree<T>) get_max_from_right(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||
fn (bst &BSTree[T]) get_max_from_right(node &BSTreeNode[T]) &BSTreeNode[T] {
|
||||
if unsafe { node == 0 } {
|
||||
return new_none_node<T>(false)
|
||||
return new_none_node[T](false)
|
||||
}
|
||||
right_node := node.right
|
||||
if unsafe { right_node == 0 } || !right_node.is_init {
|
||||
@ -164,9 +164,9 @@ fn (bst &BSTree<T>) get_max_from_right(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||
}
|
||||
|
||||
// get_min_from_left returns the min element of the BST by following the left branch.
|
||||
fn (bst &BSTree<T>) get_min_from_left(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||
fn (bst &BSTree[T]) get_min_from_left(node &BSTreeNode[T]) &BSTreeNode[T] {
|
||||
if unsafe { node == 0 } {
|
||||
return new_none_node<T>(false)
|
||||
return new_none_node[T](false)
|
||||
}
|
||||
left_node := node.left
|
||||
if unsafe { left_node == 0 } || !left_node.is_init {
|
||||
@ -176,19 +176,19 @@ fn (bst &BSTree<T>) get_min_from_left(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||
}
|
||||
|
||||
// is_empty checks if the BST is empty
|
||||
pub fn (bst &BSTree<T>) is_empty() bool {
|
||||
pub fn (bst &BSTree[T]) is_empty() bool {
|
||||
return unsafe { bst.root == 0 }
|
||||
}
|
||||
|
||||
// in_order_traversal traverses the BST in order, and returns the result as an array.
|
||||
pub fn (bst &BSTree<T>) in_order_traversal() []T {
|
||||
pub fn (bst &BSTree[T]) in_order_traversal() []T {
|
||||
mut result := []T{}
|
||||
bst.in_order_traversal_helper(bst.root, mut result)
|
||||
return result
|
||||
}
|
||||
|
||||
// in_order_traversal_helper helps traverse the BST, and accumulates the result in the `result` array.
|
||||
fn (bst &BSTree<T>) in_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||
fn (bst &BSTree[T]) in_order_traversal_helper(node &BSTreeNode[T], mut result []T) {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return
|
||||
}
|
||||
@ -198,7 +198,7 @@ fn (bst &BSTree<T>) in_order_traversal_helper(node &BSTreeNode<T>, mut result []
|
||||
}
|
||||
|
||||
// post_order_traversal traverses the BST in post order, and returns the result in an array.
|
||||
pub fn (bst &BSTree<T>) post_order_traversal() []T {
|
||||
pub fn (bst &BSTree[T]) post_order_traversal() []T {
|
||||
mut result := []T{}
|
||||
bst.post_order_traversal_helper(bst.root, mut result)
|
||||
return result
|
||||
@ -206,7 +206,7 @@ pub fn (bst &BSTree<T>) post_order_traversal() []T {
|
||||
|
||||
// post_order_traversal_helper is a helper function that traverses the BST in post order,
|
||||
// accumulating the result in an array.
|
||||
fn (bst &BSTree<T>) post_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||
fn (bst &BSTree[T]) post_order_traversal_helper(node &BSTreeNode[T], mut result []T) {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return
|
||||
}
|
||||
@ -217,7 +217,7 @@ fn (bst &BSTree<T>) post_order_traversal_helper(node &BSTreeNode<T>, mut result
|
||||
}
|
||||
|
||||
// pre_order_traversal traverses the BST in pre order, and returns the result as an array.
|
||||
pub fn (bst &BSTree<T>) pre_order_traversal() []T {
|
||||
pub fn (bst &BSTree[T]) pre_order_traversal() []T {
|
||||
mut result := []T{}
|
||||
bst.pre_order_traversal_helper(bst.root, mut result)
|
||||
return result
|
||||
@ -225,7 +225,7 @@ pub fn (bst &BSTree<T>) pre_order_traversal() []T {
|
||||
|
||||
// pre_order_traversal_helper is a helper function to traverse the BST
|
||||
// in pre order and accumulates the results in an array.
|
||||
fn (bst &BSTree<T>) pre_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||
fn (bst &BSTree[T]) pre_order_traversal_helper(node &BSTreeNode[T], mut result []T) {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return
|
||||
}
|
||||
@ -235,9 +235,9 @@ fn (bst &BSTree<T>) pre_order_traversal_helper(node &BSTreeNode<T>, mut result [
|
||||
}
|
||||
|
||||
// get_node is a helper method to ge the internal rapresentation of the node with the `value`.
|
||||
fn (bst &BSTree<T>) get_node(node &BSTreeNode<T>, value T) &BSTreeNode<T> {
|
||||
fn (bst &BSTree[T]) get_node(node &BSTreeNode[T], value T) &BSTreeNode[T] {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return new_none_node<T>(false)
|
||||
return new_none_node[T](false)
|
||||
}
|
||||
if node.value == value {
|
||||
return node
|
||||
@ -256,7 +256,7 @@ fn (bst &BSTree<T>) get_node(node &BSTreeNode<T>, value T) &BSTreeNode<T> {
|
||||
//```v
|
||||
// left_value, exist := bst.to_left(10)
|
||||
//```
|
||||
pub fn (bst &BSTree<T>) to_left(value T) ?T {
|
||||
pub fn (bst &BSTree[T]) to_left(value T) ?T {
|
||||
if bst.is_empty() {
|
||||
return none
|
||||
}
|
||||
@ -275,7 +275,7 @@ pub fn (bst &BSTree<T>) to_left(value T) ?T {
|
||||
//```v
|
||||
// left_value, exist := bst.to_right(10)
|
||||
//```
|
||||
pub fn (bst &BSTree<T>) to_right(value T) ?T {
|
||||
pub fn (bst &BSTree[T]) to_right(value T) ?T {
|
||||
if bst.is_empty() {
|
||||
return none
|
||||
}
|
||||
@ -289,7 +289,7 @@ pub fn (bst &BSTree<T>) to_right(value T) ?T {
|
||||
|
||||
// max return the max element inside the BST.
|
||||
// Time complexity O(N) if the BST is not balanced
|
||||
pub fn (bst &BSTree<T>) max() ?T {
|
||||
pub fn (bst &BSTree[T]) max() ?T {
|
||||
if bst.is_empty() {
|
||||
return none
|
||||
}
|
||||
@ -302,7 +302,7 @@ pub fn (bst &BSTree<T>) max() ?T {
|
||||
|
||||
// min return the minimum element in the BST.
|
||||
// Time complexity O(N) if the BST is not balanced.
|
||||
pub fn (bst &BSTree<T>) min() ?T {
|
||||
pub fn (bst &BSTree[T]) min() ?T {
|
||||
if bst.is_empty() {
|
||||
return none
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ module datatypes
|
||||
// Make an insert of one element and check if
|
||||
// the bst is able to fin it.
|
||||
fn test_insert_into_bst_one() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert bst.insert(10) == true
|
||||
assert bst.contains(10) == true
|
||||
assert bst.contains(20) == false
|
||||
@ -12,7 +12,7 @@ fn test_insert_into_bst_one() {
|
||||
// Make the insert of more element inside the BST
|
||||
// and check if the BST is able to find all the values
|
||||
fn test_insert_into_bst_two() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
assert bst.insert(9)
|
||||
@ -26,7 +26,7 @@ fn test_insert_into_bst_two() {
|
||||
// Test if the in_order_traversals list return the correct
|
||||
// result array
|
||||
fn test_in_order_bst_visit_one() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
assert bst.insert(21)
|
||||
@ -38,7 +38,7 @@ fn test_in_order_bst_visit_one() {
|
||||
// Test if the post_order_bst_visit return the correct
|
||||
// result array
|
||||
fn test_post_order_bst_visit_one() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
assert bst.insert(21)
|
||||
@ -49,7 +49,7 @@ fn test_post_order_bst_visit_one() {
|
||||
|
||||
// Test if the pre_order_traversal return the correct result array
|
||||
fn test_pre_order_bst_visit_one() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
assert bst.insert(21)
|
||||
@ -61,7 +61,7 @@ fn test_pre_order_bst_visit_one() {
|
||||
// After many insert check if we are abe to get the correct
|
||||
// right and left value of the root.
|
||||
fn test_get_left_root() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
assert bst.insert(21)
|
||||
@ -76,7 +76,7 @@ fn test_get_left_root() {
|
||||
|
||||
// Check if BST panic if we call some operation on an empty BST.
|
||||
fn test_get_left_on_empty_bst() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
|
||||
left_val := bst.to_left(10) or { -1 }
|
||||
assert left_val == -1
|
||||
@ -88,7 +88,7 @@ fn test_get_left_on_empty_bst() {
|
||||
// Check the remove operation if it is able to remove
|
||||
// all elements required, and mantains the BST propriety.
|
||||
fn test_remove_from_bst_one() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
assert bst.insert(21)
|
||||
@ -102,7 +102,7 @@ fn test_remove_from_bst_one() {
|
||||
// Another test n the remove BST, this remove an intermidia node
|
||||
// that it is a triky operation.
|
||||
fn test_remove_from_bst_two() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
assert bst.insert(21)
|
||||
@ -115,7 +115,7 @@ fn test_remove_from_bst_two() {
|
||||
|
||||
// check if we are able to get the max from the BST.
|
||||
fn test_get_max_in_bst() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert (bst.max() or { -1 }) == -1
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
@ -127,7 +127,7 @@ fn test_get_max_in_bst() {
|
||||
|
||||
// check if we are able to get the min from the BST.
|
||||
fn test_get_min_in_bst() {
|
||||
mut bst := BSTree<int>{}
|
||||
mut bst := BSTree[int]{}
|
||||
assert (bst.min() or { -1 }) == -1
|
||||
assert bst.insert(10)
|
||||
assert bst.insert(20)
|
||||
|
@ -1,36 +1,36 @@
|
||||
module datatypes
|
||||
|
||||
struct DoublyListNode<T> {
|
||||
struct DoublyListNode[T] {
|
||||
mut:
|
||||
data T
|
||||
next &DoublyListNode<T> = unsafe { 0 }
|
||||
prev &DoublyListNode<T> = unsafe { 0 }
|
||||
next &DoublyListNode[T] = unsafe { 0 }
|
||||
prev &DoublyListNode[T] = unsafe { 0 }
|
||||
}
|
||||
|
||||
// DoublyLinkedList<T> represents a generic doubly linked list of elements, each of type T.
|
||||
pub struct DoublyLinkedList<T> {
|
||||
pub struct DoublyLinkedList[T] {
|
||||
mut:
|
||||
head &DoublyListNode<T> = unsafe { 0 }
|
||||
tail &DoublyListNode<T> = unsafe { 0 }
|
||||
head &DoublyListNode[T] = unsafe { 0 }
|
||||
tail &DoublyListNode[T] = unsafe { 0 }
|
||||
// Internal iter pointer for allowing safe modification
|
||||
// of the list while iterating. TODO: use an option
|
||||
// instead of a pointer to determine it is initialized.
|
||||
iter &DoublyListIter<T> = unsafe { 0 }
|
||||
iter &DoublyListIter[T] = unsafe { 0 }
|
||||
len int
|
||||
}
|
||||
|
||||
// is_empty checks if the linked list is empty
|
||||
pub fn (list DoublyLinkedList<T>) is_empty() bool {
|
||||
pub fn (list DoublyLinkedList[T]) is_empty() bool {
|
||||
return list.len == 0
|
||||
}
|
||||
|
||||
// len returns the length of the linked list
|
||||
pub fn (list DoublyLinkedList<T>) len() int {
|
||||
pub fn (list DoublyLinkedList[T]) len() int {
|
||||
return list.len
|
||||
}
|
||||
|
||||
// first returns the first element of the linked list
|
||||
pub fn (list DoublyLinkedList<T>) first() ?T {
|
||||
pub fn (list DoublyLinkedList[T]) first() ?T {
|
||||
if list.is_empty() {
|
||||
return error('Linked list is empty')
|
||||
}
|
||||
@ -38,7 +38,7 @@ pub fn (list DoublyLinkedList<T>) first() ?T {
|
||||
}
|
||||
|
||||
// last returns the last element of the linked list
|
||||
pub fn (list DoublyLinkedList<T>) last() ?T {
|
||||
pub fn (list DoublyLinkedList[T]) last() ?T {
|
||||
if list.is_empty() {
|
||||
return error('Linked list is empty')
|
||||
}
|
||||
@ -46,8 +46,8 @@ pub fn (list DoublyLinkedList<T>) last() ?T {
|
||||
}
|
||||
|
||||
// push_back adds an element to the end of the linked list
|
||||
pub fn (mut list DoublyLinkedList<T>) push_back(item T) {
|
||||
mut new_node := &DoublyListNode<T>{
|
||||
pub fn (mut list DoublyLinkedList[T]) push_back(item T) {
|
||||
mut new_node := &DoublyListNode[T]{
|
||||
data: item
|
||||
}
|
||||
if list.is_empty() {
|
||||
@ -63,8 +63,8 @@ pub fn (mut list DoublyLinkedList<T>) push_back(item T) {
|
||||
}
|
||||
|
||||
// push_front adds an element to the beginning of the linked list
|
||||
pub fn (mut list DoublyLinkedList<T>) push_front(item T) {
|
||||
mut new_node := &DoublyListNode<T>{
|
||||
pub fn (mut list DoublyLinkedList[T]) push_front(item T) {
|
||||
mut new_node := &DoublyListNode[T]{
|
||||
data: item
|
||||
}
|
||||
if list.is_empty() {
|
||||
@ -80,7 +80,7 @@ pub fn (mut list DoublyLinkedList<T>) push_front(item T) {
|
||||
}
|
||||
|
||||
// pop_back removes the last element of the linked list
|
||||
pub fn (mut list DoublyLinkedList<T>) pop_back() ?T {
|
||||
pub fn (mut list DoublyLinkedList[T]) pop_back() ?T {
|
||||
if list.is_empty() {
|
||||
return error('Linked list is empty')
|
||||
}
|
||||
@ -101,7 +101,7 @@ pub fn (mut list DoublyLinkedList<T>) pop_back() ?T {
|
||||
}
|
||||
|
||||
// pop_front removes the last element of the linked list
|
||||
pub fn (mut list DoublyLinkedList<T>) pop_front() ?T {
|
||||
pub fn (mut list DoublyLinkedList[T]) pop_front() ?T {
|
||||
if list.is_empty() {
|
||||
return error('Linked list is empty')
|
||||
}
|
||||
@ -122,7 +122,7 @@ pub fn (mut list DoublyLinkedList<T>) pop_front() ?T {
|
||||
}
|
||||
|
||||
// insert adds an element to the linked list at the given index
|
||||
pub fn (mut list DoublyLinkedList<T>) insert(idx int, item T) ? {
|
||||
pub fn (mut list DoublyLinkedList[T]) insert(idx int, item T) ? {
|
||||
if idx < 0 || idx > list.len {
|
||||
return error('Index ${idx} out of bounds [0..${list.len}]')
|
||||
} else if idx == 0 {
|
||||
@ -142,7 +142,7 @@ pub fn (mut list DoublyLinkedList<T>) insert(idx int, item T) ? {
|
||||
// (determined from the forward index). This function should be called
|
||||
// when idx > list.len/2. This helper function assumes idx bounds have
|
||||
// already been checked and idx is not at the edges.
|
||||
fn (mut list DoublyLinkedList<T>) insert_back(idx int, item T) {
|
||||
fn (mut list DoublyLinkedList[T]) insert_back(idx int, item T) {
|
||||
mut node := list.node(idx + 1)
|
||||
mut prev := node.prev
|
||||
// prev node
|
||||
@ -150,7 +150,7 @@ fn (mut list DoublyLinkedList<T>) insert_back(idx int, item T) {
|
||||
// |next|---->|next|
|
||||
// |prev|<----|prev|
|
||||
// ------ ------
|
||||
new := &DoublyListNode<T>{
|
||||
new := &DoublyListNode[T]{
|
||||
data: item
|
||||
next: node
|
||||
prev: prev
|
||||
@ -169,7 +169,7 @@ fn (mut list DoublyLinkedList<T>) insert_back(idx int, item T) {
|
||||
// (determined from the forward index). This function should be called
|
||||
// when idx <= list.len/2. This helper function assumes idx bounds have
|
||||
// already been checked and idx is not at the edges.
|
||||
fn (mut list DoublyLinkedList<T>) insert_front(idx int, item T) {
|
||||
fn (mut list DoublyLinkedList[T]) insert_front(idx int, item T) {
|
||||
mut node := list.node(idx - 1)
|
||||
mut next := node.next
|
||||
// node next
|
||||
@ -177,7 +177,7 @@ fn (mut list DoublyLinkedList<T>) insert_front(idx int, item T) {
|
||||
// |next|---->|next|
|
||||
// |prev|<----|prev|
|
||||
// ------ ------
|
||||
new := &DoublyListNode<T>{
|
||||
new := &DoublyListNode[T]{
|
||||
data: item
|
||||
next: next
|
||||
prev: node
|
||||
@ -195,7 +195,7 @@ fn (mut list DoublyLinkedList<T>) insert_front(idx int, item T) {
|
||||
// node walks from the head or tail and finds the node at index idx.
|
||||
// This helper function assumes the list is not empty and idx is in
|
||||
// bounds.
|
||||
fn (list &DoublyLinkedList<T>) node(idx int) &DoublyListNode<T> {
|
||||
fn (list &DoublyLinkedList[T]) node(idx int) &DoublyListNode[T] {
|
||||
if idx <= list.len / 2 {
|
||||
mut node := list.head
|
||||
for h := 0; h < idx; h += 1 {
|
||||
@ -212,7 +212,7 @@ fn (list &DoublyLinkedList<T>) node(idx int) &DoublyListNode<T> {
|
||||
|
||||
// index searches the linked list for item and returns the forward index
|
||||
// or none if not found.
|
||||
pub fn (list &DoublyLinkedList<T>) index(item T) ?int {
|
||||
pub fn (list &DoublyLinkedList[T]) index(item T) ?int {
|
||||
mut hn := list.head
|
||||
mut tn := list.tail
|
||||
for h, t := 0, list.len - 1; h <= t; {
|
||||
@ -231,7 +231,7 @@ pub fn (list &DoublyLinkedList<T>) index(item T) ?int {
|
||||
|
||||
// delete removes index idx from the linked list and is safe to call
|
||||
// for any idx.
|
||||
pub fn (mut list DoublyLinkedList<T>) delete(idx int) {
|
||||
pub fn (mut list DoublyLinkedList[T]) delete(idx int) {
|
||||
if idx < 0 || idx >= list.len {
|
||||
return
|
||||
} else if idx == 0 {
|
||||
@ -249,12 +249,12 @@ pub fn (mut list DoublyLinkedList<T>) delete(idx int) {
|
||||
}
|
||||
|
||||
// str returns a string representation of the linked list
|
||||
pub fn (list DoublyLinkedList<T>) str() string {
|
||||
pub fn (list DoublyLinkedList[T]) str() string {
|
||||
return list.array().str()
|
||||
}
|
||||
|
||||
// array returns a array representation of the linked list
|
||||
pub fn (list DoublyLinkedList<T>) array() []T {
|
||||
pub fn (list DoublyLinkedList[T]) array() []T {
|
||||
mut result_array := []T{cap: list.len}
|
||||
mut node := list.head
|
||||
for unsafe { node != 0 } {
|
||||
@ -266,10 +266,10 @@ pub fn (list DoublyLinkedList<T>) array() []T {
|
||||
|
||||
// next implements the iter interface to use DoublyLinkedList with
|
||||
// V's `for x in list {` loop syntax.
|
||||
pub fn (mut list DoublyLinkedList<T>) next() ?T {
|
||||
pub fn (mut list DoublyLinkedList[T]) next() ?T {
|
||||
if list.iter == unsafe { nil } {
|
||||
// initialize new iter object
|
||||
list.iter = &DoublyListIter<T>{
|
||||
list.iter = &DoublyListIter[T]{
|
||||
node: list.head
|
||||
}
|
||||
return list.next()
|
||||
@ -285,15 +285,15 @@ pub fn (mut list DoublyLinkedList<T>) next() ?T {
|
||||
}
|
||||
|
||||
// iterator returns a new iterator instance for the `list`.
|
||||
pub fn (mut list DoublyLinkedList<T>) iterator() DoublyListIter<T> {
|
||||
return DoublyListIter<T>{
|
||||
pub fn (mut list DoublyLinkedList[T]) iterator() DoublyListIter[T] {
|
||||
return DoublyListIter[T]{
|
||||
node: list.head
|
||||
}
|
||||
}
|
||||
|
||||
// back_iterator returns a new backwards iterator instance for the `list`.
|
||||
pub fn (mut list DoublyLinkedList<T>) back_iterator() DoublyListIterBack<T> {
|
||||
return DoublyListIterBack<T>{
|
||||
pub fn (mut list DoublyLinkedList[T]) back_iterator() DoublyListIterBack[T] {
|
||||
return DoublyListIterBack[T]{
|
||||
node: list.tail
|
||||
}
|
||||
}
|
||||
@ -303,14 +303,14 @@ pub fn (mut list DoublyLinkedList<T>) back_iterator() DoublyListIterBack<T> {
|
||||
// It can be used with V's `for x in iter {` construct.
|
||||
// One list can have multiple independent iterators, pointing to different positions/places in the list.
|
||||
// A DoublyListIter iterator instance always traverses the list from *start to finish*.
|
||||
pub struct DoublyListIter<T> {
|
||||
pub struct DoublyListIter[T] {
|
||||
mut:
|
||||
node &DoublyListNode<T> = unsafe { 0 }
|
||||
node &DoublyListNode[T] = unsafe { 0 }
|
||||
}
|
||||
|
||||
// next returns *the next* element of the list, or `none` when the end of the list is reached.
|
||||
// It is called by V's `for x in iter{` on each iteration.
|
||||
pub fn (mut iter DoublyListIter<T>) next() ?T {
|
||||
pub fn (mut iter DoublyListIter[T]) next() ?T {
|
||||
if iter.node == unsafe { nil } {
|
||||
return none
|
||||
}
|
||||
@ -324,14 +324,14 @@ pub fn (mut iter DoublyListIter<T>) next() ?T {
|
||||
// It can be used with V's `for x in iter {` construct.
|
||||
// One list can have multiple independent iterators, pointing to different positions/places in the list.
|
||||
// A DoublyListIterBack iterator instance always traverses the list from *finish to start*.
|
||||
pub struct DoublyListIterBack<T> {
|
||||
pub struct DoublyListIterBack[T] {
|
||||
mut:
|
||||
node &DoublyListNode<T> = unsafe { 0 }
|
||||
node &DoublyListNode[T] = unsafe { 0 }
|
||||
}
|
||||
|
||||
// next returns *the previous* element of the list, or `none` when the start of the list is reached.
|
||||
// It is called by V's `for x in iter{` on each iteration.
|
||||
pub fn (mut iter DoublyListIterBack<T>) next() ?T {
|
||||
pub fn (mut iter DoublyListIterBack[T]) next() ?T {
|
||||
if iter.node == unsafe { nil } {
|
||||
return none
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
module datatypes
|
||||
|
||||
fn test_is_empty() {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
assert list.is_empty() == true
|
||||
list.push_back(1)
|
||||
assert list.is_empty() == false
|
||||
}
|
||||
|
||||
fn test_len() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
assert list.len() == 0
|
||||
list.push_back(1)
|
||||
assert list.len() == 1
|
||||
@ -17,29 +17,29 @@ fn test_len() ? {
|
||||
}
|
||||
|
||||
fn test_first() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
assert list.first()? == 1
|
||||
list.push_back(2)
|
||||
assert list.first()? == 1
|
||||
list = DoublyLinkedList<int>{}
|
||||
list = DoublyLinkedList[int]{}
|
||||
list.first() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_last() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
assert list.last()? == 1
|
||||
list.push_back(2)
|
||||
assert list.last()? == 2
|
||||
list = DoublyLinkedList<int>{}
|
||||
list = DoublyLinkedList[int]{}
|
||||
list.last() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_push() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
assert list.last()? == 1
|
||||
list.push_back(2)
|
||||
@ -49,7 +49,7 @@ fn test_push() ? {
|
||||
}
|
||||
|
||||
fn test_pop() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
@ -57,13 +57,13 @@ fn test_pop() ? {
|
||||
list.push_back(4)
|
||||
assert list.pop_back()? == 4
|
||||
assert list.pop_back()? == 2
|
||||
list = DoublyLinkedList<int>{}
|
||||
list = DoublyLinkedList[int]{}
|
||||
list.pop_back() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_pop_front() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
@ -71,13 +71,13 @@ fn test_pop_front() ? {
|
||||
list.push_back(4)
|
||||
assert list.pop_front()? == 2
|
||||
assert list.pop_front()? == 3
|
||||
list = DoublyLinkedList<int>{}
|
||||
list = DoublyLinkedList[int]{}
|
||||
list.pop_front() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_insert() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
@ -93,7 +93,7 @@ fn test_insert() ? {
|
||||
}
|
||||
|
||||
fn test_push_front() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
@ -102,7 +102,7 @@ fn test_push_front() ? {
|
||||
}
|
||||
|
||||
fn test_delete() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(0)
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
@ -119,7 +119,7 @@ fn test_delete() ? {
|
||||
}
|
||||
|
||||
fn test_iter() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
for i := 0; i < 10; i++ {
|
||||
list.push_back(i * 10)
|
||||
}
|
||||
@ -141,7 +141,7 @@ fn test_iter() ? {
|
||||
}
|
||||
|
||||
fn test_index() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
for i := 0; i < 10; i++ {
|
||||
list.push_back(i * 10)
|
||||
}
|
||||
@ -152,7 +152,7 @@ fn test_index() ? {
|
||||
}
|
||||
|
||||
fn test_str() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
@ -160,7 +160,7 @@ fn test_str() ? {
|
||||
}
|
||||
|
||||
fn test_array() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
@ -168,7 +168,7 @@ fn test_array() ? {
|
||||
}
|
||||
|
||||
fn test_string_array() ? {
|
||||
mut list := DoublyLinkedList<[]string>{}
|
||||
mut list := DoublyLinkedList[[]string]{}
|
||||
list.push_back(['a'])
|
||||
list.push_back(['b'])
|
||||
list.push_back(['c'])
|
||||
@ -176,7 +176,7 @@ fn test_string_array() ? {
|
||||
}
|
||||
|
||||
fn test_iteration_with_for() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
@ -188,7 +188,7 @@ fn test_iteration_with_for() ? {
|
||||
}
|
||||
|
||||
fn test_iterator() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
@ -201,7 +201,7 @@ fn test_iterator() ? {
|
||||
}
|
||||
|
||||
fn test_back_iterator() ? {
|
||||
mut list := DoublyLinkedList<int>{}
|
||||
mut list := DoublyLinkedList[int]{}
|
||||
list.push_back(1)
|
||||
list.push_back(2)
|
||||
list.push_back(3)
|
||||
|
@ -1,13 +1,13 @@
|
||||
module datatypes
|
||||
|
||||
// MinHeap is a binary minimum heap data structure.
|
||||
pub struct MinHeap<T> {
|
||||
pub struct MinHeap[T] {
|
||||
mut:
|
||||
data []T
|
||||
}
|
||||
|
||||
// insert adds an element to the heap.
|
||||
pub fn (mut heap MinHeap<T>) insert(item T) {
|
||||
pub fn (mut heap MinHeap[T]) insert(item T) {
|
||||
// push item to the end of the array
|
||||
heap.data << item
|
||||
// swap the new node with its parent until the heap is in order
|
||||
@ -21,7 +21,7 @@ pub fn (mut heap MinHeap<T>) insert(item T) {
|
||||
}
|
||||
|
||||
// pop removes the top-most element from the heap.
|
||||
pub fn (mut heap MinHeap<T>) pop() ?T {
|
||||
pub fn (mut heap MinHeap[T]) pop() ?T {
|
||||
if heap.data.len == 0 {
|
||||
return none
|
||||
} else if heap.data.len == 1 {
|
||||
@ -46,7 +46,7 @@ pub fn (mut heap MinHeap<T>) pop() ?T {
|
||||
}
|
||||
|
||||
// peek gets the top-most element from the heap without removing it.
|
||||
pub fn (heap MinHeap<T>) peek() ?T {
|
||||
pub fn (heap MinHeap[T]) peek() ?T {
|
||||
if heap.data.len == 0 {
|
||||
return none
|
||||
}
|
||||
@ -54,13 +54,13 @@ pub fn (heap MinHeap<T>) peek() ?T {
|
||||
}
|
||||
|
||||
// len returns the number of elements in the heap.
|
||||
pub fn (heap MinHeap<T>) len() int {
|
||||
pub fn (heap MinHeap[T]) len() int {
|
||||
return heap.data.len
|
||||
}
|
||||
|
||||
// left_child is a helper function that returns the index of the left
|
||||
// child given a parent idx, or none if there is no left child.
|
||||
fn (heap MinHeap<T>) left_child(idx int) ?int {
|
||||
fn (heap MinHeap[T]) left_child(idx int) ?int {
|
||||
child := 2 * idx + 1
|
||||
if child >= heap.data.len {
|
||||
return none
|
||||
@ -70,7 +70,7 @@ fn (heap MinHeap<T>) left_child(idx int) ?int {
|
||||
|
||||
// right_child is a helper function that returns the index of the right
|
||||
// child given a parent idx, or none if there is no right child.
|
||||
fn (heap MinHeap<T>) right_child(idx int) ?int {
|
||||
fn (heap MinHeap[T]) right_child(idx int) ?int {
|
||||
child := 2 * idx + 2
|
||||
if child >= heap.data.len {
|
||||
return none
|
||||
@ -79,6 +79,6 @@ fn (heap MinHeap<T>) right_child(idx int) ?int {
|
||||
}
|
||||
|
||||
// parent is a helper function that returns the parent index of the child.
|
||||
fn (heap MinHeap<T>) parent(idx int) int {
|
||||
fn (heap MinHeap[T]) parent(idx int) int {
|
||||
return (idx - 1) / 2
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
module datatypes
|
||||
|
||||
fn test_min_heap() ? {
|
||||
mut heap := MinHeap<int>{}
|
||||
mut heap := MinHeap[int]{}
|
||||
heap.insert(2)
|
||||
heap.insert(0)
|
||||
heap.insert(8)
|
||||
@ -28,7 +28,7 @@ fn (lhs Item) < (rhs Item) bool {
|
||||
}
|
||||
|
||||
fn test_min_heap_custom() ? {
|
||||
mut heap := MinHeap<Item>{}
|
||||
mut heap := MinHeap[Item]{}
|
||||
heap.insert(Item{'buz', 10})
|
||||
heap.insert(Item{'qux', 0})
|
||||
heap.insert(Item{'baz', 50})
|
||||
@ -46,7 +46,7 @@ fn test_min_heap_custom() ? {
|
||||
}
|
||||
|
||||
fn test_heap_len() ? {
|
||||
mut heap := MinHeap<int>{}
|
||||
mut heap := MinHeap[int]{}
|
||||
heap.insert(2)
|
||||
assert heap.len() == 1
|
||||
heap.insert(0)
|
||||
|
@ -1,38 +1,38 @@
|
||||
module datatypes
|
||||
|
||||
pub struct ListNode<T> {
|
||||
pub struct ListNode[T] {
|
||||
mut:
|
||||
data T
|
||||
next &ListNode<T> = unsafe { 0 }
|
||||
next &ListNode[T] = unsafe { 0 }
|
||||
}
|
||||
|
||||
pub struct LinkedList<T> {
|
||||
pub struct LinkedList[T] {
|
||||
mut:
|
||||
head &ListNode<T> = unsafe { 0 }
|
||||
head &ListNode[T] = unsafe { 0 }
|
||||
len int
|
||||
// Internal iter pointer for allowing safe modification
|
||||
// of the list while iterating. TODO: use an option
|
||||
// instead of a pointer to determine if it is initialized.
|
||||
iter &ListIter<T> = unsafe { 0 }
|
||||
iter &ListIter[T] = unsafe { 0 }
|
||||
}
|
||||
|
||||
// is_empty checks if the linked list is empty
|
||||
pub fn (list LinkedList<T>) is_empty() bool {
|
||||
pub fn (list LinkedList[T]) is_empty() bool {
|
||||
return list.len == 0
|
||||
}
|
||||
|
||||
// len returns the length of the linked list
|
||||
pub fn (list LinkedList<T>) len() int {
|
||||
pub fn (list LinkedList[T]) len() int {
|
||||
return list.len
|
||||
}
|
||||
|
||||
// first returns the first element of the linked list
|
||||
pub fn (list LinkedList<T>) first() ?T {
|
||||
pub fn (list LinkedList[T]) first() ?T {
|
||||
return if !list.is_empty() { list.head.data } else { error('Linked list is empty') }
|
||||
}
|
||||
|
||||
// last returns the last element of the linked list
|
||||
pub fn (list LinkedList<T>) last() ?T {
|
||||
pub fn (list LinkedList[T]) last() ?T {
|
||||
if unsafe { list.head == 0 } {
|
||||
return error('Linked list is empty')
|
||||
} else {
|
||||
@ -45,7 +45,7 @@ pub fn (list LinkedList<T>) last() ?T {
|
||||
}
|
||||
|
||||
// index returns the element at the given index of the linked list
|
||||
pub fn (list LinkedList<T>) index(idx int) ?T {
|
||||
pub fn (list LinkedList[T]) index(idx int) ?T {
|
||||
if unsafe { list.head == 0 } {
|
||||
return error('Linked list is empty')
|
||||
} else {
|
||||
@ -64,8 +64,8 @@ pub fn (list LinkedList<T>) index(idx int) ?T {
|
||||
}
|
||||
|
||||
// push adds an element to the end of the linked list
|
||||
pub fn (mut list LinkedList<T>) push(item T) {
|
||||
new_node := &ListNode<T>{
|
||||
pub fn (mut list LinkedList[T]) push(item T) {
|
||||
new_node := &ListNode[T]{
|
||||
data: item
|
||||
}
|
||||
if unsafe { list.head == 0 } {
|
||||
@ -82,7 +82,7 @@ pub fn (mut list LinkedList<T>) push(item T) {
|
||||
}
|
||||
|
||||
// pop removes the last element of the linked list
|
||||
pub fn (mut list LinkedList<T>) pop() ?T {
|
||||
pub fn (mut list LinkedList[T]) pop() ?T {
|
||||
if unsafe { list.head == 0 } {
|
||||
return error('Linked list is empty')
|
||||
}
|
||||
@ -105,7 +105,7 @@ pub fn (mut list LinkedList<T>) pop() ?T {
|
||||
}
|
||||
|
||||
// shift removes the first element of the linked list
|
||||
pub fn (mut list LinkedList<T>) shift() ?T {
|
||||
pub fn (mut list LinkedList[T]) shift() ?T {
|
||||
if unsafe { list.head == 0 } {
|
||||
return error('Linked list is empty')
|
||||
} else {
|
||||
@ -117,7 +117,7 @@ pub fn (mut list LinkedList<T>) shift() ?T {
|
||||
}
|
||||
|
||||
// insert adds an element to the linked list at the given index
|
||||
pub fn (mut list LinkedList<T>) insert(idx int, item T) ? {
|
||||
pub fn (mut list LinkedList[T]) insert(idx int, item T) ? {
|
||||
if idx < 0 || idx > list.len {
|
||||
return error('Index ${idx} out of bounds [0..${list.len}]')
|
||||
} else if list.len == 0 {
|
||||
@ -128,7 +128,7 @@ pub fn (mut list LinkedList<T>) insert(idx int, item T) ? {
|
||||
|
||||
if idx == 0 {
|
||||
// first node case
|
||||
list.head = &ListNode<T>{
|
||||
list.head = &ListNode[T]{
|
||||
data: item
|
||||
next: node
|
||||
}
|
||||
@ -136,7 +136,7 @@ pub fn (mut list LinkedList<T>) insert(idx int, item T) ? {
|
||||
for i := 0; i < idx - 1; i++ {
|
||||
node = node.next
|
||||
}
|
||||
node.next = &ListNode<T>{
|
||||
node.next = &ListNode[T]{
|
||||
data: item
|
||||
next: node.next
|
||||
}
|
||||
@ -145,17 +145,17 @@ pub fn (mut list LinkedList<T>) insert(idx int, item T) ? {
|
||||
}
|
||||
|
||||
// prepend adds an element to the beginning of the linked list (equivalent to insert(0, item))
|
||||
pub fn (mut list LinkedList<T>) prepend(item T) {
|
||||
pub fn (mut list LinkedList[T]) prepend(item T) {
|
||||
list.insert(0, item) or {}
|
||||
}
|
||||
|
||||
// str returns a string representation of the linked list
|
||||
pub fn (list LinkedList<T>) str() string {
|
||||
pub fn (list LinkedList[T]) str() string {
|
||||
return list.array().str()
|
||||
}
|
||||
|
||||
// array returns a array representation of the linked list
|
||||
pub fn (list LinkedList<T>) array() []T {
|
||||
pub fn (list LinkedList[T]) array() []T {
|
||||
mut result_array := []T{cap: list.len}
|
||||
mut node := list.head
|
||||
for unsafe { node != 0 } {
|
||||
@ -167,10 +167,10 @@ pub fn (list LinkedList<T>) array() []T {
|
||||
|
||||
// next implements the iteration interface to use LinkedList
|
||||
// with V's `for` loop syntax.
|
||||
pub fn (mut list LinkedList<T>) next() ?T {
|
||||
pub fn (mut list LinkedList[T]) next() ?T {
|
||||
if list.iter == unsafe { nil } {
|
||||
// initialize new iter object
|
||||
list.iter = &ListIter<T>{
|
||||
list.iter = &ListIter[T]{
|
||||
node: list.head
|
||||
}
|
||||
return list.next()
|
||||
@ -186,8 +186,8 @@ pub fn (mut list LinkedList<T>) next() ?T {
|
||||
}
|
||||
|
||||
// iterator returns a new iterator instance for the `list`.
|
||||
pub fn (mut list LinkedList<T>) iterator() ListIter<T> {
|
||||
return ListIter<T>{
|
||||
pub fn (mut list LinkedList[T]) iterator() ListIter[T] {
|
||||
return ListIter[T]{
|
||||
node: list.head
|
||||
}
|
||||
}
|
||||
@ -196,14 +196,14 @@ pub fn (mut list LinkedList<T>) iterator() ListIter<T> {
|
||||
// It can be used with V's `for x in iter {` construct.
|
||||
// One list can have multiple independent iterators, pointing to different positions/places in the list.
|
||||
// An iterator instance always traverses the list from start to finish.
|
||||
pub struct ListIter<T> {
|
||||
pub struct ListIter[T] {
|
||||
mut:
|
||||
node &ListNode<T> = unsafe { 0 }
|
||||
node &ListNode[T] = unsafe { 0 }
|
||||
}
|
||||
|
||||
// next returns the next element of the list, or `none` when the end of the list is reached.
|
||||
// It is called by V's `for x in iter{` on each iteration.
|
||||
pub fn (mut iter ListIter<T>) next() ?T {
|
||||
pub fn (mut iter ListIter[T]) next() ?T {
|
||||
if iter.node == unsafe { nil } {
|
||||
return none
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
module datatypes
|
||||
|
||||
fn test_is_empty() {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
assert list.is_empty() == true
|
||||
list.push(1)
|
||||
assert list.is_empty() == false
|
||||
}
|
||||
|
||||
fn test_len() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
assert list.len() == 0
|
||||
list.push(1)
|
||||
assert list.len() == 1
|
||||
@ -17,29 +17,29 @@ fn test_len() ? {
|
||||
}
|
||||
|
||||
fn test_first() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
assert list.first()? == 1
|
||||
list.push(2)
|
||||
assert list.first()? == 1
|
||||
list = LinkedList<int>{}
|
||||
list = LinkedList[int]{}
|
||||
list.first() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_last() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
assert list.last()? == 1
|
||||
list.push(2)
|
||||
assert list.last()? == 2
|
||||
list = LinkedList<int>{}
|
||||
list = LinkedList[int]{}
|
||||
list.last() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_index() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
assert list.index(0)? == 1
|
||||
list.push(2)
|
||||
@ -50,7 +50,7 @@ fn test_index() ? {
|
||||
}
|
||||
|
||||
fn test_push() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
assert list.last()? == 1
|
||||
list.push(2)
|
||||
@ -60,7 +60,7 @@ fn test_push() ? {
|
||||
}
|
||||
|
||||
fn test_pop() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
@ -68,13 +68,13 @@ fn test_pop() ? {
|
||||
list.push(4)
|
||||
assert list.pop()? == 4
|
||||
assert list.pop()? == 2
|
||||
list = LinkedList<int>{}
|
||||
list = LinkedList[int]{}
|
||||
list.pop() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_shift() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
@ -82,13 +82,13 @@ fn test_shift() ? {
|
||||
list.push(4)
|
||||
assert list.shift()? == 2
|
||||
assert list.shift()? == 3
|
||||
list = LinkedList<int>{}
|
||||
list = LinkedList[int]{}
|
||||
list.shift() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_insert() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
@ -97,7 +97,7 @@ fn test_insert() ? {
|
||||
}
|
||||
|
||||
fn test_prepend() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
@ -106,7 +106,7 @@ fn test_prepend() ? {
|
||||
}
|
||||
|
||||
fn test_str() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
@ -114,7 +114,7 @@ fn test_str() ? {
|
||||
}
|
||||
|
||||
fn test_array() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
@ -122,7 +122,7 @@ fn test_array() ? {
|
||||
}
|
||||
|
||||
fn test_linked_list_iterating_with_for() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
@ -134,7 +134,7 @@ fn test_linked_list_iterating_with_for() ? {
|
||||
}
|
||||
|
||||
fn test_linked_list_separate_iterators() ? {
|
||||
mut list := LinkedList<int>{}
|
||||
mut list := LinkedList[int]{}
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
|
@ -1,51 +1,51 @@
|
||||
module datatypes
|
||||
|
||||
pub struct Queue<T> {
|
||||
pub struct Queue[T] {
|
||||
mut:
|
||||
elements LinkedList<T>
|
||||
elements LinkedList[T]
|
||||
}
|
||||
|
||||
// is_empty checks if the queue is empty
|
||||
pub fn (queue Queue<T>) is_empty() bool {
|
||||
pub fn (queue Queue[T]) is_empty() bool {
|
||||
return queue.elements.is_empty()
|
||||
}
|
||||
|
||||
// len returns the length of the queue
|
||||
pub fn (queue Queue<T>) len() int {
|
||||
pub fn (queue Queue[T]) len() int {
|
||||
return queue.elements.len()
|
||||
}
|
||||
|
||||
// peek returns the head of the queue (first element added)
|
||||
pub fn (queue Queue<T>) peek() ?T {
|
||||
pub fn (queue Queue[T]) peek() ?T {
|
||||
return queue.elements.first()
|
||||
}
|
||||
|
||||
// last returns the tail of the queue (last element added)
|
||||
pub fn (queue Queue<T>) last() ?T {
|
||||
pub fn (queue Queue[T]) last() ?T {
|
||||
return queue.elements.last()
|
||||
}
|
||||
|
||||
// index returns the element at the given index of the queue
|
||||
pub fn (queue Queue<T>) index(idx int) ?T {
|
||||
pub fn (queue Queue[T]) index(idx int) ?T {
|
||||
return queue.elements.index(idx)
|
||||
}
|
||||
|
||||
// push adds an element to the tail of the queue
|
||||
pub fn (mut queue Queue<T>) push(item T) {
|
||||
pub fn (mut queue Queue[T]) push(item T) {
|
||||
queue.elements.push(item)
|
||||
}
|
||||
|
||||
// pop removes the element at the head of the queue and returns it
|
||||
pub fn (mut queue Queue<T>) pop() ?T {
|
||||
pub fn (mut queue Queue[T]) pop() ?T {
|
||||
return queue.elements.shift()
|
||||
}
|
||||
|
||||
// str returns a string representation of the queue
|
||||
pub fn (queue Queue<T>) str() string {
|
||||
pub fn (queue Queue[T]) str() string {
|
||||
return queue.elements.str()
|
||||
}
|
||||
|
||||
// array returns a array representation of the queue
|
||||
pub fn (queue Queue<T>) array() []T {
|
||||
pub fn (queue Queue[T]) array() []T {
|
||||
return queue.elements.array()
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
module datatypes
|
||||
|
||||
fn test_is_empty() {
|
||||
mut queue := Queue<int>{}
|
||||
mut queue := Queue[int]{}
|
||||
assert queue.is_empty() == true
|
||||
queue.push(1)
|
||||
assert queue.is_empty() == false
|
||||
}
|
||||
|
||||
fn test_len() ? {
|
||||
mut queue := Queue<int>{}
|
||||
mut queue := Queue[int]{}
|
||||
assert queue.len() == 0
|
||||
queue.push(1)
|
||||
assert queue.len() == 1
|
||||
@ -17,29 +17,29 @@ fn test_len() ? {
|
||||
}
|
||||
|
||||
fn test_peek() ? {
|
||||
mut queue := Queue<int>{}
|
||||
mut queue := Queue[int]{}
|
||||
queue.push(1)
|
||||
assert queue.peek()? == 1
|
||||
queue.push(2)
|
||||
assert queue.peek()? == 1
|
||||
queue = Queue<int>{}
|
||||
queue = Queue[int]{}
|
||||
queue.peek() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_last() ? {
|
||||
mut queue := Queue<int>{}
|
||||
mut queue := Queue[int]{}
|
||||
queue.push(1)
|
||||
assert queue.last()? == 1
|
||||
queue.push(2)
|
||||
assert queue.last()? == 2
|
||||
queue = Queue<int>{}
|
||||
queue = Queue[int]{}
|
||||
queue.last() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_index() ? {
|
||||
mut queue := Queue<int>{}
|
||||
mut queue := Queue[int]{}
|
||||
queue.push(1)
|
||||
assert queue.index(0)? == 1
|
||||
queue.push(2)
|
||||
@ -50,14 +50,14 @@ fn test_index() ? {
|
||||
}
|
||||
|
||||
fn test_push() ? {
|
||||
mut queue := Queue<int>{}
|
||||
mut queue := Queue[int]{}
|
||||
queue.push(1)
|
||||
queue.push(2)
|
||||
assert queue.peek()? == 1
|
||||
}
|
||||
|
||||
fn test_pop() ? {
|
||||
mut queue := Queue<int>{}
|
||||
mut queue := Queue[int]{}
|
||||
queue.push(1)
|
||||
queue.push(2)
|
||||
queue.push(3)
|
||||
@ -65,13 +65,13 @@ fn test_pop() ? {
|
||||
queue.push(4)
|
||||
assert queue.pop()? == 2
|
||||
assert queue.pop()? == 3
|
||||
queue = Queue<int>{}
|
||||
queue = Queue[int]{}
|
||||
queue.pop() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_array() ? {
|
||||
mut queue := Queue<int>{}
|
||||
mut queue := Queue[int]{}
|
||||
queue.push(1)
|
||||
queue.push(2)
|
||||
assert queue.array() == [1, 2]
|
||||
|
@ -3,7 +3,7 @@
|
||||
module datatypes
|
||||
|
||||
// RingBuffer - public struct that represents the ringbuffer
|
||||
pub struct RingBuffer<T> {
|
||||
pub struct RingBuffer[T] {
|
||||
mut:
|
||||
reader int // index of the tail where data is going to be read
|
||||
writer int // index of the head where data is going to be written
|
||||
@ -11,14 +11,14 @@ mut:
|
||||
}
|
||||
|
||||
// new_ringbuffer - creates an empty ringbuffer
|
||||
pub fn new_ringbuffer<T>(s int) RingBuffer<T> {
|
||||
return RingBuffer<T>{
|
||||
pub fn new_ringbuffer[T](s int) RingBuffer[T] {
|
||||
return RingBuffer[T]{
|
||||
content: []T{len: s + 1, cap: s + 1}
|
||||
} // increasing custom set size by one element in order to make ring flow possible, so that writer cannot equal reader before reader-index has been read.
|
||||
}
|
||||
|
||||
// push - adds an element to the ringbuffer
|
||||
pub fn (mut rb RingBuffer<T>) push(element T) ? {
|
||||
pub fn (mut rb RingBuffer[T]) push(element T) ? {
|
||||
if rb.is_full() {
|
||||
return error('Buffer overflow')
|
||||
} else {
|
||||
@ -28,7 +28,7 @@ pub fn (mut rb RingBuffer<T>) push(element T) ? {
|
||||
}
|
||||
|
||||
// pop - returns the oldest element of the buffer
|
||||
pub fn (mut rb RingBuffer<T>) pop() ?T {
|
||||
pub fn (mut rb RingBuffer[T]) pop() ?T {
|
||||
mut v := rb.content[rb.reader]
|
||||
if rb.is_empty() {
|
||||
return error('Buffer is empty')
|
||||
@ -39,14 +39,14 @@ pub fn (mut rb RingBuffer<T>) pop() ?T {
|
||||
}
|
||||
|
||||
// push_many - pushes an array to the buffer
|
||||
pub fn (mut rb RingBuffer<T>) push_many(elements []T) ? {
|
||||
pub fn (mut rb RingBuffer[T]) push_many(elements []T) ? {
|
||||
for v in elements {
|
||||
rb.push(v) or { return err }
|
||||
}
|
||||
}
|
||||
|
||||
// pop_many - returns a given number(n) of elements of the buffer starting with the oldest one
|
||||
pub fn (mut rb RingBuffer<T>) pop_many(n u64) ?[]T {
|
||||
pub fn (mut rb RingBuffer[T]) pop_many(n u64) ?[]T {
|
||||
mut elements := []T{}
|
||||
for _ in 0 .. n {
|
||||
elements << rb.pop() or { return err }
|
||||
@ -55,12 +55,12 @@ pub fn (mut rb RingBuffer<T>) pop_many(n u64) ?[]T {
|
||||
}
|
||||
|
||||
// is_empty - checks if the ringbuffer is empty
|
||||
pub fn (rb RingBuffer<T>) is_empty() bool {
|
||||
pub fn (rb RingBuffer[T]) is_empty() bool {
|
||||
return rb.reader == rb.writer // if reader equals writer it means that no value to read has been written before. It follows that the buffer is empty.
|
||||
}
|
||||
|
||||
// is_full - checks if the ringbuffer is full
|
||||
pub fn (rb RingBuffer<T>) is_full() bool {
|
||||
pub fn (rb RingBuffer[T]) is_full() bool {
|
||||
if rb.writer + 1 == rb.reader {
|
||||
return true
|
||||
} else if rb.writer == rb.content.len - 1 && rb.reader == 0 {
|
||||
@ -71,19 +71,19 @@ pub fn (rb RingBuffer<T>) is_full() bool {
|
||||
}
|
||||
|
||||
// capacity - returns the capacity of the ringbuffer
|
||||
pub fn (rb RingBuffer<T>) capacity() int {
|
||||
pub fn (rb RingBuffer[T]) capacity() int {
|
||||
return rb.content.cap - 1 // reduce by one because of the extra element explained in function `new_ringbuffer()`
|
||||
}
|
||||
|
||||
// clear - emptys the ringbuffer and all pushed elements
|
||||
pub fn (mut rb RingBuffer<T>) clear() {
|
||||
rb = RingBuffer<T>{
|
||||
pub fn (mut rb RingBuffer[T]) clear() {
|
||||
rb = RingBuffer[T]{
|
||||
content: []T{len: rb.content.len, cap: rb.content.cap}
|
||||
}
|
||||
}
|
||||
|
||||
// occupied - returns occupied capacity of the buffer.
|
||||
pub fn (rb RingBuffer<T>) occupied() int {
|
||||
pub fn (rb RingBuffer[T]) occupied() int {
|
||||
mut reader := rb.reader
|
||||
mut v := 0
|
||||
if rb.is_empty() {
|
||||
@ -103,20 +103,20 @@ pub fn (rb RingBuffer<T>) occupied() int {
|
||||
}
|
||||
|
||||
// remaining - returns remaining capacity of the buffer
|
||||
pub fn (rb RingBuffer<T>) remaining() int {
|
||||
pub fn (rb RingBuffer[T]) remaining() int {
|
||||
return rb.capacity() - rb.occupied()
|
||||
}
|
||||
|
||||
// head an tail-pointer move methods
|
||||
// these methods are not public, they are just an eneasement for handling the pointer-movement process.
|
||||
fn (mut rb RingBuffer<T>) move_reader() {
|
||||
fn (mut rb RingBuffer[T]) move_reader() {
|
||||
rb.reader++
|
||||
if rb.reader > rb.content.len - 1 {
|
||||
rb.reader = 0
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut rb RingBuffer<T>) move_writer() {
|
||||
fn (mut rb RingBuffer[T]) move_writer() {
|
||||
rb.writer++
|
||||
if rb.writer > rb.content.len - 1 {
|
||||
rb.writer = 0
|
||||
|
@ -1,7 +1,7 @@
|
||||
import datatypes
|
||||
|
||||
fn test_push_and_pop() {
|
||||
mut r := datatypes.new_ringbuffer<int>(2)
|
||||
mut r := datatypes.new_ringbuffer[int](2)
|
||||
|
||||
r.push(3) or { panic(err) }
|
||||
r.push(4) or { panic(err) }
|
||||
@ -18,7 +18,7 @@ fn test_push_and_pop() {
|
||||
}
|
||||
|
||||
fn test_clear_and_empty() {
|
||||
mut r := datatypes.new_ringbuffer<int>(4)
|
||||
mut r := datatypes.new_ringbuffer[int](4)
|
||||
r.push(3) or { panic(err) }
|
||||
r.push(4) or { panic(err) }
|
||||
|
||||
@ -31,7 +31,7 @@ fn test_clear_and_empty() {
|
||||
}
|
||||
|
||||
fn test_capacity_and_is_full() {
|
||||
mut r := datatypes.new_ringbuffer<int>(4)
|
||||
mut r := datatypes.new_ringbuffer[int](4)
|
||||
|
||||
assert r.capacity() == 4
|
||||
|
||||
@ -44,7 +44,7 @@ fn test_capacity_and_is_full() {
|
||||
}
|
||||
|
||||
fn test_occupied_and_remaining() {
|
||||
mut r := datatypes.new_ringbuffer<int>(4)
|
||||
mut r := datatypes.new_ringbuffer[int](4)
|
||||
|
||||
r.push(3) or { panic(err) }
|
||||
r.push(4) or { panic(err) }
|
||||
@ -53,7 +53,7 @@ fn test_occupied_and_remaining() {
|
||||
}
|
||||
|
||||
fn test_push_and_pop_many() {
|
||||
mut r := datatypes.new_ringbuffer<int>(4)
|
||||
mut r := datatypes.new_ringbuffer[int](4)
|
||||
a := [1, 2, 3, 4]
|
||||
r.push_many(a) or { panic(err) }
|
||||
|
||||
|
@ -1,27 +1,27 @@
|
||||
module datatypes
|
||||
|
||||
pub struct Set<T> {
|
||||
pub struct Set[T] {
|
||||
mut:
|
||||
elements map[T]u8
|
||||
}
|
||||
|
||||
// checks the element is exists.
|
||||
pub fn (set Set<T>) exists(element T) bool {
|
||||
pub fn (set Set[T]) exists(element T) bool {
|
||||
return element in set.elements
|
||||
}
|
||||
|
||||
// adds the element to set, if it is not present already.
|
||||
pub fn (mut set Set<T>) add(element T) {
|
||||
pub fn (mut set Set[T]) add(element T) {
|
||||
set.elements[element] = 1
|
||||
}
|
||||
|
||||
// removes the element from set.
|
||||
pub fn (mut set Set<T>) remove(element T) {
|
||||
pub fn (mut set Set[T]) remove(element T) {
|
||||
set.elements.delete(element)
|
||||
}
|
||||
|
||||
// pick returns an arbitrary element of set, if set is not empty.
|
||||
pub fn (set Set<T>) pick() ?T {
|
||||
pub fn (set Set[T]) pick() ?T {
|
||||
for k, _ in set.elements {
|
||||
return k
|
||||
}
|
||||
@ -29,31 +29,31 @@ pub fn (set Set<T>) pick() ?T {
|
||||
}
|
||||
|
||||
// rest returns the set consisting of all elements except for the arbitrary element.
|
||||
pub fn (mut set Set<T>) rest() ?[]T {
|
||||
pub fn (mut set Set[T]) rest() ?[]T {
|
||||
element := set.pick()?
|
||||
return set.elements.keys().filter(it != element)
|
||||
}
|
||||
|
||||
// pop returns an arbitrary element and deleting it from set.
|
||||
pub fn (mut set Set<T>) pop() ?T {
|
||||
pub fn (mut set Set[T]) pop() ?T {
|
||||
element := set.pick()?
|
||||
set.elements.delete(element)
|
||||
return element
|
||||
}
|
||||
|
||||
// delete all elements of set.
|
||||
pub fn (mut set Set<T>) clear() {
|
||||
pub fn (mut set Set[T]) clear() {
|
||||
set.elements = map[T]u8{}
|
||||
}
|
||||
|
||||
// equal checks whether the two given sets are equal (i.e. contain all and only the same elements).
|
||||
[deprecated: 'use set1<T> == set2<T> instead']
|
||||
pub fn (l Set<T>) equal(r Set<T>) bool {
|
||||
pub fn (l Set[T]) equal(r Set[T]) bool {
|
||||
return l == r
|
||||
}
|
||||
|
||||
// == checks whether the two given sets are equal (i.e. contain all and only the same elements).
|
||||
pub fn (l Set<T>) == (r Set<T>) bool {
|
||||
pub fn (l Set[T]) == (r Set[T]) bool {
|
||||
if l.elements.len != r.elements.len {
|
||||
return false
|
||||
}
|
||||
@ -66,31 +66,31 @@ pub fn (l Set<T>) == (r Set<T>) bool {
|
||||
}
|
||||
|
||||
// is_empty checks whether the set is empty or not.
|
||||
pub fn (set Set<T>) is_empty() bool {
|
||||
pub fn (set Set[T]) is_empty() bool {
|
||||
return set.size() == 0
|
||||
}
|
||||
|
||||
// size returns the number of elements in the set.
|
||||
pub fn (set Set<T>) size() int {
|
||||
pub fn (set Set[T]) size() int {
|
||||
return set.elements.len
|
||||
}
|
||||
|
||||
// copy returns a copy of all the elements in the set.
|
||||
pub fn (set Set<T>) copy() Set<T> {
|
||||
return Set<T>{
|
||||
pub fn (set Set[T]) copy() Set[T] {
|
||||
return Set[T]{
|
||||
elements: set.elements.clone()
|
||||
}
|
||||
}
|
||||
|
||||
// add_all adds the whole `elements` array to the set
|
||||
pub fn (mut set Set<T>) add_all(elements []T) {
|
||||
pub fn (mut set Set[T]) add_all(elements []T) {
|
||||
for element in elements {
|
||||
set.add(element)
|
||||
}
|
||||
}
|
||||
|
||||
// @union returns the union of the two sets.
|
||||
pub fn (l Set<T>) @union(r Set<T>) Set<T> {
|
||||
pub fn (l Set[T]) @union(r Set[T]) Set[T] {
|
||||
mut set := l
|
||||
for e, _ in r.elements {
|
||||
set.add(e)
|
||||
@ -99,7 +99,7 @@ pub fn (l Set<T>) @union(r Set<T>) Set<T> {
|
||||
}
|
||||
|
||||
// intersection returns the intersection of sets.
|
||||
pub fn (l Set<T>) intersection(r Set<T>) Set<T> {
|
||||
pub fn (l Set[T]) intersection(r Set[T]) Set[T] {
|
||||
mut set := l
|
||||
for e, _ in l.elements {
|
||||
if !r.exists(e) {
|
||||
@ -116,12 +116,12 @@ pub fn (l Set<T>) intersection(r Set<T>) Set<T> {
|
||||
|
||||
// difference returns the difference of sets.
|
||||
[deprecated: 'use set1<T> - set2<T> instead']
|
||||
pub fn (l Set<T>) difference(r Set<T>) Set<T> {
|
||||
pub fn (l Set[T]) difference(r Set[T]) Set[T] {
|
||||
return l - r
|
||||
}
|
||||
|
||||
// - returns the difference of sets.
|
||||
pub fn (l Set<T>) - (r Set<T>) Set<T> {
|
||||
pub fn (l Set[T]) - (r Set[T]) Set[T] {
|
||||
mut set := l
|
||||
for e, _ in l.elements {
|
||||
if r.exists(e) {
|
||||
@ -132,7 +132,7 @@ pub fn (l Set<T>) - (r Set<T>) Set<T> {
|
||||
}
|
||||
|
||||
// subset returns true if the set `r` is a subset of the set `l`.
|
||||
pub fn (l Set<T>) subset(r Set<T>) bool {
|
||||
pub fn (l Set[T]) subset(r Set[T]) bool {
|
||||
for e, _ in r.elements {
|
||||
if e !in l.elements {
|
||||
return false
|
||||
|
@ -1,14 +1,14 @@
|
||||
module datatypes
|
||||
|
||||
fn test_exists() {
|
||||
mut set := Set<string>{}
|
||||
mut set := Set[string]{}
|
||||
set.add('foo')
|
||||
assert set.exists('foo')
|
||||
assert set.exists('bar') == false
|
||||
}
|
||||
|
||||
fn test_remove() {
|
||||
mut set := Set<string>{}
|
||||
mut set := Set[string]{}
|
||||
set.remove('foo')
|
||||
set.add('foo')
|
||||
assert set.exists('foo')
|
||||
@ -17,28 +17,28 @@ fn test_remove() {
|
||||
}
|
||||
|
||||
fn test_size() {
|
||||
mut set := Set<string>{}
|
||||
mut set := Set[string]{}
|
||||
set.add('foo')
|
||||
set.add('foo')
|
||||
assert set.size() == 1
|
||||
}
|
||||
|
||||
fn test_pop() {
|
||||
mut set := Set<string>{}
|
||||
mut set := Set[string]{}
|
||||
set.add('foo')
|
||||
set.pop() or { return }
|
||||
assert set.exists('foo') == false
|
||||
}
|
||||
|
||||
fn test_clear() {
|
||||
mut set := Set<string>{}
|
||||
mut set := Set[string]{}
|
||||
set.add('foo')
|
||||
set.clear()
|
||||
assert set.size() == 0
|
||||
}
|
||||
|
||||
fn test_rest() {
|
||||
mut set := Set<string>{}
|
||||
mut set := Set[string]{}
|
||||
set.add('foo')
|
||||
set.add('bar')
|
||||
array := set.rest() or { return }
|
||||
@ -46,8 +46,8 @@ fn test_rest() {
|
||||
}
|
||||
|
||||
fn test_equal() {
|
||||
mut first_set := Set<string>{}
|
||||
mut second_set := Set<string>{}
|
||||
mut first_set := Set[string]{}
|
||||
mut second_set := Set[string]{}
|
||||
first_set.add('foo')
|
||||
assert second_set != first_set
|
||||
second_set.add('foo')
|
||||
@ -55,15 +55,15 @@ fn test_equal() {
|
||||
}
|
||||
|
||||
fn test_is_empty() {
|
||||
mut set := Set<string>{}
|
||||
mut set := Set[string]{}
|
||||
assert set.is_empty()
|
||||
set.add('foo')
|
||||
assert set.is_empty() == false
|
||||
}
|
||||
|
||||
fn test_union() {
|
||||
mut first_set := Set<string>{}
|
||||
mut second_set := Set<string>{}
|
||||
mut first_set := Set[string]{}
|
||||
mut second_set := Set[string]{}
|
||||
first_set.add_all(['b', 'c', 'd'])
|
||||
second_set.add_all(['a', 'e'])
|
||||
mut third_set := first_set.@union(second_set)
|
||||
@ -75,9 +75,9 @@ fn test_union() {
|
||||
}
|
||||
|
||||
fn test_intersection() {
|
||||
mut first_set := Set<string>{}
|
||||
mut first_set := Set[string]{}
|
||||
first_set.add_all(['foo', 'bar', 'baz'])
|
||||
mut second_set := Set<string>{}
|
||||
mut second_set := Set[string]{}
|
||||
second_set.add_all(['bar', 'baz', 'boo'])
|
||||
mut third_set := first_set.intersection(second_set)
|
||||
assert third_set.exists('foo') == false
|
||||
@ -87,8 +87,8 @@ fn test_intersection() {
|
||||
}
|
||||
|
||||
fn test_difference() {
|
||||
mut first_set := Set<string>{}
|
||||
mut second_set := Set<string>{}
|
||||
mut first_set := Set[string]{}
|
||||
mut second_set := Set[string]{}
|
||||
first_set.add_all(['foo', 'bar', 'baz'])
|
||||
second_set.add_all(['bar', 'baz', 'boo'])
|
||||
mut third_set := first_set - second_set
|
||||
@ -109,9 +109,9 @@ fn test_difference() {
|
||||
}
|
||||
|
||||
fn test_subset() {
|
||||
mut set := Set<string>{}
|
||||
mut set := Set[string]{}
|
||||
set.add_all(['a', 'b', 'c'])
|
||||
mut subset := Set<string>{}
|
||||
mut subset := Set[string]{}
|
||||
subset.add_all(['b', 'c'])
|
||||
assert set.subset(subset)
|
||||
}
|
||||
|
@ -1,41 +1,41 @@
|
||||
module datatypes
|
||||
|
||||
pub struct Stack<T> {
|
||||
pub struct Stack[T] {
|
||||
mut:
|
||||
elements []T
|
||||
}
|
||||
|
||||
// is_empty checks if the stack is empty
|
||||
pub fn (stack Stack<T>) is_empty() bool {
|
||||
pub fn (stack Stack[T]) is_empty() bool {
|
||||
return stack.elements.len == 0
|
||||
}
|
||||
|
||||
// len returns the length of the stack
|
||||
pub fn (stack Stack<T>) len() int {
|
||||
pub fn (stack Stack[T]) len() int {
|
||||
return stack.elements.len
|
||||
}
|
||||
|
||||
// peek returns the top of the stack
|
||||
pub fn (stack Stack<T>) peek() ?T {
|
||||
pub fn (stack Stack[T]) peek() ?T {
|
||||
return if !stack.is_empty() { stack.elements.last() } else { error('Stack is empty') }
|
||||
}
|
||||
|
||||
// push adds an element to the top of the stack
|
||||
pub fn (mut stack Stack<T>) push(item T) {
|
||||
pub fn (mut stack Stack[T]) push(item T) {
|
||||
stack.elements << item
|
||||
}
|
||||
|
||||
// pop removes the element at the top of the stack and returns it
|
||||
pub fn (mut stack Stack<T>) pop() ?T {
|
||||
pub fn (mut stack Stack[T]) pop() ?T {
|
||||
return if !stack.is_empty() { stack.elements.pop() } else { error('Stack is empty') }
|
||||
}
|
||||
|
||||
// str returns a string representation of the stack
|
||||
pub fn (stack Stack<T>) str() string {
|
||||
pub fn (stack Stack[T]) str() string {
|
||||
return stack.elements.str()
|
||||
}
|
||||
|
||||
// array returns a array representation of the stack
|
||||
pub fn (stack Stack<T>) array() []T {
|
||||
pub fn (stack Stack[T]) array() []T {
|
||||
return stack.elements
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import datatypes as dt
|
||||
|
||||
fn test_is_empty() {
|
||||
mut stack := dt.Stack<int>{}
|
||||
mut stack := dt.Stack[int]{}
|
||||
assert stack.is_empty() == true
|
||||
stack.push(1)
|
||||
assert stack.is_empty() == false
|
||||
}
|
||||
|
||||
fn test_len() ? {
|
||||
mut stack := dt.Stack<int>{}
|
||||
mut stack := dt.Stack[int]{}
|
||||
assert stack.len() == 0
|
||||
stack.push(1)
|
||||
assert stack.len() == 1
|
||||
@ -17,18 +17,18 @@ fn test_len() ? {
|
||||
}
|
||||
|
||||
fn test_peek() ? {
|
||||
mut stack := dt.Stack<int>{}
|
||||
mut stack := dt.Stack[int]{}
|
||||
stack.push(1)
|
||||
assert stack.peek()? == 1
|
||||
stack.push(2)
|
||||
assert stack.peek()? == 2
|
||||
stack = dt.Stack<int>{}
|
||||
stack = dt.Stack[int]{}
|
||||
stack.peek() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_push() ? {
|
||||
mut stack := dt.Stack<int>{}
|
||||
mut stack := dt.Stack[int]{}
|
||||
stack.push(1)
|
||||
assert stack.peek()? == 1
|
||||
stack.push(2)
|
||||
@ -38,7 +38,7 @@ fn test_push() ? {
|
||||
}
|
||||
|
||||
fn test_pop() ? {
|
||||
mut stack := dt.Stack<int>{}
|
||||
mut stack := dt.Stack[int]{}
|
||||
stack.push(1)
|
||||
stack.push(2)
|
||||
stack.push(3)
|
||||
@ -46,13 +46,13 @@ fn test_pop() ? {
|
||||
stack.push(4)
|
||||
assert stack.pop()? == 4
|
||||
assert stack.pop()? == 2
|
||||
stack = dt.Stack<int>{}
|
||||
stack = dt.Stack[int]{}
|
||||
stack.pop() or { return }
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_array() ? {
|
||||
mut stack := dt.Stack<int>{}
|
||||
mut stack := dt.Stack[int]{}
|
||||
stack.push(1)
|
||||
stack.push(2)
|
||||
assert stack.array() == [1, 2]
|
||||
|
@ -290,7 +290,7 @@ mut:
|
||||
|
||||
fn test_decode_to_struct() {
|
||||
text := 'id,bonus,amount,yes\r\n1,bomb,1,true\r\n2,rocket,1,false,\r\n3,lightning,2,2\r\n'
|
||||
arr := csv.decode<Test>(text)
|
||||
arr := csv.decode[Test](text)
|
||||
assert arr[0].id == 1
|
||||
assert arr[0].bonus == 'bomb'
|
||||
assert arr[0].amount == 1
|
||||
|
@ -3,7 +3,7 @@ module csv
|
||||
import strconv
|
||||
|
||||
// decode csv to struct
|
||||
pub fn decode<T>(data string) []T {
|
||||
pub fn decode[T](data string) []T {
|
||||
mut result := []T{}
|
||||
if data == '' {
|
||||
return result
|
||||
|
@ -33,7 +33,7 @@ pub fn sum32(data []u8) u32 {
|
||||
|
||||
// sum32_bytes returns a fnv1a hash of the struct `s`.
|
||||
[direct_array_access; inline]
|
||||
pub fn sum32_struct<T>(s &T) u32 {
|
||||
pub fn sum32_struct[T](s &T) u32 {
|
||||
bp := unsafe { &u8(s) }
|
||||
sz := int(sizeof(T))
|
||||
mut hash := fnv1a.fnv32_offset_basis
|
||||
@ -88,7 +88,7 @@ pub fn sum64_bytes(data &u8, data_len int) u64 {
|
||||
|
||||
// sum64_bytes returns a fnv1a hash of the struct `s`.
|
||||
[direct_array_access; inline]
|
||||
pub fn sum64_struct<T>(s &T) u64 {
|
||||
pub fn sum64_struct[T](s &T) u64 {
|
||||
bp := unsafe { &u8(s) }
|
||||
sz := int(sizeof(T))
|
||||
mut hash := fnv1a.fnv64_offset_basis
|
||||
|
@ -22,9 +22,9 @@ pub interface JS.Response {
|
||||
clone() JS.Response
|
||||
}
|
||||
|
||||
pub fn fetch(input string, init map[string]JS.Any) promise.Promise<JS.Response, JS.String> {
|
||||
pub fn fetch(input string, init map[string]JS.Any) promise.Promise[JS.Response, JS.String] {
|
||||
p_init := JS.Any(unsafe { nil })
|
||||
p := promise.Promise<JS.Response, String>{p_init}
|
||||
p := promise.Promise[JS.Response, String]{p_init}
|
||||
|
||||
#let obj = {}; for (let [key,val] of init.map) { obj[key] = val; }
|
||||
#p.promise = fetch(input.str,obj);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import json
|
||||
|
||||
struct Result<T> {
|
||||
struct Result[T] {
|
||||
ok bool
|
||||
result T
|
||||
}
|
||||
@ -10,14 +10,14 @@ struct User {
|
||||
username string
|
||||
}
|
||||
|
||||
fn func<T>() !T {
|
||||
fn func[T]() !T {
|
||||
text := '{"ok": true, "result":{"id":37467243, "username": "ciao"}}'
|
||||
a := json.decode(Result<T>, text)!
|
||||
a := json.decode(Result[T], text)!
|
||||
return a.result
|
||||
}
|
||||
|
||||
fn test_decode_with_generic_struct() {
|
||||
ret := func<User>()!
|
||||
ret := func[User]()!
|
||||
println(ret)
|
||||
assert ret.id == 37467243
|
||||
assert ret.username == 'ciao'
|
||||
|
@ -106,7 +106,7 @@ fn test_encode_decode_sumtype() {
|
||||
assert (game.other[4] as time.Time).unix_time() == (dec.other[4] as time.Time).unix_time()
|
||||
}
|
||||
|
||||
fn bar<T>(payload string) !Bar { // ?T doesn't work currently
|
||||
fn bar[T](payload string) !Bar { // ?T doesn't work currently
|
||||
result := json.decode(T, payload)!
|
||||
return result
|
||||
}
|
||||
@ -116,7 +116,7 @@ struct Bar {
|
||||
}
|
||||
|
||||
fn test_generic() {
|
||||
result := bar<Bar>('{"x":"test"}') or { Bar{} }
|
||||
result := bar[Bar]('{"x":"test"}') or { Bar{} }
|
||||
assert result.x == 'test'
|
||||
}
|
||||
|
||||
@ -332,17 +332,17 @@ fn test_nested_type() {
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo<T> {
|
||||
struct Foo[T] {
|
||||
pub:
|
||||
name string
|
||||
data T
|
||||
}
|
||||
|
||||
fn test_generic_struct() {
|
||||
foo_int := Foo<int>{'bar', 12}
|
||||
foo_int := Foo[int]{'bar', 12}
|
||||
foo_enc := json.encode(foo_int)
|
||||
assert foo_enc == '{"name":"bar","data":12}'
|
||||
foo_dec := json.decode(Foo<int>, foo_enc)!
|
||||
foo_dec := json.decode(Foo[int], foo_enc)!
|
||||
assert foo_dec.name == 'bar'
|
||||
assert foo_dec.data == 12
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
module maps
|
||||
|
||||
// filter filters map entries by the given predicate function
|
||||
pub fn filter<K, V>(m map[K]V, f fn (key K, val V) bool) map[K]V {
|
||||
pub fn filter[K, V](m map[K]V, f fn (key K, val V) bool) map[K]V {
|
||||
mut mp := map[K]V{}
|
||||
|
||||
for k, v in m {
|
||||
@ -14,7 +14,7 @@ pub fn filter<K, V>(m map[K]V, f fn (key K, val V) bool) map[K]V {
|
||||
}
|
||||
|
||||
// to_array maps map entries into one-dimensional array
|
||||
pub fn to_array<K, V, I>(m map[K]V, f fn (key K, val V) I) []I {
|
||||
pub fn to_array[K, V, I](m map[K]V, f fn (key K, val V) I) []I {
|
||||
mut a := []I{cap: m.len}
|
||||
|
||||
for k, v in m {
|
||||
@ -25,7 +25,7 @@ pub fn to_array<K, V, I>(m map[K]V, f fn (key K, val V) I) []I {
|
||||
}
|
||||
|
||||
// flat_map maps map entries into arrays and flattens into a one-dimensional array
|
||||
pub fn flat_map<K, V, I>(m map[K]V, f fn (key K, val V) []I) []I {
|
||||
pub fn flat_map[K, V, I](m map[K]V, f fn (key K, val V) []I) []I {
|
||||
mut a := []I{cap: m.len}
|
||||
|
||||
for k, v in m {
|
||||
@ -36,7 +36,7 @@ pub fn flat_map<K, V, I>(m map[K]V, f fn (key K, val V) []I) []I {
|
||||
}
|
||||
|
||||
// to_map maps map entries into new entries and constructs a new map
|
||||
pub fn to_map<K, V, X, Y>(m map[K]V, f fn (key K, val V) (X, Y)) map[X]Y {
|
||||
pub fn to_map[K, V, X, Y](m map[K]V, f fn (key K, val V) (X, Y)) map[X]Y {
|
||||
mut mp := map[X]Y{}
|
||||
|
||||
for k, v in m {
|
||||
@ -48,7 +48,7 @@ pub fn to_map<K, V, X, Y>(m map[K]V, f fn (key K, val V) (X, Y)) map[X]Y {
|
||||
}
|
||||
|
||||
// invert returns a new map, created by swapping key to value and vice versa for each entry.
|
||||
pub fn invert<K, V>(m map[K]V) map[V]K {
|
||||
pub fn invert[K, V](m map[K]V) map[V]K {
|
||||
mut mp := map[V]K{}
|
||||
|
||||
for k, v in m {
|
||||
@ -59,7 +59,7 @@ pub fn invert<K, V>(m map[K]V) map[V]K {
|
||||
}
|
||||
|
||||
// from_array maps array into map with index to element per entry
|
||||
pub fn from_array<T>(array []T) map[int]T {
|
||||
pub fn from_array[T](array []T) map[int]T {
|
||||
mut mp := map[int]T{}
|
||||
|
||||
for i, e in array {
|
||||
|
@ -42,7 +42,7 @@ fn test_flat_map() {
|
||||
4: [5, 6]
|
||||
7: [8, 9]
|
||||
}
|
||||
assert flat_map<int, []int, int>(m1, fn (k int, v []int) []int {
|
||||
assert flat_map[int, []int, int](m1, fn (k int, v []int) []int {
|
||||
mut a := [k]
|
||||
a << v
|
||||
return a
|
||||
@ -58,7 +58,7 @@ fn test_to_map() {
|
||||
4: '4'
|
||||
5: '5'
|
||||
}
|
||||
assert to_map<int, string, string, int>(m1, fn (k int, v string) (string, int) {
|
||||
assert to_map[int, string, string, int](m1, fn (k int, v string) (string, int) {
|
||||
return v, k
|
||||
}) == {
|
||||
'0': 0
|
||||
|
@ -5,18 +5,18 @@ module math
|
||||
|
||||
// min returns the minimum of `a` and `b`
|
||||
[inline]
|
||||
pub fn min<T>(a T, b T) T {
|
||||
pub fn min[T](a T, b T) T {
|
||||
return if a < b { a } else { b }
|
||||
}
|
||||
|
||||
// max returns the maximum of `a` and `b`
|
||||
[inline]
|
||||
pub fn max<T>(a T, b T) T {
|
||||
pub fn max[T](a T, b T) T {
|
||||
return if a > b { a } else { b }
|
||||
}
|
||||
|
||||
// abs returns the absolute value of `a`
|
||||
[inline]
|
||||
pub fn abs<T>(a T) T {
|
||||
pub fn abs[T](a T) T {
|
||||
return if a < 0 { -a } else { a }
|
||||
}
|
||||
|
@ -6,20 +6,20 @@ module mathutil
|
||||
[deprecated: 'use math.min instead']
|
||||
[deprecated_after: '2022-01-19']
|
||||
[inline]
|
||||
pub fn min<T>(a T, b T) T {
|
||||
pub fn min[T](a T, b T) T {
|
||||
return if a < b { a } else { b }
|
||||
}
|
||||
|
||||
[deprecated: 'use math.max instead']
|
||||
[deprecated_after: '2022-01-19']
|
||||
[inline]
|
||||
pub fn max<T>(a T, b T) T {
|
||||
pub fn max[T](a T, b T) T {
|
||||
return if a > b { a } else { b }
|
||||
}
|
||||
|
||||
[deprecated: 'use math.abs instead']
|
||||
[deprecated_after: '2022-01-19']
|
||||
[inline]
|
||||
pub fn abs<T>(a T) T {
|
||||
pub fn abs[T](a T) T {
|
||||
return if a > 0 { a } else { -a }
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import math
|
||||
// Frequency of a given number
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/frequency-distribution.html
|
||||
pub fn freq<T>(data []T, val T) int {
|
||||
pub fn freq[T](data []T, val T) int {
|
||||
if data.len == 0 {
|
||||
return 0
|
||||
}
|
||||
@ -23,7 +23,7 @@ pub fn freq<T>(data []T, val T) int {
|
||||
// of the given input array, sum(data)/data.len
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/central-measures.html
|
||||
pub fn mean<T>(data []T) T {
|
||||
pub fn mean[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -38,7 +38,7 @@ pub fn mean<T>(data []T) T {
|
||||
// of the given input array, product(data)**1/data.len
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/numbers/geometric-mean.html
|
||||
pub fn geometric_mean<T>(data []T) T {
|
||||
pub fn geometric_mean[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -53,7 +53,7 @@ pub fn geometric_mean<T>(data []T) T {
|
||||
// of the given input array
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/numbers/harmonic-mean.html
|
||||
pub fn harmonic_mean<T>(data []T) T {
|
||||
pub fn harmonic_mean[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -67,7 +67,7 @@ pub fn harmonic_mean<T>(data []T) T {
|
||||
// median returns the middlemost value of the given input array ( input array is assumed to be sorted )
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/central-measures.html
|
||||
pub fn median<T>(sorted_data []T) T {
|
||||
pub fn median[T](sorted_data []T) T {
|
||||
if sorted_data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -82,7 +82,7 @@ pub fn median<T>(sorted_data []T) T {
|
||||
// mode calculates the highest occuring value of the given input array
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/central-measures.html
|
||||
pub fn mode<T>(data []T) T {
|
||||
pub fn mode[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -102,7 +102,7 @@ pub fn mode<T>(data []T) T {
|
||||
// rms, Root Mean Square, calculates the sqrt of the mean of the squares of the given input array
|
||||
// Based on
|
||||
// https://en.wikipedia.org/wiki/Root_mean_square
|
||||
pub fn rms<T>(data []T) T {
|
||||
pub fn rms[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -118,19 +118,19 @@ pub fn rms<T>(data []T) T {
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
pub fn population_variance<T>(data []T) T {
|
||||
pub fn population_variance[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
data_mean := mean<T>(data)
|
||||
return population_variance_mean<T>(data, data_mean)
|
||||
data_mean := mean[T](data)
|
||||
return population_variance_mean[T](data, data_mean)
|
||||
}
|
||||
|
||||
// population_variance_mean is the Measure of Dispersion / Spread
|
||||
// of the given input array, with the provided mean
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
pub fn population_variance_mean<T>(data []T, mean T) T {
|
||||
pub fn population_variance_mean[T](data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -145,18 +145,18 @@ pub fn population_variance_mean<T>(data []T, mean T) T {
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
pub fn sample_variance<T>(data []T) T {
|
||||
pub fn sample_variance[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
data_mean := mean<T>(data)
|
||||
return sample_variance_mean<T>(data, data_mean)
|
||||
data_mean := mean[T](data)
|
||||
return sample_variance_mean[T](data, data_mean)
|
||||
}
|
||||
|
||||
// sample_variance calculates the spread of dataset around the provided mean
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
pub fn sample_variance_mean<T>(data []T, mean T) T {
|
||||
pub fn sample_variance_mean[T](data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -171,22 +171,22 @@ pub fn sample_variance_mean<T>(data []T, mean T) T {
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
pub fn population_stddev<T>(data []T) T {
|
||||
pub fn population_stddev[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
return math.sqrt(population_variance<T>(data))
|
||||
return math.sqrt(population_variance[T](data))
|
||||
}
|
||||
|
||||
// population_stddev_mean calculates how spread out the dataset is, with the provide mean
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
pub fn population_stddev_mean<T>(data []T, mean T) T {
|
||||
pub fn population_stddev_mean[T](data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
return T(math.sqrt(f64(population_variance_mean<T>(data, mean))))
|
||||
return T(math.sqrt(f64(population_variance_mean[T](data, mean))))
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
@ -194,11 +194,11 @@ pub fn population_stddev_mean<T>(data []T, mean T) T {
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
pub fn sample_stddev<T>(data []T) T {
|
||||
pub fn sample_stddev[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
return T(math.sqrt(f64(sample_variance<T>(data))))
|
||||
return T(math.sqrt(f64(sample_variance[T](data))))
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
@ -206,29 +206,29 @@ pub fn sample_stddev<T>(data []T) T {
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
pub fn sample_stddev_mean<T>(data []T, mean T) T {
|
||||
pub fn sample_stddev_mean[T](data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
return T(math.sqrt(f64(sample_variance_mean<T>(data, mean))))
|
||||
return T(math.sqrt(f64(sample_variance_mean[T](data, mean))))
|
||||
}
|
||||
|
||||
// absdev calculates the average distance between each data point and the mean
|
||||
// Based on
|
||||
// https://en.wikipedia.org/wiki/Average_absolute_deviation
|
||||
[inline]
|
||||
pub fn absdev<T>(data []T) T {
|
||||
pub fn absdev[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
data_mean := mean<T>(data)
|
||||
return absdev_mean<T>(data, data_mean)
|
||||
data_mean := mean[T](data)
|
||||
return absdev_mean[T](data, data_mean)
|
||||
}
|
||||
|
||||
// absdev_mean calculates the average distance between each data point and the provided mean
|
||||
// Based on
|
||||
// https://en.wikipedia.org/wiki/Average_absolute_deviation
|
||||
pub fn absdev_mean<T>(data []T, mean T) T {
|
||||
pub fn absdev_mean[T](data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -241,16 +241,16 @@ pub fn absdev_mean<T>(data []T, mean T) T {
|
||||
|
||||
// tts, Sum of squares, calculates the sum over all squared differences between values and overall mean
|
||||
[inline]
|
||||
pub fn tss<T>(data []T) T {
|
||||
pub fn tss[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
data_mean := mean<T>(data)
|
||||
return tss_mean<T>(data, data_mean)
|
||||
data_mean := mean[T](data)
|
||||
return tss_mean[T](data, data_mean)
|
||||
}
|
||||
|
||||
// tts_mean, Sum of squares, calculates the sum over all squared differences between values and the provided mean
|
||||
pub fn tss_mean<T>(data []T, mean T) T {
|
||||
pub fn tss_mean[T](data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -262,7 +262,7 @@ pub fn tss_mean<T>(data []T, mean T) T {
|
||||
}
|
||||
|
||||
// min finds the minimum value from the dataset
|
||||
pub fn min<T>(data []T) T {
|
||||
pub fn min[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -276,7 +276,7 @@ pub fn min<T>(data []T) T {
|
||||
}
|
||||
|
||||
// max finds the maximum value from the dataset
|
||||
pub fn max<T>(data []T) T {
|
||||
pub fn max[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -290,7 +290,7 @@ pub fn max<T>(data []T) T {
|
||||
}
|
||||
|
||||
// minmax finds the minimum and maximum value from the dataset
|
||||
pub fn minmax<T>(data []T) (T, T) {
|
||||
pub fn minmax[T](data []T) (T, T) {
|
||||
if data.len == 0 {
|
||||
return T(0), T(0)
|
||||
}
|
||||
@ -308,7 +308,7 @@ pub fn minmax<T>(data []T) (T, T) {
|
||||
}
|
||||
|
||||
// min_index finds the first index of the minimum value
|
||||
pub fn min_index<T>(data []T) int {
|
||||
pub fn min_index[T](data []T) int {
|
||||
if data.len == 0 {
|
||||
return 0
|
||||
}
|
||||
@ -324,7 +324,7 @@ pub fn min_index<T>(data []T) int {
|
||||
}
|
||||
|
||||
// max_index finds the first index of the maximum value
|
||||
pub fn max_index<T>(data []T) int {
|
||||
pub fn max_index[T](data []T) int {
|
||||
if data.len == 0 {
|
||||
return 0
|
||||
}
|
||||
@ -340,7 +340,7 @@ pub fn max_index<T>(data []T) int {
|
||||
}
|
||||
|
||||
// minmax_index finds the first index of the minimum and maximum value
|
||||
pub fn minmax_index<T>(data []T) (int, int) {
|
||||
pub fn minmax_index[T](data []T) (int, int) {
|
||||
if data.len == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
@ -365,26 +365,26 @@ pub fn minmax_index<T>(data []T) (int, int) {
|
||||
// Range ( Maximum - Minimum ) of the given input array
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/range.html
|
||||
pub fn range<T>(data []T) T {
|
||||
pub fn range[T](data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
min, max := minmax<T>(data)
|
||||
min, max := minmax[T](data)
|
||||
return max - min
|
||||
}
|
||||
|
||||
// covariance calculates directional association between datasets
|
||||
// positive value denotes variables move in same direction and negative denotes variables move in opposite directions
|
||||
[inline]
|
||||
pub fn covariance<T>(data1 []T, data2 []T) T {
|
||||
mean1 := mean<T>(data1)
|
||||
mean2 := mean<T>(data2)
|
||||
return covariance_mean<T>(data1, data2, mean1, mean2)
|
||||
pub fn covariance[T](data1 []T, data2 []T) T {
|
||||
mean1 := mean[T](data1)
|
||||
mean2 := mean[T](data2)
|
||||
return covariance_mean[T](data1, data2, mean1, mean2)
|
||||
}
|
||||
|
||||
// covariance_mean computes the covariance of a dataset with means provided
|
||||
// the recurrence relation
|
||||
pub fn covariance_mean<T>(data1 []T, data2 []T, mean1 T, mean2 T) T {
|
||||
pub fn covariance_mean[T](data1 []T, data2 []T, mean1 T, mean2 T) T {
|
||||
n := int(math.min(data1.len, data2.len))
|
||||
if n == 0 {
|
||||
return T(0)
|
||||
@ -401,15 +401,15 @@ pub fn covariance_mean<T>(data1 []T, data2 []T, mean1 T, mean2 T) T {
|
||||
// lag1_autocorrelation_mean calculates the correlation between values that are one time period apart
|
||||
// of a dataset, based on the mean
|
||||
[inline]
|
||||
pub fn lag1_autocorrelation<T>(data []T) T {
|
||||
data_mean := mean<T>(data)
|
||||
return lag1_autocorrelation_mean<T>(data, data_mean)
|
||||
pub fn lag1_autocorrelation[T](data []T) T {
|
||||
data_mean := mean[T](data)
|
||||
return lag1_autocorrelation_mean[T](data, data_mean)
|
||||
}
|
||||
|
||||
// lag1_autocorrelation_mean calculates the correlation between values that are one time period apart
|
||||
// of a dataset, using
|
||||
// the recurrence relation
|
||||
pub fn lag1_autocorrelation_mean<T>(data []T, mean T) T {
|
||||
pub fn lag1_autocorrelation_mean[T](data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
@ -426,15 +426,15 @@ pub fn lag1_autocorrelation_mean<T>(data []T, mean T) T {
|
||||
|
||||
// kurtosis calculates the measure of the 'tailedness' of the data by finding mean and standard of deviation
|
||||
[inline]
|
||||
pub fn kurtosis<T>(data []T) T {
|
||||
data_mean := mean<T>(data)
|
||||
sd := population_stddev_mean<T>(data, data_mean)
|
||||
return kurtosis_mean_stddev<T>(data, data_mean, sd)
|
||||
pub fn kurtosis[T](data []T) T {
|
||||
data_mean := mean[T](data)
|
||||
sd := population_stddev_mean[T](data, data_mean)
|
||||
return kurtosis_mean_stddev[T](data, data_mean, sd)
|
||||
}
|
||||
|
||||
// kurtosis_mean_stddev calculates the measure of the 'tailedness' of the data
|
||||
// using the fourth moment the deviations, normalized by the sd
|
||||
pub fn kurtosis_mean_stddev<T>(data []T, mean T, sd T) T {
|
||||
pub fn kurtosis_mean_stddev[T](data []T, mean T, sd T) T {
|
||||
mut avg := T(0) // find the fourth moment the deviations, normalized by the sd
|
||||
/*
|
||||
we use a recurrence relation to stably update a running value so
|
||||
@ -449,14 +449,14 @@ pub fn kurtosis_mean_stddev<T>(data []T, mean T, sd T) T {
|
||||
|
||||
// skew calculates the mean and standard of deviation to find the skew from the data
|
||||
[inline]
|
||||
pub fn skew<T>(data []T) T {
|
||||
data_mean := mean<T>(data)
|
||||
sd := population_stddev_mean<T>(data, data_mean)
|
||||
return skew_mean_stddev<T>(data, data_mean, sd)
|
||||
pub fn skew[T](data []T) T {
|
||||
data_mean := mean[T](data)
|
||||
sd := population_stddev_mean[T](data, data_mean)
|
||||
return skew_mean_stddev[T](data, data_mean, sd)
|
||||
}
|
||||
|
||||
// skew_mean_stddev calculates the skewness of data
|
||||
pub fn skew_mean_stddev<T>(data []T, mean T, sd T) T {
|
||||
pub fn skew_mean_stddev[T](data []T, mean T, sd T) T {
|
||||
mut skew := T(0) // find the sum of the cubed deviations, normalized by the sd.
|
||||
/*
|
||||
we use a recurrence relation to stably update a running value so
|
||||
@ -469,7 +469,7 @@ pub fn skew_mean_stddev<T>(data []T, mean T, sd T) T {
|
||||
return skew
|
||||
}
|
||||
|
||||
pub fn quantile<T>(sorted_data []T, f T) T {
|
||||
pub fn quantile[T](sorted_data []T, f T) T {
|
||||
if sorted_data.len == 0 {
|
||||
return T(0)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import net.conv
|
||||
|
||||
fn check<T>(f fn (a T) T, finv fn (b T) T, x T) {
|
||||
fn check[T](f fn (a T) T, finv fn (b T) T, x T) {
|
||||
a := f(x)
|
||||
b := finv(a)
|
||||
assert b == x
|
||||
|
@ -588,7 +588,7 @@ fn error_size_of_type_0() IError {
|
||||
}
|
||||
|
||||
// read_struct reads a single struct of type `T`
|
||||
pub fn (mut f File) read_struct<T>(mut t T) ! {
|
||||
pub fn (mut f File) read_struct[T](mut t T) ! {
|
||||
if !f.is_opened {
|
||||
return error_file_not_opened()
|
||||
}
|
||||
@ -603,7 +603,7 @@ pub fn (mut f File) read_struct<T>(mut t T) ! {
|
||||
}
|
||||
|
||||
// read_struct_at reads a single struct of type `T` at position specified in file
|
||||
pub fn (mut f File) read_struct_at<T>(mut t T, pos u64) ! {
|
||||
pub fn (mut f File) read_struct_at[T](mut t T, pos u64) ! {
|
||||
if !f.is_opened {
|
||||
return error_file_not_opened()
|
||||
}
|
||||
@ -634,7 +634,7 @@ pub fn (mut f File) read_struct_at<T>(mut t T, pos u64) ! {
|
||||
}
|
||||
|
||||
// read_raw reads and returns a single instance of type `T`
|
||||
pub fn (mut f File) read_raw<T>() !T {
|
||||
pub fn (mut f File) read_raw[T]() !T {
|
||||
if !f.is_opened {
|
||||
return error_file_not_opened()
|
||||
}
|
||||
@ -651,7 +651,7 @@ pub fn (mut f File) read_raw<T>() !T {
|
||||
}
|
||||
|
||||
// read_raw_at reads and returns a single instance of type `T` starting at file byte offset `pos`
|
||||
pub fn (mut f File) read_raw_at<T>(pos u64) !T {
|
||||
pub fn (mut f File) read_raw_at[T](pos u64) !T {
|
||||
if !f.is_opened {
|
||||
return error_file_not_opened()
|
||||
}
|
||||
@ -697,7 +697,7 @@ pub fn (mut f File) read_raw_at<T>(pos u64) !T {
|
||||
}
|
||||
|
||||
// write_struct writes a single struct of type `T`
|
||||
pub fn (mut f File) write_struct<T>(t &T) ! {
|
||||
pub fn (mut f File) write_struct[T](t &T) ! {
|
||||
if !f.is_opened {
|
||||
return error_file_not_opened()
|
||||
}
|
||||
@ -716,7 +716,7 @@ pub fn (mut f File) write_struct<T>(t &T) ! {
|
||||
}
|
||||
|
||||
// write_struct_at writes a single struct of type `T` at position specified in file
|
||||
pub fn (mut f File) write_struct_at<T>(t &T, pos u64) ! {
|
||||
pub fn (mut f File) write_struct_at[T](t &T, pos u64) ! {
|
||||
if !f.is_opened {
|
||||
return error_file_not_opened()
|
||||
}
|
||||
@ -753,7 +753,7 @@ pub fn (mut f File) write_struct_at<T>(t &T, pos u64) ! {
|
||||
// TODO `write_raw[_at]` implementations are copy-pasted from `write_struct[_at]`
|
||||
|
||||
// write_raw writes a single instance of type `T`
|
||||
pub fn (mut f File) write_raw<T>(t &T) ! {
|
||||
pub fn (mut f File) write_raw[T](t &T) ! {
|
||||
if !f.is_opened {
|
||||
return error_file_not_opened()
|
||||
}
|
||||
@ -772,7 +772,7 @@ pub fn (mut f File) write_raw<T>(t &T) ! {
|
||||
}
|
||||
|
||||
// write_raw_at writes a single instance of type `T` starting at file byte offset `pos`
|
||||
pub fn (mut f File) write_raw_at<T>(t &T, pos u64) ! {
|
||||
pub fn (mut f File) write_raw_at[T](t &T, pos u64) ! {
|
||||
if !f.is_opened {
|
||||
return error_file_not_opened()
|
||||
}
|
||||
|
@ -282,10 +282,10 @@ fn test_read_raw() {
|
||||
f.write_raw(another_permission)!
|
||||
f.close()
|
||||
f = os.open_file(tfile, 'r')!
|
||||
p := f.read_raw<Point>()!
|
||||
b := f.read_raw<u8>()!
|
||||
c := f.read_raw<Color>()!
|
||||
x := f.read_raw<Permissions>()!
|
||||
p := f.read_raw[Point]()!
|
||||
b := f.read_raw[u8]()!
|
||||
c := f.read_raw[Color]()!
|
||||
x := f.read_raw[Permissions]()!
|
||||
f.close()
|
||||
|
||||
assert p == another_point
|
||||
@ -304,13 +304,13 @@ fn test_read_raw_at() {
|
||||
f.close()
|
||||
f = os.open_file(tfile, 'r')!
|
||||
mut at := u64(3)
|
||||
p := f.read_raw_at<Point>(at)!
|
||||
p := f.read_raw_at[Point](at)!
|
||||
at += sizeof(Point)
|
||||
b := f.read_raw_at<u8>(at)!
|
||||
b := f.read_raw_at[u8](at)!
|
||||
at += sizeof(u8)
|
||||
c := f.read_raw_at<Color>(at)!
|
||||
c := f.read_raw_at[Color](at)!
|
||||
at += sizeof(Color)
|
||||
x := f.read_raw_at<Permissions>(at)!
|
||||
x := f.read_raw_at[Permissions](at)!
|
||||
at += sizeof(Permissions)
|
||||
f.close()
|
||||
|
||||
@ -322,10 +322,10 @@ fn test_read_raw_at() {
|
||||
|
||||
fn test_read_raw_at_negative_pos() {
|
||||
mut f := os.open_file(tfile, 'r')!
|
||||
if _ := f.read_raw_at<Point>(-1) {
|
||||
if _ := f.read_raw_at[Point](-1) {
|
||||
assert false
|
||||
}
|
||||
f.read_raw_at<Point>(-234) or { assert err.msg() == 'Invalid argument' }
|
||||
f.read_raw_at[Point](-234) or { assert err.msg() == 'Invalid argument' }
|
||||
f.close()
|
||||
}
|
||||
|
||||
@ -342,11 +342,11 @@ fn test_seek() {
|
||||
//
|
||||
f.seek(i64(sizeof(Point)), .start)!
|
||||
assert f.tell()! == sizeof(Point)
|
||||
b := f.read_raw<u8>()!
|
||||
b := f.read_raw[u8]()!
|
||||
assert b == another_byte
|
||||
|
||||
f.seek(i64(sizeof(Color)), .current)!
|
||||
x := f.read_raw<Permissions>()!
|
||||
x := f.read_raw[Permissions]()!
|
||||
assert x == another_permission
|
||||
//
|
||||
f.close()
|
||||
|
@ -598,7 +598,7 @@ pub fn get_raw_stdin() []u8 {
|
||||
}
|
||||
|
||||
// read_file_array reads an array of `T` values from file `path`.
|
||||
pub fn read_file_array<T>(path string) []T {
|
||||
pub fn read_file_array[T](path string) []T {
|
||||
a := T{}
|
||||
tsize := int(sizeof(a))
|
||||
// prepare for reading, get current file size
|
||||
|
@ -706,7 +706,7 @@ fn test_write_file_array_structs() {
|
||||
arr[i] = IntPoint{65 + i, 65 + i + 10}
|
||||
}
|
||||
os.write_file_array(fpath, arr) or { panic(err) }
|
||||
rarr := os.read_file_array<IntPoint>(fpath)
|
||||
rarr := os.read_file_array[IntPoint](fpath)
|
||||
assert rarr == arr
|
||||
assert rarr.len == maxn
|
||||
// eprintln( rarr.str().replace('\n', ' ').replace('},', '},\n'))
|
||||
|
@ -36,7 +36,7 @@ pub:
|
||||
}
|
||||
|
||||
// validate_for is a helper function for validating the configuration struct for the given array.
|
||||
pub fn (config ShuffleConfigStruct) validate_for<T>(a []T) ! {
|
||||
pub fn (config ShuffleConfigStruct) validate_for[T](a []T) ! {
|
||||
if config.start < 0 || config.start >= a.len {
|
||||
return error("argument 'config.start' must be in range [0, a.len)")
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ pub fn (mut rng PRNG) exponential(lambda f64) f64 {
|
||||
// optional and the entire array is shuffled by default. Leave the end as 0 to
|
||||
// shuffle all elements until the end.
|
||||
[direct_array_access]
|
||||
pub fn (mut rng PRNG) shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ! {
|
||||
pub fn (mut rng PRNG) shuffle[T](mut a []T, config config.ShuffleConfigStruct) ! {
|
||||
config.validate_for(a)!
|
||||
new_end := if config.end == 0 { a.len } else { config.end }
|
||||
|
||||
@ -360,23 +360,23 @@ pub fn (mut rng PRNG) shuffle<T>(mut a []T, config config.ShuffleConfigStruct) !
|
||||
|
||||
// shuffle_clone returns a random permutation of the elements in `a`.
|
||||
// The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
|
||||
pub fn (mut rng PRNG) shuffle_clone<T>(a []T, config config.ShuffleConfigStruct) ![]T {
|
||||
pub fn (mut rng PRNG) shuffle_clone[T](a []T, config config.ShuffleConfigStruct) ![]T {
|
||||
mut res := a.clone()
|
||||
rng.shuffle<T>(mut res, config)!
|
||||
rng.shuffle[T](mut res, config)!
|
||||
return res
|
||||
}
|
||||
|
||||
// choose samples k elements from the array without replacement.
|
||||
// This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array.
|
||||
// Note that if the array has repeating elements, then the sample may have repeats as well.
|
||||
pub fn (mut rng PRNG) choose<T>(array []T, k int) ![]T {
|
||||
pub fn (mut rng PRNG) choose[T](array []T, k int) ![]T {
|
||||
n := array.len
|
||||
if k > n {
|
||||
return error('Cannot choose ${k} elements without replacement from a ${n}-element array.')
|
||||
}
|
||||
mut results := []T{len: k}
|
||||
mut indices := []int{len: n, init: it}
|
||||
rng.shuffle<int>(mut indices)!
|
||||
rng.shuffle[int](mut indices)!
|
||||
for i in 0 .. k {
|
||||
results[i] = array[indices[i]]
|
||||
}
|
||||
@ -385,7 +385,7 @@ pub fn (mut rng PRNG) choose<T>(array []T, k int) ![]T {
|
||||
|
||||
// element returns a random element from the given array.
|
||||
// Note that all the positions in the array have an equal chance of being selected. This means that if the array has repeating elements, then the probability of selecting a particular element is not uniform.
|
||||
pub fn (mut rng PRNG) element<T>(array []T) !T {
|
||||
pub fn (mut rng PRNG) element[T](array []T) !T {
|
||||
if array.len == 0 {
|
||||
return error('Cannot choose an element from an empty array.')
|
||||
}
|
||||
@ -394,7 +394,7 @@ pub fn (mut rng PRNG) element<T>(array []T) !T {
|
||||
|
||||
// sample samples k elements from the array with replacement.
|
||||
// This means the elements can repeat and the size of the sample may exceed the size of the array.
|
||||
pub fn (mut rng PRNG) sample<T>(array []T, k int) []T {
|
||||
pub fn (mut rng PRNG) sample[T](array []T, k int) []T {
|
||||
mut results := []T{len: k}
|
||||
for i in 0 .. k {
|
||||
results[i] = array[rng.intn(array.len) or { 0 }]
|
||||
@ -599,33 +599,33 @@ pub fn ascii(len int) string {
|
||||
// shuffle randomly permutates the elements in `a`. The range for shuffling is
|
||||
// optional and the entire array is shuffled by default. Leave the end as 0 to
|
||||
// shuffle all elements until the end.
|
||||
pub fn shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ! {
|
||||
default_rng.shuffle<T>(mut a, config)!
|
||||
pub fn shuffle[T](mut a []T, config config.ShuffleConfigStruct) ! {
|
||||
default_rng.shuffle[T](mut a, config)!
|
||||
}
|
||||
|
||||
// shuffle_clone returns a random permutation of the elements in `a`.
|
||||
// The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
|
||||
pub fn shuffle_clone<T>(a []T, config config.ShuffleConfigStruct) ![]T {
|
||||
return default_rng.shuffle_clone<T>(a, config)
|
||||
pub fn shuffle_clone[T](a []T, config config.ShuffleConfigStruct) ![]T {
|
||||
return default_rng.shuffle_clone[T](a, config)
|
||||
}
|
||||
|
||||
// choose samples k elements from the array without replacement.
|
||||
// This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array.
|
||||
// Note that if the array has repeating elements, then the sample may have repeats as well.
|
||||
pub fn choose<T>(array []T, k int) ![]T {
|
||||
return default_rng.choose<T>(array, k)
|
||||
pub fn choose[T](array []T, k int) ![]T {
|
||||
return default_rng.choose[T](array, k)
|
||||
}
|
||||
|
||||
// element returns a random element from the given array.
|
||||
// Note that all the positions in the array have an equal chance of being selected. This means that if the array has repeating elements, then the probability of selecting a particular element is not uniform.
|
||||
pub fn element<T>(array []T) !T {
|
||||
return default_rng.element<T>(array)
|
||||
pub fn element[T](array []T) !T {
|
||||
return default_rng.element[T](array)
|
||||
}
|
||||
|
||||
// sample samples k elements from the array with replacement.
|
||||
// This means the elements can repeat and the size of the sample may exceed the size of the array.
|
||||
pub fn sample<T>(array []T, k int) []T {
|
||||
return default_rng.sample<T>(array, k)
|
||||
pub fn sample[T](array []T, k int) []T {
|
||||
return default_rng.sample[T](array, k)
|
||||
}
|
||||
|
||||
// bernoulli returns true with a probability p. Note that 0 <= p <= 1.
|
||||
|
@ -49,10 +49,10 @@ fn do_send_i64(mut ch Channel) {
|
||||
}
|
||||
|
||||
fn test_select() {
|
||||
mut chi := new_channel<int>(0)
|
||||
mut chl := new_channel<i64>(1)
|
||||
mut chb := new_channel<u8>(10)
|
||||
mut recch := new_channel<i64>(0)
|
||||
mut chi := new_channel[int](0)
|
||||
mut chl := new_channel[i64](1)
|
||||
mut chb := new_channel[u8](10)
|
||||
mut recch := new_channel[i64](0)
|
||||
spawn do_rec_i64(mut recch)
|
||||
spawn do_send_int(mut chi)
|
||||
spawn do_send_u8(mut chb)
|
||||
|
@ -58,7 +58,7 @@ pub:
|
||||
cap u32 // queue length in #objects
|
||||
}
|
||||
|
||||
pub fn new_channel<T>(n u32) &Channel {
|
||||
pub fn new_channel[T](n u32) &Channel {
|
||||
st := sizeof(T)
|
||||
if isreftype(T) {
|
||||
return new_channel_st(n, st)
|
||||
|
@ -4,7 +4,7 @@ pub struct Channel {
|
||||
arr array
|
||||
}
|
||||
|
||||
pub fn new_channel<T>(n u32) &Channel {
|
||||
pub fn new_channel[T](n u32) &Channel {
|
||||
return &Channel{arr, new_array()}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ waitgroups, mutexes etc.., you just need to supply a callback function, that
|
||||
will be called once per each item in your input array.
|
||||
|
||||
After all the work is done in parallel by the worker threads in the pool,
|
||||
pool.work_on_items will return. You can then call pool.get_results<Result>()
|
||||
pool.work_on_items will return. You can then call pool.get_results[Result]()
|
||||
to retrieve a list of all the results, that the worker callbacks returned
|
||||
for each input item. Example:
|
||||
|
||||
@ -17,7 +17,7 @@ pub struct SResult {
|
||||
}
|
||||
|
||||
fn sprocess(mut pp pool.PoolProcessor, idx int, wid int) &SResult {
|
||||
item := pp.get_item<string>(idx)
|
||||
item := pp.get_item[string](idx)
|
||||
println('idx: ${idx}, wid: ${wid}, item: ' + item)
|
||||
return &SResult{item.reverse()}
|
||||
}
|
||||
@ -26,7 +26,7 @@ fn main() {
|
||||
mut pp := pool.new_pool_processor(callback: sprocess)
|
||||
pp.work_on_items(['1abc', '2abc', '3abc', '4abc', '5abc', '6abc', '7abc'])
|
||||
// optionally, you can iterate over the results too:
|
||||
for x in pp.get_results<SResult>() {
|
||||
for x in pp.get_results[SResult]() {
|
||||
println('result: ${x.s}')
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ pub fn (mut pool PoolProcessor) set_max_jobs(njobs int) {
|
||||
// by the number of available cores on the system.
|
||||
// work_on_items returns *after* all threads finish.
|
||||
// You can optionally call get_results after that.
|
||||
pub fn (mut pool PoolProcessor) work_on_items<T>(items []T) {
|
||||
pub fn (mut pool PoolProcessor) work_on_items[T](items []T) {
|
||||
pool.work_on_pointers(unsafe { items.pointers() })
|
||||
}
|
||||
|
||||
@ -117,18 +117,18 @@ fn process_in_thread(mut pool PoolProcessor, task_id int) {
|
||||
|
||||
// get_item - called by the worker callback.
|
||||
// Retrieves a type safe instance of the currently processed item
|
||||
pub fn (pool &PoolProcessor) get_item<T>(idx int) T {
|
||||
pub fn (pool &PoolProcessor) get_item[T](idx int) T {
|
||||
return *(&T(pool.items[idx]))
|
||||
}
|
||||
|
||||
// get_result - called by the main thread to get a specific result.
|
||||
// Retrieves a type safe instance of the produced result.
|
||||
pub fn (pool &PoolProcessor) get_result<T>(idx int) T {
|
||||
pub fn (pool &PoolProcessor) get_result[T](idx int) T {
|
||||
return *(&T(pool.results[idx]))
|
||||
}
|
||||
|
||||
// get_results - get a list of type safe results in the main thread.
|
||||
pub fn (pool &PoolProcessor) get_results<T>() []T {
|
||||
pub fn (pool &PoolProcessor) get_results[T]() []T {
|
||||
mut res := []T{cap: pool.results.len}
|
||||
for i in 0 .. pool.results.len {
|
||||
res << *(&T(pool.results[i]))
|
||||
@ -137,7 +137,7 @@ pub fn (pool &PoolProcessor) get_results<T>() []T {
|
||||
}
|
||||
|
||||
// get_results_ref - get a list of type safe results in the main thread.
|
||||
pub fn (pool &PoolProcessor) get_results_ref<T>() []&T {
|
||||
pub fn (pool &PoolProcessor) get_results_ref[T]() []&T {
|
||||
mut res := []&T{cap: pool.results.len}
|
||||
for i in 0 .. pool.results.len {
|
||||
res << &T(pool.results[i])
|
||||
|
@ -10,14 +10,14 @@ pub struct IResult {
|
||||
}
|
||||
|
||||
fn worker_s(mut p pool.PoolProcessor, idx int, worker_id int) &SResult {
|
||||
item := p.get_item<string>(idx)
|
||||
item := p.get_item[string](idx)
|
||||
println('worker_s worker_id: ${worker_id} | idx: ${idx} | item: ${item}')
|
||||
time.sleep(3 * time.millisecond)
|
||||
return &SResult{'${item} ${item}'}
|
||||
}
|
||||
|
||||
fn worker_i(mut p pool.PoolProcessor, idx int, worker_id int) &IResult {
|
||||
item := p.get_item<int>(idx)
|
||||
item := p.get_item[int](idx)
|
||||
println('worker_i worker_id: ${worker_id} | idx: ${idx} | item: ${item}')
|
||||
time.sleep(5 * time.millisecond)
|
||||
return &IResult{item * 1000}
|
||||
@ -30,12 +30,12 @@ fn test_work_on_strings() {
|
||||
)
|
||||
|
||||
pool_s.work_on_items(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'])
|
||||
for x in pool_s.get_results<SResult>() {
|
||||
for x in pool_s.get_results[SResult]() {
|
||||
println(x.s)
|
||||
assert x.s.len > 1
|
||||
}
|
||||
println('---------- pool_s.get_results_ref: --------------')
|
||||
for x in pool_s.get_results_ref<SResult>() {
|
||||
for x in pool_s.get_results_ref[SResult]() {
|
||||
println(x.s)
|
||||
assert x.s.len > 1
|
||||
}
|
||||
@ -50,12 +50,12 @@ fn test_work_on_ints() {
|
||||
)
|
||||
|
||||
pool_i.work_on_items([1, 2, 3, 4, 5, 6, 7, 8])
|
||||
for x in pool_i.get_results<IResult>() {
|
||||
for x in pool_i.get_results[IResult]() {
|
||||
println(x.i)
|
||||
assert x.i > 100
|
||||
}
|
||||
println('---------- pool_i.get_results_ref: --------------')
|
||||
for x in pool_i.get_results_ref<IResult>() {
|
||||
for x in pool_i.get_results_ref[IResult]() {
|
||||
println(x.i)
|
||||
assert x.i > 100
|
||||
}
|
||||
|
@ -40,10 +40,10 @@ fn do_send_i64(mut ch Channel) {
|
||||
}
|
||||
|
||||
fn test_select() {
|
||||
mut chi := new_channel<int>(0)
|
||||
mut chl := new_channel<i64>(1)
|
||||
mut chb := new_channel<u8>(10)
|
||||
mut recch := new_channel<i64>(0)
|
||||
mut chi := new_channel[int](0)
|
||||
mut chl := new_channel[i64](1)
|
||||
mut chb := new_channel[u8](10)
|
||||
mut recch := new_channel[i64](0)
|
||||
spawn do_rec_i64(mut recch)
|
||||
spawn do_send_int(mut chi)
|
||||
spawn do_send_u8(mut chb)
|
||||
|
@ -329,7 +329,7 @@ fn (a Any) value_(value Any, key []string) Any {
|
||||
|
||||
// reflect returns `T` with `T.<field>`'s value set to the
|
||||
// value of any 1st level TOML key by the same name.
|
||||
pub fn (a Any) reflect<T>() T {
|
||||
pub fn (a Any) reflect[T]() T {
|
||||
mut reflected := T{}
|
||||
$for field in T.fields {
|
||||
mut toml_field_name := field.name
|
||||
|
@ -36,7 +36,7 @@ fn (mut e Employee) from_toml(any toml.Any) {
|
||||
|
||||
fn test_encode_and_decode() {
|
||||
x := Employee{'Peter', 28, 95000.5, true, .worker}
|
||||
s := toml.encode<Employee>(x)
|
||||
s := toml.encode[Employee](x)
|
||||
eprintln('Employee x: ${s}')
|
||||
assert s == r'name = "Peter"
|
||||
age = 28
|
||||
@ -44,7 +44,7 @@ salary = 95000.5
|
||||
is_human = true
|
||||
title = 2'
|
||||
|
||||
y := toml.decode<Employee>(s) or {
|
||||
y := toml.decode[Employee](s) or {
|
||||
println(err)
|
||||
assert false
|
||||
return
|
||||
|
@ -62,9 +62,9 @@ mut:
|
||||
fn test_reflect() {
|
||||
toml_doc := toml.parse_text(toml_text) or { panic(err) }
|
||||
|
||||
mut user := toml_doc.reflect<User>()
|
||||
user.bio = toml_doc.value('bio').reflect<Bio>()
|
||||
user.remap = toml_doc.value('field_remap').reflect<FieldRemap>()
|
||||
mut user := toml_doc.reflect[User]()
|
||||
user.bio = toml_doc.value('bio').reflect[Bio]()
|
||||
user.remap = toml_doc.value('field_remap').reflect[FieldRemap]()
|
||||
|
||||
assert user.name == 'Tom'
|
||||
assert user.age == 45
|
||||
|
@ -13,7 +13,7 @@ pub struct Null {
|
||||
}
|
||||
|
||||
// decode decodes a TOML `string` into the target type `T`.
|
||||
pub fn decode<T>(toml_txt string) !T {
|
||||
pub fn decode[T](toml_txt string) !T {
|
||||
doc := parse_text(toml_txt)!
|
||||
mut typ := T{}
|
||||
typ.from_toml(doc.to_any())
|
||||
@ -22,7 +22,7 @@ pub fn decode<T>(toml_txt string) !T {
|
||||
|
||||
// encode encodes the type `T` into a TOML string.
|
||||
// Currently encode expects the method `.to_toml()` exists on `T`.
|
||||
pub fn encode<T>(typ T) string {
|
||||
pub fn encode[T](typ T) string {
|
||||
return typ.to_toml()
|
||||
}
|
||||
|
||||
@ -194,8 +194,8 @@ pub fn (d Doc) to_any() Any {
|
||||
|
||||
// reflect returns `T` with `T.<field>`'s value set to the
|
||||
// value of any 1st level TOML key by the same name.
|
||||
pub fn (d Doc) reflect<T>() T {
|
||||
return d.to_any().reflect<T>()
|
||||
pub fn (d Doc) reflect[T]() T {
|
||||
return d.to_any().reflect[T]()
|
||||
}
|
||||
|
||||
// value queries a value from the TOML document.
|
||||
|
@ -108,7 +108,7 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo
|
||||
}
|
||||
}
|
||||
if add_para_types {
|
||||
f.write_string('<')
|
||||
f.write_string('[')
|
||||
for i, gname in node.generic_names {
|
||||
is_last := i == node.generic_names.len - 1
|
||||
f.write_string(gname)
|
||||
@ -116,7 +116,7 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo
|
||||
f.write_string(', ')
|
||||
}
|
||||
}
|
||||
f.write_string('>')
|
||||
f.write_string(']')
|
||||
}
|
||||
}
|
||||
f.write_string('(')
|
||||
|
@ -898,8 +898,8 @@ pub fn (t &Table) array_cname(elem_type Type) string {
|
||||
suffix := if elem_type.is_ptr() { '_ptr'.repeat(elem_type.nr_muls()) } else { '' }
|
||||
opt := if elem_type.has_flag(.optional) { '_option_' } else { '' }
|
||||
res := if elem_type.has_flag(.result) { '_result_' } else { '' }
|
||||
if elem_type_sym.cname.contains('<') {
|
||||
type_name := elem_type_sym.cname.replace_each(['<', '_T_', ', ', '_', '>', ''])
|
||||
if elem_type_sym.cname.contains('[') {
|
||||
type_name := elem_type_sym.cname.replace_each(['[', '_T_', ', ', '_', ']', ''])
|
||||
return 'Array_${opt}${res}${type_name}${suffix}'
|
||||
} else {
|
||||
return 'Array_${opt}${res}${elem_type_sym.cname}${suffix}'
|
||||
@ -928,8 +928,8 @@ pub fn (t &Table) array_fixed_cname(elem_type Type, size int) string {
|
||||
suffix := if elem_type.is_ptr() { '_ptr${elem_type.nr_muls()}' } else { '' }
|
||||
opt := if elem_type.has_flag(.optional) { '_option_' } else { '' }
|
||||
res := if elem_type.has_flag(.result) { '_result_' } else { '' }
|
||||
if elem_type_sym.cname.contains('<') {
|
||||
type_name := elem_type_sym.cname.replace_each(['<', '_T_', ', ', '_', '>', ''])
|
||||
if elem_type_sym.cname.contains('[') {
|
||||
type_name := elem_type_sym.cname.replace_each(['[', '_T_', ', ', '_', ']', ''])
|
||||
return 'Array_fixed_${opt}${res}${type_name}${suffix}_${size}'
|
||||
} else {
|
||||
return 'Array_fixed_${opt}${res}${elem_type_sym.cname}${suffix}_${size}'
|
||||
@ -963,11 +963,11 @@ pub fn (t &Table) chan_cname(elem_type Type, is_mut bool) string {
|
||||
[inline]
|
||||
pub fn (t &Table) promise_name(return_type Type) string {
|
||||
if return_type.idx() == void_type_idx {
|
||||
return 'Promise<JS.Any,JS.Any>'
|
||||
return 'Promise[JS.Any, JS.Any]'
|
||||
}
|
||||
|
||||
return_type_sym := t.sym(return_type)
|
||||
return 'Promise<${return_type_sym.name}, JS.Any>'
|
||||
return 'Promise[${return_type_sym.name}, JS.Any]'
|
||||
}
|
||||
|
||||
[inline]
|
||||
@ -1035,8 +1035,8 @@ pub fn (t &Table) map_cname(key_type Type, value_type Type) string {
|
||||
suffix := if value_type.is_ptr() { '_ptr'.repeat(value_type.nr_muls()) } else { '' }
|
||||
opt := if value_type.has_flag(.optional) { '_option_' } else { '' }
|
||||
res := if value_type.has_flag(.result) { '_result_' } else { '' }
|
||||
if value_type_sym.cname.contains('<') {
|
||||
type_name := value_type_sym.cname.replace_each(['<', '_T_', ', ', '_', '>', ''])
|
||||
if value_type_sym.cname.contains('[') {
|
||||
type_name := value_type_sym.cname.replace_each(['[', '_T_', ', ', '_', ']', ''])
|
||||
return 'Map_${key_type_sym.cname}_${opt}${res}${type_name}${suffix}'
|
||||
} else {
|
||||
return 'Map_${key_type_sym.cname}_${opt}${res}${value_type_sym.cname}${suffix}'
|
||||
@ -1707,7 +1707,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||
}
|
||||
Struct, Interface, SumType {
|
||||
if sym.info.is_generic {
|
||||
mut nrt := '${sym.name}<'
|
||||
mut nrt := '${sym.name}['
|
||||
for i in 0 .. sym.info.generic_types.len {
|
||||
if ct := t.resolve_generic_to_concrete(sym.info.generic_types[i],
|
||||
generic_names, concrete_types)
|
||||
@ -1719,7 +1719,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||
}
|
||||
}
|
||||
}
|
||||
nrt += '>'
|
||||
nrt += ']'
|
||||
mut idx := t.type_idxs[nrt]
|
||||
if idx == 0 {
|
||||
idx = t.add_placeholder_type(nrt, .v)
|
||||
@ -1839,7 +1839,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
|
||||
if !ts.info.is_generic {
|
||||
return typ
|
||||
}
|
||||
nrt = '${ts.name}<'
|
||||
nrt = '${ts.name}['
|
||||
c_nrt = '${ts.cname}_T_'
|
||||
for i in 0 .. ts.info.generic_types.len {
|
||||
if ct := t.resolve_generic_to_concrete(ts.info.generic_types[i], generic_names,
|
||||
@ -1854,7 +1854,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
|
||||
}
|
||||
}
|
||||
}
|
||||
nrt += '>'
|
||||
nrt += ']'
|
||||
idx := t.type_idxs[nrt]
|
||||
if idx != 0 && t.type_symbols[idx].kind != .placeholder {
|
||||
return new_type(idx).derive(typ).clear_flag(.generic)
|
||||
|
@ -1150,7 +1150,7 @@ pub fn (mytable &Table) type_to_code(t Type) string {
|
||||
// clean type name from generics form. From Type<int> -> Type
|
||||
pub fn (t &Table) clean_generics_type_str(typ Type) string {
|
||||
result := t.type_to_str(typ)
|
||||
return result.all_before('<')
|
||||
return result.all_before('[')
|
||||
}
|
||||
|
||||
// import_aliases is a map of imported symbol aliases 'module.Type' => 'Type'
|
||||
@ -1263,14 +1263,14 @@ pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]
|
||||
if typ.has_flag(.generic) {
|
||||
match sym.info {
|
||||
Struct, Interface, SumType {
|
||||
res += '<'
|
||||
res += '['
|
||||
for i, gtyp in sym.info.generic_types {
|
||||
res += t.sym(gtyp).name
|
||||
if i != sym.info.generic_types.len - 1 {
|
||||
res += ', '
|
||||
}
|
||||
}
|
||||
res += '>'
|
||||
res += ']'
|
||||
}
|
||||
else {}
|
||||
}
|
||||
@ -1284,15 +1284,15 @@ pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]
|
||||
}
|
||||
.generic_inst {
|
||||
info := sym.info as GenericInst
|
||||
res = t.shorten_user_defined_typenames(sym.name.all_before('<'), import_aliases)
|
||||
res += '<'
|
||||
res = t.shorten_user_defined_typenames(sym.name.all_before('['), import_aliases)
|
||||
res += '['
|
||||
for i, ctyp in info.concrete_types {
|
||||
res += t.type_to_str_using_aliases(ctyp, import_aliases)
|
||||
if i != info.concrete_types.len - 1 {
|
||||
res += ', '
|
||||
}
|
||||
}
|
||||
res += '>'
|
||||
res += ']'
|
||||
}
|
||||
.void {
|
||||
if typ.has_flag(.optional) {
|
||||
@ -1441,8 +1441,8 @@ pub fn (t &TypeSymbol) symbol_name_except_generic() string {
|
||||
mut embed_name := t.name
|
||||
// remove generic part from name
|
||||
// main.Abc<int> => main.Abc
|
||||
if embed_name.contains('<') {
|
||||
embed_name = embed_name.all_before('<')
|
||||
if embed_name.contains('[') {
|
||||
embed_name = embed_name.all_before('[')
|
||||
}
|
||||
return embed_name
|
||||
}
|
||||
@ -1452,8 +1452,8 @@ pub fn (t &TypeSymbol) embed_name() string {
|
||||
mut embed_name := t.name.split('.').last()
|
||||
// remove generic part from name
|
||||
// Abc<int> => Abc
|
||||
if embed_name.contains('<') {
|
||||
embed_name = embed_name.split('<')[0]
|
||||
if embed_name.contains('[') {
|
||||
embed_name = embed_name.split('[')[0]
|
||||
}
|
||||
return embed_name
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ fn parallel_cc(mut b builder.Builder, header string, res string, out_str string,
|
||||
}
|
||||
|
||||
fn build_parallel_o_cb(mut p pool.PoolProcessor, idx int, wid int) voidptr {
|
||||
postfix := p.get_item<string>(idx)
|
||||
postfix := p.get_item[string](idx)
|
||||
sw := time.new_stopwatch()
|
||||
cmd := '${os.quoted_path(cbuilder.cc_compiler)} ${cbuilder.cc_cflags} -c -w -o out_${postfix}.o out_${postfix}.c'
|
||||
res := os.execute(cmd)
|
||||
|
@ -32,7 +32,7 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||
for name in embed_generic_names {
|
||||
if name !in node_generic_names {
|
||||
struct_generic_names := node_generic_names.join(', ')
|
||||
c.error('generic type name `${name}` is not mentioned in struct `${node.name}<${struct_generic_names}>`',
|
||||
c.error('generic type name `${name}` is not mentioned in struct `${node.name}[${struct_generic_names}]`',
|
||||
embed.pos)
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,7 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||
}
|
||||
if info.generic_types.len > 0 && !field.typ.has_flag(.generic)
|
||||
&& info.concrete_types.len == 0 {
|
||||
c.error('field `${field.name}` type is generic struct, must specify the generic type names, e.g. Foo<T>, Foo<int>',
|
||||
c.error('field `${field.name}` type is generic struct, must specify the generic type names, e.g. Foo[T], Foo[int]',
|
||||
field.type_pos)
|
||||
}
|
||||
}
|
||||
@ -162,14 +162,14 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||
for name in field_generic_names {
|
||||
if name !in node_generic_names {
|
||||
struct_generic_names := node_generic_names.join(', ')
|
||||
c.error('generic type name `${name}` is not mentioned in struct `${node.name}<${struct_generic_names}>`',
|
||||
c.error('generic type name `${name}` is not mentioned in struct `${node.name}[${struct_generic_names}]`',
|
||||
field.type_pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.generic_types.len == 0 && has_generic_types {
|
||||
c.error('generic struct declaration must specify the generic type names, e.g. Foo<T>',
|
||||
c.error('generic struct declaration must specify the generic type names, e.g. Foo[T]',
|
||||
node.pos)
|
||||
}
|
||||
}
|
||||
@ -264,10 +264,10 @@ fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
||||
}
|
||||
} else {
|
||||
if c.table.cur_concrete_types.len == 0 {
|
||||
c.error('generic struct init must specify type parameter, e.g. Foo<int>',
|
||||
c.error('generic struct init must specify type parameter, e.g. Foo[int]',
|
||||
node.pos)
|
||||
} else if node.generic_types.len == 0 {
|
||||
c.error('generic struct init must specify type parameter, e.g. Foo<T>',
|
||||
c.error('generic struct init must specify type parameter, e.g. Foo[T]',
|
||||
node.pos)
|
||||
} else if node.generic_types.len > 0
|
||||
&& node.generic_types.len != struct_sym.info.generic_types.len {
|
||||
|
@ -1,6 +1,6 @@
|
||||
vlib/v/checker/tests/check_err_msg_with_generics.vv:15:10: error: cannot cast struct `BSTree<Result<[]Token, Err<string>>>` to `int`
|
||||
vlib/v/checker/tests/check_err_msg_with_generics.vv:15:10: error: cannot cast struct `BSTree[Result[[]Token, Err[string]]]` to `int`
|
||||
13 | fn test_err_msg() {
|
||||
14 | typ := datatypes.BSTree<Result<[]Token, Err<string>>>{}
|
||||
14 | typ := datatypes.BSTree[Result[[]Token, Err[string]]]{}
|
||||
15 | println(int(typ))
|
||||
| ~~~~~~~~
|
||||
16 | }
|
||||
@ -24,4 +24,4 @@ vlib/datatypes/bstree.v:232:17: error: cannot append `T` to `[]T`
|
||||
232 | result << node.value
|
||||
| ~~~~~
|
||||
233 | bst.pre_order_traversal_helper(node.left, mut result)
|
||||
234 | bst.pre_order_traversal_helper(node.right, mut result)
|
||||
234 | bst.pre_order_traversal_helper(node.right, mut result)
|
||||
|
@ -1,16 +1,16 @@
|
||||
import datatypes
|
||||
|
||||
type Result<T, U> = Err<U> | Ok<T>
|
||||
type Result[T, U] = Err[U] | Ok[T]
|
||||
|
||||
struct Ok<T> {
|
||||
struct Ok[T] {
|
||||
value T
|
||||
}
|
||||
|
||||
struct Err<U> {
|
||||
struct Err[U] {
|
||||
value U
|
||||
}
|
||||
|
||||
fn test_err_msg() {
|
||||
typ := datatypes.BSTree<Result<[]Token, Err<string>>>{}
|
||||
typ := datatypes.BSTree[Result[[]Token, Err[string]]]{}
|
||||
println(int(typ))
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
vlib/v/checker/tests/generic_interface_err.vv:10:1: warning: unused variable: `i`
|
||||
8 |
|
||||
8 |
|
||||
9 | s := Struct{7}
|
||||
10 | i := Interface(s)
|
||||
| ^
|
||||
vlib/v/checker/tests/generic_interface_err.vv:9:6: error: generic struct init must specify type parameter, e.g. Foo<int>
|
||||
vlib/v/checker/tests/generic_interface_err.vv:9:6: error: generic struct init must specify type parameter, e.g. Foo[int]
|
||||
7 | }
|
||||
8 |
|
||||
8 |
|
||||
9 | s := Struct{7}
|
||||
| ~~~~~~~~~
|
||||
10 | i := Interface(s)
|
||||
vlib/v/checker/tests/generic_interface_err.vv:10:6: error: can not find method `method` on `Struct`, needed for interface: `Interface`
|
||||
8 |
|
||||
8 |
|
||||
9 | s := Struct{7}
|
||||
10 | i := Interface(s)
|
||||
| ~~~~~~~~~~~~
|
||||
|
@ -1,11 +1,11 @@
|
||||
vlib/v/checker/tests/generic_sumtype_invalid_variant.vv:5:10: error: `MultiGeneric<bool, int, string>` has no variant `u64`
|
||||
vlib/v/checker/tests/generic_sumtype_invalid_variant.vv:5:10: error: `MultiGeneric[bool, int, string]` has no variant `u64`
|
||||
3 | fn main() {
|
||||
4 | mut m := MultiGeneric<bool, int, string>(true)
|
||||
4 | mut m := MultiGeneric[bool, int, string](true)
|
||||
5 | if m is u64 {
|
||||
| ~~~
|
||||
6 | println('hi')
|
||||
7 | }
|
||||
vlib/v/checker/tests/generic_sumtype_invalid_variant.vv:8:10: error: `MultiGeneric<bool, int, string>` has no variant `X`
|
||||
vlib/v/checker/tests/generic_sumtype_invalid_variant.vv:8:10: error: `MultiGeneric[bool, int, string]` has no variant `X`
|
||||
6 | println('hi')
|
||||
7 | }
|
||||
8 | if m is X {
|
||||
|
@ -1,7 +1,7 @@
|
||||
type MultiGeneric<X, Y, Z> = X | Y | Z
|
||||
type MultiGeneric[X, Y, Z] = X | Y | Z
|
||||
|
||||
fn main() {
|
||||
mut m := MultiGeneric<bool, int, string>(true)
|
||||
mut m := MultiGeneric[bool, int, string](true)
|
||||
if m is u64 {
|
||||
println('hi')
|
||||
}
|
||||
|
@ -4,10 +4,10 @@ vlib/v/checker/tests/generics_fn_called_multi_args_mismatch.vv:3:13: error: cann
|
||||
3 | foo_str(1, x)
|
||||
| ^
|
||||
4 |
|
||||
5 | foo := Foo<int>{}
|
||||
vlib/v/checker/tests/generics_fn_called_multi_args_mismatch.vv:6:11: error: cannot use `[]rune` as `string` in argument 1 to `Foo<int>.info`
|
||||
5 | foo := Foo[int]{}
|
||||
vlib/v/checker/tests/generics_fn_called_multi_args_mismatch.vv:6:11: error: cannot use `[]rune` as `string` in argument 1 to `Foo[int].info`
|
||||
4 |
|
||||
5 | foo := Foo<int>{}
|
||||
5 | foo := Foo[int]{}
|
||||
6 | foo.info(x)
|
||||
| ^
|
||||
7 | }
|
||||
|
@ -2,16 +2,16 @@ fn main() {
|
||||
x := 'ab'.runes()[..1]
|
||||
foo_str(1, x)
|
||||
|
||||
foo := Foo<int>{}
|
||||
foo := Foo[int]{}
|
||||
foo.info(x)
|
||||
}
|
||||
|
||||
fn foo_str<T>(b T, a string) {
|
||||
fn foo_str[T](b T, a string) {
|
||||
}
|
||||
|
||||
struct Foo<T> {
|
||||
struct Foo[T] {
|
||||
t T
|
||||
}
|
||||
|
||||
fn (f Foo<T>) info(a string) {
|
||||
fn (f Foo[T]) info(a string) {
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:13:32: error: return generic struct in fn declaration must specify the generic type names, e.g. Foo<T>
|
||||
11 | }
|
||||
12 |
|
||||
13 | pub fn new_channel_struct<T>() GenericChannelStruct {
|
||||
13 | pub fn new_channel_struct[T]() GenericChannelStruct {
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
14 | d := GenericChannelStruct{
|
||||
15 | ch: chan T{}
|
||||
vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:14:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||
vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:14:7: error: generic struct init must specify type parameter, e.g. Foo[T]
|
||||
12 |
|
||||
13 | pub fn new_channel_struct<T>() GenericChannelStruct {
|
||||
13 | pub fn new_channel_struct[T]() GenericChannelStruct {
|
||||
14 | d := GenericChannelStruct{
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
15 | ch: chan T{}
|
||||
|
@ -1,4 +1,4 @@
|
||||
struct GenericChannelStruct<T> {
|
||||
struct GenericChannelStruct[T] {
|
||||
ch chan T
|
||||
}
|
||||
|
||||
@ -7,10 +7,10 @@ struct Simple {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
new_channel_struct<Simple>()
|
||||
new_channel_struct[Simple]()
|
||||
}
|
||||
|
||||
pub fn new_channel_struct<T>() GenericChannelStruct {
|
||||
pub fn new_channel_struct[T]() GenericChannelStruct {
|
||||
d := GenericChannelStruct{
|
||||
ch: chan T{}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/generics_method_sumtype_arg_mismatch.vv:56:13: error: cannot use `Maybe<string>` as `Maybe<int>` in argument 1 to `Maybe<int>.or`
|
||||
vlib/v/checker/tests/generics_method_sumtype_arg_mismatch.vv:56:13: error: cannot use `Maybe[string]` as `Maybe[int]` in argument 1 to `Maybe[int].or`
|
||||
54 | b := some('abc')
|
||||
55 |
|
||||
56 | c := a.@or(b)
|
||||
|
@ -1,12 +1,12 @@
|
||||
vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv:4:2: error: generic type name `T` is not mentioned in struct `Foo<U>`
|
||||
vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv:4:2: error: generic type name `T` is not mentioned in struct `Foo[U]`
|
||||
2 |
|
||||
3 | struct Foo<U> {
|
||||
4 | Bar<T>
|
||||
3 | struct Foo[U] {
|
||||
4 | Bar[T]
|
||||
| ~~~~~~
|
||||
5 | foo U
|
||||
6 | bar P
|
||||
vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv:6:6: error: generic type name `P` is not mentioned in struct `Foo<U>`
|
||||
4 | Bar<T>
|
||||
vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv:6:6: error: generic type name `P` is not mentioned in struct `Foo[U]`
|
||||
4 | Bar[T]
|
||||
5 | foo U
|
||||
6 | bar P
|
||||
| ^
|
||||
|
@ -1,10 +1,10 @@
|
||||
fn main() {}
|
||||
|
||||
struct Foo<U> {
|
||||
Bar<T>
|
||||
struct Foo[U] {
|
||||
Bar[T]
|
||||
foo U
|
||||
bar P
|
||||
}
|
||||
|
||||
struct Bar<T> {
|
||||
struct Bar[T] {
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
vlib/v/checker/tests/generics_struct_declaration_err.vv:5:1: error: generic struct declaration must specify the generic type names, e.g. Foo<T>
|
||||
vlib/v/checker/tests/generics_struct_declaration_err.vv:5:1: error: generic struct declaration must specify the generic type names, e.g. Foo[T]
|
||||
3 | }
|
||||
4 |
|
||||
5 | struct MyGenericChannelStruct {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
6 | GenericChannelStruct<T>
|
||||
6 | GenericChannelStruct[T]
|
||||
7 | msg string
|
||||
|
@ -1,9 +1,9 @@
|
||||
struct GenericChannelStruct<T> {
|
||||
struct GenericChannelStruct[T] {
|
||||
ch chan T
|
||||
}
|
||||
|
||||
struct MyGenericChannelStruct {
|
||||
GenericChannelStruct<T>
|
||||
GenericChannelStruct[T]
|
||||
msg string
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ struct Simple {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
new_channel_struct<Simple>()
|
||||
new_channel_struct[Simple]()
|
||||
}
|
||||
|
||||
pub fn new_channel_struct<T>() GenericChannelStruct<T> {
|
||||
d := GenericChannelStruct<T>{
|
||||
pub fn new_channel_struct[T]() GenericChannelStruct[T] {
|
||||
d := GenericChannelStruct[T]{
|
||||
ch: chan T{}
|
||||
}
|
||||
|
||||
|
@ -26,21 +26,21 @@ vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:30:24: error: expected
|
||||
| ~~
|
||||
31 |
|
||||
32 | println(fun1.call(true))
|
||||
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:32:20: error: cannot use `bool` as `int` in argument 1 to `Fun<fn (int) int>.call`
|
||||
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:32:20: error: cannot use `bool` as `int` in argument 1 to `Fun[fn (int) int].call`
|
||||
30 | println(fun1.call(42, 43))
|
||||
31 |
|
||||
32 | println(fun1.call(true))
|
||||
| ~~~~
|
||||
33 | println(fun1.call('text'))
|
||||
34 | println(fun1.call(22.2))
|
||||
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:33:20: error: cannot use `string` as `int` in argument 1 to `Fun<fn (int) int>.call`
|
||||
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:33:20: error: cannot use `string` as `int` in argument 1 to `Fun[fn (int) int].call`
|
||||
31 |
|
||||
32 | println(fun1.call(true))
|
||||
33 | println(fun1.call('text'))
|
||||
| ~~~~~~
|
||||
34 | println(fun1.call(22.2))
|
||||
35 | }
|
||||
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:34:20: error: cannot use `float literal` as `int` in argument 1 to `Fun<fn (int) int>.call`
|
||||
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:34:20: error: cannot use `float literal` as `int` in argument 1 to `Fun[fn (int) int].call`
|
||||
32 | println(fun1.call(true))
|
||||
33 | println(fun1.call('text'))
|
||||
34 | println(fun1.call(22.2))
|
||||
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/generics_struct_field_type_err.vv:4:9: error: field `next` type is generic struct, must specify the generic type names, e.g. Foo<T>, Foo<int>
|
||||
vlib/v/checker/tests/generics_struct_field_type_err.vv:4:9: error: field `next` type is generic struct, must specify the generic type names, e.g. Foo[T], Foo[int]
|
||||
2 | mut:
|
||||
3 | value T
|
||||
4 | next &LL = unsafe { 0 }
|
||||
|
@ -1,55 +1,55 @@
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:58:8: error: generic struct init must specify type parameter, e.g. Foo<int>
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:58:8: error: generic struct init must specify type parameter, e.g. Foo[int]
|
||||
56 | ret = holder_call_12(neg, 3)
|
||||
57 | assert ret == -3
|
||||
58 | ret = FnHolder1{neg}.call(4)
|
||||
| ~~~~~~~~~~~~~~
|
||||
59 | assert ret == -4
|
||||
60 |
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:67:8: error: generic struct init must specify type parameter, e.g. Foo<int>
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:67:8: error: generic struct init must specify type parameter, e.g. Foo[int]
|
||||
65 | ret = holder_call_22(neg, 5)
|
||||
66 | assert ret == -5
|
||||
67 | ret = FnHolder2{neg}.call(6)
|
||||
| ~~~~~~~~~~~~~~
|
||||
68 | assert ret == -6
|
||||
69 | }
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:22:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:22:7: error: generic struct init must specify type parameter, e.g. Foo[T]
|
||||
20 |
|
||||
21 | fn holder_call_1<T>(func T, a int) int {
|
||||
21 | fn holder_call_1[T](func T, a int) int {
|
||||
22 | h := FnHolder1{func}
|
||||
| ~~~~~~~~~~~~~~~
|
||||
23 | return h.call(a)
|
||||
24 | }
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:27:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:27:7: error: generic struct init must specify type parameter, e.g. Foo[T]
|
||||
25 |
|
||||
26 | fn holder_call_2<T>(func T, a int) int {
|
||||
26 | fn holder_call_2[T](func T, a int) int {
|
||||
27 | h := FnHolder2{func}
|
||||
| ~~~~~~~~~~~~~~~
|
||||
28 | return h.call(a)
|
||||
29 | }
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:33:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||
31 | fn holder_call_11<T>(func T, a int) int {
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:33:7: error: generic struct init must specify type parameter, e.g. Foo[T]
|
||||
31 | fn holder_call_11[T](func T, a int) int {
|
||||
32 | f := func
|
||||
33 | h := FnHolder1{f}
|
||||
| ~~~~~~~~~~~~
|
||||
34 | return h.call(a)
|
||||
35 | }
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:39:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||
37 | fn holder_call_21<T>(func T, a int) int {
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:39:7: error: generic struct init must specify type parameter, e.g. Foo[T]
|
||||
37 | fn holder_call_21[T](func T, a int) int {
|
||||
38 | f := func
|
||||
39 | h := FnHolder2{f}
|
||||
| ~~~~~~~~~~~~
|
||||
40 | return h.call(a)
|
||||
41 | }
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:44:9: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:44:9: error: generic struct init must specify type parameter, e.g. Foo[T]
|
||||
42 |
|
||||
43 | fn holder_call_12<T>(func T, a int) int {
|
||||
43 | fn holder_call_12[T](func T, a int) int {
|
||||
44 | return FnHolder1{func}.call(a)
|
||||
| ~~~~~~~~~~~~~~~
|
||||
45 | }
|
||||
46 |
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:48:9: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:48:9: error: generic struct init must specify type parameter, e.g. Foo[T]
|
||||
46 |
|
||||
47 | fn holder_call_22<T>(func T, a int) int {
|
||||
47 | fn holder_call_22[T](func T, a int) int {
|
||||
48 | return FnHolder2{func}.call(a)
|
||||
| ~~~~~~~~~~~~~~~
|
||||
49 | }
|
||||
|
@ -2,49 +2,49 @@ fn neg(a int) int {
|
||||
return -a
|
||||
}
|
||||
|
||||
struct FnHolder1<T> {
|
||||
struct FnHolder1[T] {
|
||||
func T
|
||||
}
|
||||
|
||||
fn (self FnHolder1<T>) call(a int) int {
|
||||
fn (self FnHolder1[T]) call(a int) int {
|
||||
return self.func(a)
|
||||
}
|
||||
|
||||
struct FnHolder2<T> {
|
||||
struct FnHolder2[T] {
|
||||
func fn (int) int
|
||||
}
|
||||
|
||||
fn (self FnHolder2<T>) call(a int) int {
|
||||
fn (self FnHolder2[T]) call(a int) int {
|
||||
return self.func(a)
|
||||
}
|
||||
|
||||
fn holder_call_1<T>(func T, a int) int {
|
||||
fn holder_call_1[T](func T, a int) int {
|
||||
h := FnHolder1{func}
|
||||
return h.call(a)
|
||||
}
|
||||
|
||||
fn holder_call_2<T>(func T, a int) int {
|
||||
fn holder_call_2[T](func T, a int) int {
|
||||
h := FnHolder2{func}
|
||||
return h.call(a)
|
||||
}
|
||||
|
||||
fn holder_call_11<T>(func T, a int) int {
|
||||
fn holder_call_11[T](func T, a int) int {
|
||||
f := func
|
||||
h := FnHolder1{f}
|
||||
return h.call(a)
|
||||
}
|
||||
|
||||
fn holder_call_21<T>(func T, a int) int {
|
||||
fn holder_call_21[T](func T, a int) int {
|
||||
f := func
|
||||
h := FnHolder2{f}
|
||||
return h.call(a)
|
||||
}
|
||||
|
||||
fn holder_call_12<T>(func T, a int) int {
|
||||
fn holder_call_12[T](func T, a int) int {
|
||||
return FnHolder1{func}.call(a)
|
||||
}
|
||||
|
||||
fn holder_call_22<T>(func T, a int) int {
|
||||
fn holder_call_22[T](func T, a int) int {
|
||||
return FnHolder2{func}.call(a)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
vlib/v/checker/tests/generics_undefined_operation.vv:12:5: error: undefined operation `V2d<int>` * `V2d<int>`
|
||||
10 | v3 := V2d<int>{4, 6}
|
||||
vlib/v/checker/tests/generics_undefined_operation.vv:12:5: error: undefined operation `V2d[int]` * `V2d[int]`
|
||||
10 | v3 := V2d[int]{4, 6}
|
||||
11 |
|
||||
12 | if v1 * v2 == v3 {
|
||||
| ~~~~~~~
|
||||
|
@ -1,13 +1,13 @@
|
||||
struct V2d<T> {
|
||||
struct V2d[T] {
|
||||
mut:
|
||||
x T
|
||||
y T
|
||||
}
|
||||
|
||||
fn main() {
|
||||
v1 := V2d<int>{2, 2}
|
||||
v2 := V2d<int>{2, 3}
|
||||
v3 := V2d<int>{4, 6}
|
||||
v1 := V2d[int]{2, 2}
|
||||
v2 := V2d[int]{2, 3}
|
||||
v3 := V2d[int]{4, 6}
|
||||
|
||||
if v1 * v2 == v3 {
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ vlib/v/checker/tests/interface_generic_err.vv:8:1: warning: unused variable: `wh
|
||||
7 | what := What{}
|
||||
8 | why := Why(what)
|
||||
| ~~~
|
||||
vlib/v/checker/tests/interface_generic_err.vv:7:9: error: generic struct init must specify type parameter, e.g. Foo<int>
|
||||
5 |
|
||||
vlib/v/checker/tests/interface_generic_err.vv:7:9: error: generic struct init must specify type parameter, e.g. Foo[int]
|
||||
5 |
|
||||
6 | // no segfault without generic
|
||||
7 | what := What{}
|
||||
| ~~~~~~
|
||||
|
@ -1,7 +1,7 @@
|
||||
struct What<T> {}
|
||||
struct What[T] {}
|
||||
|
||||
// with or without generic
|
||||
interface Why<T> {}
|
||||
interface Why[T] {}
|
||||
|
||||
// no segfault without generic
|
||||
what := What{}
|
||||
|
@ -1,12 +1,12 @@
|
||||
vlib/v/checker/tests/struct_cast_to_struct_generic_err.vv:11:7: warning: casting to struct is deprecated, use e.g. `Struct{...expr}` instead
|
||||
9 | fn main() {
|
||||
10 | abc := Abc<int>{}
|
||||
10 | abc := Abc[int]{}
|
||||
11 | _ := Xyz(abc)
|
||||
| ~~~~~~~~
|
||||
12 | }
|
||||
vlib/v/checker/tests/struct_cast_to_struct_generic_err.vv:11:7: error: cannot convert struct `Abc<int>` to struct `Xyz`
|
||||
vlib/v/checker/tests/struct_cast_to_struct_generic_err.vv:11:7: error: cannot convert struct `Abc[int]` to struct `Xyz`
|
||||
9 | fn main() {
|
||||
10 | abc := Abc<int>{}
|
||||
10 | abc := Abc[int]{}
|
||||
11 | _ := Xyz(abc)
|
||||
| ~~~~~~~~
|
||||
12 | }
|
||||
|
@ -1,4 +1,4 @@
|
||||
struct Abc<T> {
|
||||
struct Abc[T] {
|
||||
name T
|
||||
}
|
||||
|
||||
@ -7,6 +7,6 @@ struct Xyz {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
abc := Abc<int>{}
|
||||
abc := Abc[int]{}
|
||||
_ := Xyz(abc)
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
vlib/v/checker/tests/undefined_type_on_sumtype.vv:30:4: warning: unused variable: `rx`
|
||||
28 | match r {
|
||||
29 | Some<ParseRes> {
|
||||
29 | Some[ParseRes] {
|
||||
30 | rx := r.value
|
||||
| ~~
|
||||
31 | }
|
||||
32 | None<ParseRes> {}
|
||||
32 | None[ParseRes] {}
|
||||
vlib/v/checker/tests/undefined_type_on_sumtype.vv:1:17: error: unknown type `Token`.
|
||||
Did you mean `Ok<[]Token>`?
|
||||
1 | type ParseRes = Result<[]Token, ParseErr>
|
||||
Did you mean `Ok[[]Token]`?
|
||||
1 | type ParseRes = Result[[]Token, ParseErr]
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
2 |
|
||||
2 |
|
||||
3 | // Token type is unknown
|
||||
|
@ -1,34 +1,34 @@
|
||||
type ParseRes = Result<[]Token, ParseErr>
|
||||
type ParseRes = Result[[]Token, ParseErr]
|
||||
|
||||
// Token type is unknown
|
||||
//struct Token {}
|
||||
// struct Token {}
|
||||
|
||||
struct ParseErr {}
|
||||
|
||||
type Opt<T> = None<T> | Some<T>
|
||||
type Opt[T] = None[T] | Some[T]
|
||||
|
||||
struct None<T> {}
|
||||
struct None[T] {}
|
||||
|
||||
struct Some<T> {
|
||||
struct Some[T] {
|
||||
value T
|
||||
}
|
||||
|
||||
type Result<T, U> = Err<U> | Ok<T>
|
||||
type Result[T, U] = Err[U] | Ok[T]
|
||||
|
||||
struct Ok<T> {
|
||||
struct Ok[T] {
|
||||
value T
|
||||
}
|
||||
|
||||
struct Err<U> {
|
||||
struct Err[U] {
|
||||
value U
|
||||
}
|
||||
|
||||
fn test_report() {
|
||||
r := Opt<ParseRes>(None<ParseRes>{})
|
||||
r := Opt[ParseRes](None[ParseRes]{})
|
||||
match r {
|
||||
Some<ParseRes> {
|
||||
Some[ParseRes] {
|
||||
rx := r.value
|
||||
}
|
||||
None<ParseRes> {}
|
||||
None[ParseRes] {}
|
||||
}
|
||||
}
|
||||
|
@ -201,10 +201,10 @@ fn (mut f Fmt) write_language_prefix(lang ast.Language) {
|
||||
|
||||
fn (mut f Fmt) write_generic_types(gtypes []ast.Type) {
|
||||
if gtypes.len > 0 {
|
||||
f.write('<')
|
||||
f.write('[')
|
||||
gtypes_string := gtypes.map(f.table.type_to_str(it)).join(', ')
|
||||
f.write(gtypes_string)
|
||||
f.write('>')
|
||||
f.write(']')
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,14 +248,14 @@ pub fn (mut f Fmt) short_module(name string) string {
|
||||
if name in f.mod2syms {
|
||||
return f.mod2syms[name]
|
||||
}
|
||||
if name.ends_with('>') {
|
||||
generic_levels := name.trim_string_right('>').split('<')
|
||||
if name.ends_with(']') {
|
||||
generic_levels := name.trim_string_right(']').split('[')
|
||||
mut res := '${f.short_module(generic_levels[0])}'
|
||||
for i in 1 .. generic_levels.len {
|
||||
genshorts := generic_levels[i].split(', ').map(f.short_module(it)).join(', ')
|
||||
res += '<${genshorts}'
|
||||
res += '[${genshorts}'
|
||||
}
|
||||
res += '>'
|
||||
res += ']'
|
||||
return res
|
||||
}
|
||||
vals := name.split('.')
|
||||
@ -295,7 +295,7 @@ pub fn (mut f Fmt) mark_types_import_as_used(typ ast.Type) {
|
||||
f.mark_types_import_as_used(concrete_typ)
|
||||
}
|
||||
}
|
||||
name := sym.name.split('<')[0] // take `Type` from `Type<T>`
|
||||
name := sym.name.split('[')[0] // take `Type` from `Type[T]`
|
||||
f.mark_import_as_used(name)
|
||||
}
|
||||
|
||||
@ -1777,7 +1777,7 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
||||
|
||||
fn (mut f Fmt) write_generic_call_if_require(node ast.CallExpr) {
|
||||
if node.concrete_types.len > 0 {
|
||||
f.write('<')
|
||||
f.write('[')
|
||||
for i, concrete_type in node.concrete_types {
|
||||
mut name := f.table.type_to_str_using_aliases(concrete_type, f.mod2alias)
|
||||
tsym := f.table.sym(concrete_type)
|
||||
@ -1792,7 +1792,7 @@ fn (mut f Fmt) write_generic_call_if_require(node ast.CallExpr) {
|
||||
f.write(', ')
|
||||
}
|
||||
}
|
||||
f.write('>')
|
||||
f.write(']')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ fn (f Foo) print() {
|
||||
println('test')
|
||||
}
|
||||
|
||||
fn test<T>() {
|
||||
fn test[T]() {
|
||||
mut t := T{}
|
||||
t.name = '2'
|
||||
$for f in T.fields {
|
||||
@ -19,5 +19,5 @@ fn test<T>() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test<Foo>()
|
||||
test[Foo]()
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user