I would like to do logic like:
local function create(...)
for k, v in ipairs{...} do
if k == "player" then
_player = v
end
end
if _player == nil then
**error**("It nil") -- stop running here and throw the error
end
end
Does Lua has anything like error function here?
Yes, there is, and its name is exactly error():
if _player == nil then
error("It nil") -- stop running here and throw the error
end
error() takes a string argument for error message and an optional argument for level, it terminates the program when called.
Related
Zig's documentation shows different methods of error handling including bubbling the error value up the call stack, catching the error and using a default value, panicking, etc.
I'm trying to figure out how to retry functions which provide error values.
For example, in the below snippet from ziglearn, is there a way to retry the nextLine function in the event that a user enters greater than 100 characters?
fn nextLine(reader: anytype, buffer: []u8) !?[]const u8 {
var line = (try reader.readUntilDelimiterOrEof(
buffer,
'\n',
)) orelse return null;
// trim annoying windows-only carriage return character
if (#import("builtin").os.tag == .windows) {
return std.mem.trimRight(u8, line, "\r");
} else {
return line;
}
}
test "read until next line" {
const stdout = std.io.getStdOut();
const stdin = std.io.getStdIn();
try stdout.writeAll(
\\ Enter your name:
);
var buffer: [100]u8 = undefined;
const input = (try nextLine(stdin.reader(), &buffer)).?;
try stdout.writer().print(
"Your name is: \"{s}\"\n",
.{input},
);
}
This should do what you want.
const input = while (true) {
const x = nextLine(stdin.reader(), &buffer) catch continue;
break x;
} else unreachable; // (see comment) fallback value could be an empty string maybe?
To break it down:
instead of try, you can use catch to do something in the case of an error, and we're restarting the loop in this case.
while loops can also be used as expressions and you can break from them with a value. they also need an else branch, in case the loop ends without breaking away from it. in our case this is impossible since we're going to loop forever until nextLine suceeds, but if we had another exit condition (like a limit on the number of retries), then we would need to provide a "fallback" value, instead of unreachable.
You can also make it a one-liner:
const input = while (true) break nextLine(stdin.reader(), &buffer) catch continue else unreachable;
Hopefully the new self-hosted compiler will be able to pick up on the fact that the else branch is not necessary, since we're going to either break with a value loop forever.
Consider the following try/catch flow
function test(x)
try x^3
if x < 0; error("i only accept x >= 0"); end
return x^3
catch
return abs(x)^3
end
end
How can I display the error message (and stack trace) in the case test(-2) # == 8? In this case I know the error, but if it's a more complicated function with asserts etc, I'd like to know what specifically failed.
Trying rethrow() needs to be done in the try-catch block, but I still want a return value.
You can save the Exception into a variable after writing the variable name of your choice right after catch. error creates an ErrorException. You can see the fields of this Exception using fieldnames(ErrorException). The msg field gives you the message you passed to error. Alternatively, you may use showerror method.
function test(x)
try x^3
if x < 0; error("i only accept x >= 0"); end
return x^3
catch e
showerror(stdout, e)
# or
println(e.msg)
end
end
For the stack trace, you may use stacktrace(catch_backtrace()). We pass catch_backtrace to stacktrace, because what we usually want is to obtain the stack trace of the context of the most recent exception and not the current context.
I have the code below:
if err == nil {
body, err := ioutil.ReadAll(response.Body)
if err == nil {
dataMap := &models.UserResponse{}
json.Unmarshal(body, &dataMap)
if dataMap.User == (models.UserId{}) {
err = fmt.Errorf("unauthorized")
fmt.Println(err) // when unathorized, prints unauthorized
}
}
}
fmt.Println(err) // always prints nil
The Println inside if dataMap.User ... prints "unauthorized", whereas the last Println always prints nil.
I have no idea why it happens, err is declared via var err error at the beginning of this function.
The cause is detailed in Spec: Short variable declaration:
Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.
When using short variable declaration with multiple variables where one already exists, assignment will only happen to the existing variable if it was declared in the same block. Since in your case err variable existed before the if block, a new err variable will be created inside the if block, which has nothing to do with the "outsider" err variable (other than sharing its name). The outer err will be shadowed in the if block after the short variable declaration.
So what happens is that inside the if, you create a new err variable, and you assign a value to that, and you print that.
After the if statement, you will print the outer err variable whose value was not changed inside the if block, so it remains nil.
See this example:
var err error
fmt.Println("outside:", err) // nil
{
// A new err variable, shadows the outer:
i, err := strconv.Atoi("a")
fmt.Println("inside:", i, err) // 0 strconv.Aoti: parsing "a": invalid syntax
}
fmt.Println("outside:", err) // nil, because this was never changed
// Now this will change the "outer" err:
j, err := strconv.Atoi("a")
fmt.Println("outside:", j, err) // 0 strconv.Aoti: parsing "a": invalid syntax
Output (try it on the Go Playground):
outside: <nil>
inside: 0 strconv.Atoi: parsing "a": invalid syntax
outside: <nil>
outside: 0 strconv.Atoi: parsing "a": invalid syntax
If you want to use (assign to) the "outer" variable when also creating new variable(s), you can't use short variable declaration in a "nested" block but only simple assignment, in which case you also have to declare the other variables a priori, like in this example:
if err == nil {
var body []byte
body, err = ioutil.ReadAll(response.Body)
// ... rest...
}
See related questions:
Why it is possible to redefine err in multiple return statement in Go
Why there are two ways of declaring variables in Go, what's the difference and which to use?
You have created err inside block but you are printing same outside of block. Declare error outside of block and initialize it anywhere inside that will fetch the value when printing.
var err error
fmt.Println(err) // always prints nil
I have a 'while' loop as part of an OVM test that looks like this:
while (signal_val == 0) begin
signal_val = sla_vpi_get_value_by_name ("blah");
end
I want to restrict this loop for 120 microseconds only and exit after that. I want to quit the test if (signal_val == 0) is still not being satisfied at the end of 120µs. How do I achieve this?
I figured I'll have to call the 'global_stop_request()' to quit from the test, but trying to check the existing condition in the while loop for a fixed timeout value (120µs) seems to be tricky. Also, 'break' does not seem to be working. Any ideas?
Tried using 'break' this way, but 'break' gives a syntax error:
while (signal_val == 0) begin
signal_val = sla_vpi_get_value_by_name ("blah");
#120us;
break;
end
Your code won't work as you are expecting. Let us take a look:
while (signal_val == 0) begin
signal_val = sla_vpi_get_value_by_name ("blah");
#120us;
break;
end
signal_val is evaluated initially just once at the while statement, and since it is 0, you enter the while loop
signal_val gets the value returned by your function call. This happens at the same simulation cycle as the previous evaluation of while. Assuming that there is no change, you get 0 as the return value again
Now, the function waits 120us
Finally, it breaks out of while loop. signal_val isn't evaluated again.
To achieve the functionality you want, you would need to use fork...join and a watchdog task
fork
begin: wait_signal_val
while (signal_val == 0) begin
signal_val = sla_vpi_get_value_by_name ("blah");
if (signal_val == 1) begin
`uvm_info(get_name(), "YES!! signal_val was seen as 1", UVM_LOW);
end
else begin
#20ns; // (or some clocking mechanism)
end
end
end
begin: watchdog
#120us;
`uvm_fatal(get_name(), "NOPE!! signal_val is still 0 after 120us. Killing test");
end
join_any
disable fork
In the above code, either watchdog or wait_signal_val finishes. When that happens, the fork...join_any completes and disables the fork.
I use this a lot in my testbench for functionality like you describe and it works seamlessly.
I am attempting to run a conditional to basically see if the object is empty but I keep getting (similar variations) of this error:
invalid operation: release.Name == "" (mismatched types *string and string)
Here is the code that is dying:
import (
"github.com/google/go-github/github"
)
func TestLatestTag(user, project string) {
var client *github.Client
client = github.NewClient(nil)
releases, _, err := client.Repositories.ListTags(user, project, nil)
var release github.RepositoryTag
if err != nil {
fmt.Println("Error")
} else {
if release.Name == "" {
fmt.Println("None")
} else {
fmt.Println(releases[0])
}
}
}
If I change the if statement to *release.Name == "" as the error suggests I get a different error, which I don't really understand:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x26fd]
goroutine 1 [running]:
I'm sure there is any easy way to do this but I am not very familiar with handling objects/structs
From the error message it looks like you are trying to compare a string pointer (*string) to an actual string.
release.Name is a *string (a pointer to a string value)
"" is a string (is a string value)
They are two different types. So you can't compare them.
What you probably want to do instead is release.Name == nil
When a pointer that references to nothing (equals to nil) is tried to be dereferenced you get that second error. So in your case *release.Name panics because infact release.Name is nil
var release github.RepositoryTag
You never assign any value to that var. That's why *release.Name gives you a "runtime error": release.Name is a nil pointer
As per your code you have declared var release github.RepositoryTag, but you have not initialized it.
In structure RepositoryTag, Name is declared as *string which is a pointer and in case of release.Name == "", string comparison is attempted which is incorrect hence "mismatched types *string and string" error.
In case of *release.Name == "", since release is not yet initialized, it is complaining "invalid memory address or nil pointer dereference"
You need to do two things, 1st initialize, release and second, check release.Name = nil.