1
0
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:
yuyi 2022-11-27 00:23:26 +08:00 committed by GitHub
parent b19b97e7b1
commit ef5be22f81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
297 changed files with 1959 additions and 1943 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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})')
}

View File

@ -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}

View File

@ -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

View File

@ -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)

View File

@ -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())

View File

@ -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

View File

@ -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)

View File

@ -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) {

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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

View File

@ -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
}

View File

@ -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)
```

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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()
}

View File

@ -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]

View File

@ -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

View File

@ -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) }

View File

@ -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

View File

@ -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)
}

View File

@ -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
}

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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'

View File

@ -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
}

View File

@ -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 {

View File

@ -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

View File

@ -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 }
}

View File

@ -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 }
}

View File

@ -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)
}

View File

@ -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

View File

@ -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()
}

View File

@ -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()

View File

@ -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

View File

@ -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'))

View File

@ -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)")
}

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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()}
}

View File

@ -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}')
}
}

View File

@ -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])

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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('(')

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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 {

View File

@ -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 | }

View File

@ -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))
}

View File

@ -3,7 +3,7 @@ vlib/v/checker/tests/generic_interface_err.vv:10:1: warning: unused variable: `i
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 |
9 | s := Struct{7}

View File

@ -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 {

View File

@ -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')
}

View File

@ -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 | }

View File

@ -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) {
}

View File

@ -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{}

View File

@ -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{}
}

View File

@ -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)

View File

@ -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
| ^

View File

@ -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] {
}

View File

@ -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

View File

@ -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{}
}

View File

@ -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))

View File

@ -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 }

View File

@ -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 | }

View File

@ -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)
}

View File

@ -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 {
| ~~~~~~~

View File

@ -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 {
}

View File

@ -3,7 +3,7 @@ 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>
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{}

View File

@ -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{}

View File

@ -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 | }

View File

@ -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)
}

View File

@ -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 |
3 | // Token type is unknown

View File

@ -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] {}
}
}

View File

@ -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(']')
}
}

View File

@ -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