I am quite new to the v language and i discovered this feature, however it seems like i am doing something wrong.
I have a struct that gathers information in case an error is found somewhere and i'd like to create a function in the same structure to return a string containing all the values so that i can call it and store it in a variable the proper way: error_msg := error.to_string()
I am using v version 0.3.3
Having the Error struct:
pub struct Error {
pub:
text string
row int
col int
complementary string
}
I have tried:
fn to_string(e Error) string {
return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}
fn (e Error) to_string() string {
return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}
I would like the second option to work but it is outputing the following error while compiling it:
structs/error.v:11:7: error: cannot define new methods on non-local type Error
9 | }
10 |
11 | fn (e Error) to_string() string {
| ~~~~~
12 | return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
13 | }
The function and the struct are in the same module as expected and even in the same file Full code
module structs
pub struct Error {
pub:
text string
row int
col int
complementary string
}
fn (e Error) to_string() string {
return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}
That being said, it is going to be called in another file and module:
pub fn read(file_name string) (int, string) {
data := read_file(file_name) or {
error_str := Error{text: 'File "$file_name" does not exist', row: 2, col: 0}
return 1, error_str.to_string()
}
return 0, data
}
The error cannot define new methods on non-local type Error
occurs because Error
is a V builtin, thus already defined (non-locally), and you cannot add a new method to that here.
Also, you're getting this error on the method definition because it presumably precedes the struct's definition in your source code. If you flipped their order of definition (struct first, then the method), the issue wouldn't change but the error message would have been more to the point, reading: cannot register struct `Error`, another type with this name exists
.
Give your struct
a new name:
struct MyError {
text string
row int
col int
complementary string
}
fn (e MyError) to_string() string {
return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}
error_str := MyError{text: 'File does not exist', row: 2, col: 0}
println(error_str.to_string())
File does not exist
in row 2 at col 0
Define proper custom error types which you can then use as actual errors: Either manually implement the IError
interface (requiring the two methods msg() string
and code() int
), or just embed the interface's default implementation Error
(yes, the one you have accidentally been trying to shadow) which provides empty copies of both methods, so you only have to add what's needed. For instance:
struct MyError {
Error
text string
row int
col int
complementary string
}
fn (e MyError) msg() string {
return '${e.text}\n in row ${e.row} at col ${e.col}\n${e.complementary}'
}
fn read(file_name string) !string {
failed := true
if failed {
return MyError{text: 'File "${file_name}" does not exist', row: 2, col: 0}
}
return "data"
}
data := read("xy") or { panic(err) }
println(data)
V panic: MyError: File "xy" does not exist
in row 2 at col 0
v hash: 046dd54
/tmp/v_1000/main.13380111000873620315.tmp.c:7817: at _v_panic: Backtrace
/tmp/v_1000/main.13380111000873620315.tmp.c:17765: by main__main
/tmp/v_1000/main.13380111000873620315.tmp.c:18160: by main