-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add Stdlib.todo
#13101
base: trunk
Are you sure you want to change the base?
Add Stdlib.todo
#13101
Conversation
b821aa0
to
ffe36a2
Compare
ffe36a2
to
d54a466
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this PR. I am rather in favor of having such a function, but I have doubts about the interface design. Do feel free to counter-argument.
stdlib/stdlib.mli
Outdated
val todo : ?msg:string -> ?__LOC__:string -> unit -> _ | ||
[@@alert todo "TODO: not implemented yet"] | ||
(** Raise an exception [Failure] | ||
with provided optional location [?__LOC__] and optional message [?msg]. | ||
@since 5.3 | ||
*) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I’m wrong, but to me, the main benefit of this function is to get compile-time warnings. If that’s the case, then we should be able to test that compiler output in the testsuite, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i feel like the main benefit is to have a shorthand to signify that we will implement a given piece of functionality later.
Also it should be possible to get a compile time Error from this:
[@@@ocaml.alert "++todo"]
let () =
Stdlib.todo ()
should give us:
Line 3, characters 0-11:
3 | Stdlib.todo ();;
^^^^^^^^^^^
Error (alert todo): Stdlib.todo
TODO: not implemented yet
I will push the test for the error.
Or you thought about introducing a new kind of warning into the compiler?
stdlib/stdlib.mli
Outdated
@@ -41,6 +41,13 @@ val invalid_arg : string -> 'a | |||
val failwith : string -> 'a | |||
(** Raise exception [Failure] with the given string. *) | |||
|
|||
val todo : ?msg:string -> ?__LOC__:string -> unit -> _ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t know what I think about labelling an argument __LOC__
. In my mind this name is reserved as a lexer placeholder, and the use of the function looks verbose to em. To get the location of the error, we have exception backtraces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, but i was going from the convention of passing explicit LOC from tezt
or something akin to ppx_here
.
But yeah, given the fact that user can just call Printexc.record_backtrace true
this seems excessive. removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using __LOC__
is a hack that I think I've seen in other libraries. There's no backtrace if compiled without debug information. This could be solved elegantly with Automatically insert source location #126.
EDIT: ah, sorry, I misunderstood. There's indeed no need to override the location with this parameter, the exception will do.
Here are a few thoughts:
|
how about we exclude this alert by default and enable it only when we pass
All in all it does seem like a its a better idea to add this as primitive to the compiler with a corresponding warning that can be enabled. |
Sure, but then we should add a note in the docstring so that users would be aware that they need to explicitly enable the alert. EDIT: it looks like the normal practice is already to disable by default any new alerts added to the standard library, which makes sense as I assume otherwise it could break builds (in the general case): Line 868 in eabbb40
|
I'm not fond of the |
I like the current design. I agree with @dbuenzli and @yawaramin that the alert should be disabled by default (I believe @yawaramin pointed to how to do that).
The semantics of this seem unclear to me: if I understand you correctly, if String.equal Config.architecture "amd64" then
let offset = todo in
List.iter (fun x -> x := !x + offset) l let offset = todo in
if String.equal Config.architecture "amd64" then
List.iter (fun x -> x := !x + offset) l It seems challenging to maintain correctness of the usual optimizations like hoisting operations out of loops, CSE… in this setting. I don’t think we want to go down this rabbit hole for the small gain in convenience.
Maybe I should know this, but why is adding to the initial scope frowned upon? I’m not against putting it elsewhere, but I don’t see a link between |
I would prefer the following: let todo _ = assert false val todo : _ -> _ So one can write: let f = todo "explain whatever needs to be done" And: if ... then ... else todo @@ some code that I know is wrong but is a good draft |
Because you are withdrawing names to use from the user. The user may want to use And then when people read her code it's not immediately clear if Finally it can also leads to strange error messages, or worse, lack thereof, when you move code around without, by mistake, taking all bound names with you. Having
If we agree adding to the initial scope is not a good idea. It has to go somewhere, feel free to propose a better place. We could say here that except for toplevel expressions, the raise is always part of a function that ends up
Rather like |
Mmh… I’m afraid that it could confuse newcomers by letting them think that the argument is magically left unevaluated (which isn’t true).
Understood. But if |
Again, I'd rather not withdraw (less to some extent now that the stdlib is namespaced) these generic module names from use by users. Especially if it's only to add this single identifier. If we take the constraint to not add a new module for it and not have it in the initial scope the only other candidate I see would be the "throw-it-all"
than
I had thought that having it as an Note the reason why I wanted a keyword-like
|
Don't have a horse in this race, but: if the gist of the proposal is to allow triggering an alert from arbitrary points in the code, why not do that instead? Then one could write |
In another direction we could have |
Because if your todos get in an execution and are hit the reported error does not clearly distinguish between a todo or something that should have not happened. |
If we want users to actually use the feature, it should be convenient to type, so |
More precisely, I think we could just do: (* in Fun or Sys or wherever we want *)
exception TODO of string
let todo msg = raise (TODO msg) |
I believe that is pretty much what current implementation does, except for the dedicated |
Please refer to #13072.
Added
val todo : ?msg:string -> __LOC__:string -> unit
to Standard library toplevel definitions.?msg
- is optional custom message, by default it is "not implemented yet".__LOC__
- is optional code location, where the function was called to simplify tracking of calls totodo
.Also i added a few tests, but i've put them into
testsuite/tests/lib-stdlib-todo/*
, was this a correct destination?