Generics

1. struct Repo<T> {
2. db DB
3. }

5. fn new_repo<T>(db DB) Repo<T> {
6. return Repo<T>{db: db}
7. }

9. // This is a generic function. V will generate it for every type it's used with.
10. fn (r Repo<T>) find_by_id(id int) ?T {
11. table_name := T.name // in this example getting the name of the type gives us the table name
12. return r.db.query_one<T>('select * from $table_name where id = ?', id)
13. }

15. db := new_db()
16. users_repo := new_repo<User>(db) // returns Repo<User>
17. posts_repo := new_repo<Post>(db) // returns Repo<Post>
18. user := users_repo.find_by_id(1)? // find_by_id<User>
19. post := posts_repo.find_by_id(1)? // find_by_id<Post>

At the moment only one type parameter named T is supported.

Currently generic function definitions must declare their type parameters, but in future V will infer generic type parameters from single-letter type names in runtime parameter types. This is why find_by_id can omit <T>, because the receiver argument r uses a generic type T.

Another example:

1. fn compare<T>(a T, b T) int {
2. if a < b {
3. return -1
4. }
5. if a > b {
6. return 1
7. }
8. return 0
9. }

11. // compare<int>
12. println(compare(1, 0)) // Outputs: 1
13. println(compare(1, 1)) //          0
14. println(compare(1, 2)) //         -1

16. // compare<string>
17. println(compare('1', '0')) // Outputs: 1
18. println(compare('1', '1')) //          0
19. println(compare('1', '2')) //         -1

21. // compare<f64>
22. println(compare(1.1, 1.0)) // Outputs: 1
23. println(compare(1.1, 1.1)) //          0
24. println(compare(1.1, 1.2)) //         -1