-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Functions that return single error #17
Comments
Consider nil error as |
Here is the exec.brg that I added to std/os/exec use io
use os
use syscall
use time
fn LookPath(file: string) -> Result<string> { EXT }
fn Command(name: string, arg: VarArgs<string>) -> *Cmd { EXT }
struct Cmd {
...
}
impl (c: *Cmd) {
fn Start() -> Result<()> { EXT }
fn Run() -> Result<()> { EXT }
fn StderrPipe() -> Result<io.ReadCloser> { EXT }
fn StdinPipe() -> Result<io.WriteCloser> { EXT }
fn StdoutPipe() -> Result<io.ReadCloser> { EXT }
fn String() -> string { EXT }
fn Wait() -> Result<()> { EXT }
} and tried to call the functions match exec.Command("borgo", "build").Run() {
Ok(_) => fmt.Println("Build successful")
Err(e) => {
fmt.Println("Build failed:", e)
return
}
}
exec.Command("go", "run", ".").Run() The problem is that exec.Command().Run() generates this code var3_result := func() Result[struct{}, error] {
var1_check, var2_err := exec.Command("borgo", "build").Run()
if var2_err != nil {
return make_Result_Err[struct{}, error](var2_err)
}
return make_Result_Ok[struct{}, error](var1_check)
}() which results to compilation error: |
Hey @arslanarm thanks for looking into this without any docs whatsoever! This is a case I hadn't considered and I can confirm the existing translation to Option/Result by the compiler won't cut it. I haven't thought this through yet but my gut reaction would be to add another built-in type So to answer your question, the definition would be: impl (c: *Cmd) {
fn Run() -> Nilable<error> { EXT }
} and you would use it something like this: match exec.Command("borgo", "build").Run().toOption() {
None => fmt.Println("Build successful")
Some(e) => {
fmt.Println("Build failed:", e)
return
}
} This is a pattern that will come in handy in other places as well so we need a way to support nil interfaces. What do you think? |
Hi, adding So I propose adding |
I agree in this specific case |
Didn't recall any stdlib functions that return nilable interface. But after looking up docs, found this https://pkg.go.dev/[email protected]#Lookup |
Awesome, thanks for looking it up! |
Also, how would you define os.exec.Cmd struct. My take on this struct: struct Cmd {
Path: string,
Args: [string],
Env: Nilable<[string]>,
Dir: string,
Stdin: Nilable<io.Reader>,
Stdout: Nilable<io.Writer>,
Stderr: Nilable<io.Writer>,
ExtraFiles: Nilable<[*os.File]>,
SysProcAttr: *syscall.SysProcAttr,
Process: Nilable<*os.Process>,
ProcessState: Nilable<*os.ProcessState>,
Err: Nilable<error>,
Cancel: fn() -> Result<()>,
WaitDelay: time.Duration
} NOTE: it is a go struct, so some of the fields are nilable. |
I'm thinking So to go back to the original example, the return type stays true to the Go definition: impl (c: *Cmd) {
fn Run() -> error { EXT }
} And then you'd call let err = exec.Command("borgo", "build").Run()
match isNil(err) {
Some(err) => ...,
None => ...,
} In the specific case of an let err = exec.Command("borgo", "build").Run()
match Result.fromError(err) {
Ok(()) => ..,
Err(err) => // handle error
} I prefer this design better as it doesn't add complexity to the compiler and doesn't try to hide the underlying semantics of existing Go code. This will also come in handy for nil pointers. What do you think? |
TLDR: I would like to stick with the idea of Actually, not a totally bad idea. But it affects Note: Actually, I am very biased toward null-safety in languages, because I am a kotlin developer, and I really like what language designers have done to preserve null-safety, and be fully compatible with java. Some knowledge about kotlin's null-safety that can be helpful(I hope it will be helpful): Example: fun main() {
val `some java integer` = JavaClass.staticFunctionThatReturnsInteger()
val myInt: Int = `value I assume is not null`
println(myInt + 1)
} In this example This way we don't compromise on null-safety, but that leads to runtime errors, if interactions with java don't go as we expected. I like it, because it not only preserves the full null-safety in kotlin code, also it helps debug the code, because it throws a P.S. you don't need to write kotlin "definitions" to interact with java libs. So |
That's great, Kotlin is actually a good reference to take inspiration from.
If I read this correctly, this would be equivalent to At this point I think this is the best way forward, I'm just not convinced about special casing Final take: impl (c: *Cmd) {
fn Run() -> NilResult { EXT }
}
let err = exec.Command("borgo", "build").Run()
match err.toResult() {
Ok(()) => ...,
Err(err) => ...,
} The |
About fn runBorgoBuild() -> Result<()> {
let borgoBuildCommand = exec.Command("borgo", "build")
borgoBuildCommand.Run()? // Result<()>
borgoBuildCommand.Wait()? // Result<()>
match borgoBuildCommand.Err { // Option<error>
Some(e) => Err(e)
None => Ok(())
}
} But I guess I am fine with: fn runBorgoBuild() -> Result<()> {
let borgoBuildCommand = exec.Command("borgo", "build")
borgoBuildCommand.Run().toResult()? // NilResult
borgoBuildCommand.Wait().toResult()? // NilResult
match borgoBuildCommand.Err.toOption() { // Nilable<error>
Some(e) => Err(e)
None => Ok(())
}
} Of course it would be fire if we could declare impl (err: Nilable<error>) {
fn toResult() -> Result<()> {
match err.toOption() {
Some(e) => Err(e)
None => Ok(())
}
}
} |
I was writing definitions for os/exec and stumbled upon functions that return single error.
Example:
https://pkg.go.dev/os/exec#Cmd.Run
Run() returns
error
if error happened, otherwise returnsnil
.I tried wrapping
error
inOption
. But that assumes that there is secondbool
return argument.Then I tried using
Result<()>
, but still it assumed that there are two return arguments.What should I use for this use case?
The text was updated successfully, but these errors were encountered: