Skip to content

Instantly share code, notes, and snippets.

@lazalong
Created December 2, 2022 08:07
Show Gist options
  • Save lazalong/6720f9a31c4e1023e1adf37356db9994 to your computer and use it in GitHub Desktop.
Save lazalong/6720f9a31c4e1023e1adf37356db9994 to your computer and use it in GitHub Desktop.
Example of generics in V. Implements the V documentation skeleton about Generics
// Example of generics in V.
// Its taken from the quasi-complete code in the documentation
// https://github.com/vlang/v/blob/master/doc/docs.md#generics
// credit: lazalong@gmail.com
module main
interface IData {}
struct User {
id int
name string
}
struct Post {
id int
user_id int
title string
}
[heap]
struct DB {
pub mut:
data map[string]map[int]IData // nested maps
}
pub fn new_db() DB {
mut db := DB{}
db.data = map[string]map[int]IData{}
return db
}
pub fn (mut db DB[T]) query_one<T>(t string, id int) T {
// if id in db.data[T.name] {
if x := db.data[T.name][id] {
if x is T {
return *x
}
}
// }
return T{}
}
/* alternative but then the none must be handled
pub fn (mut db DB[T]) query_one<T>(t string, id int) ?T {
if x := db.data[T.name][id] {
if x is T {
println('found ${id} | x: $x')
return *x
}
}
return none
}
*/
pub fn (mut db DB) add<T>(data T) {
db.data[T.name][data.id] = IData(data)
}
struct Repo<T> {
mut:
db &DB
}
fn new_repo<T>(db &DB) Repo<T> {
return Repo<T>{db: db}
}
// This is a generic function. V will generate it for every type it's used with.
fn (mut r Repo<T>) find_by_id(id int) ?T {
table_name := T.name // in this example getting the name of the type gives us the table name
return r.db.query_one<T>('select * from ${table_name} where id = ?', id)
}
pub fn (mut r Repo<T>) add<T>(data T) {
r.db.add(data)
}
fn main() {
db := new_db()
mut users_repo := new_repo<User>(&db) // returns Repo<User>
mut posts_repo := new_repo<Post>(&db) // returns Repo<Post>
users_repo.add(User{1, 'test'})
users_repo.add(User{2, 'test2'})
posts_repo.add(Post{3, 4, 'bob' })
users_repo.add(User{4, 'test3'})
user := users_repo.find_by_id(1)? // find_by_id<User>
post := posts_repo.find_by_id(6)? // find_by_id<Post>
println ('user 1: ${user}')
println ('post 3: ${post}')
println('User all values ${db.data['User']}')
println('Post all values ${db.data['Post']}')
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment