Closed al6x closed 3 years ago
I believe you want something like this:
converter toPriority(s: string): Priority {.compileTime.} = parseEnum[Priority](s)
# should be similar to how compileTime procs work
var x: Priority
x = "high" # works
let str = "high"
x = str # does not compile
converter toPriorityRuntime(s: string): Priority = parseEnum[Priority](s)
x = str # works
An alternative could be this:
converter toPriority(s: static string): static Priority = static parseEnum[Priority](s)
but this would complicate things.
@hlaaftana thanks, {.compile_time.}
is close to what I want, but it doesn't work, try it.
Yes, sorry, I was merely proposing its use here.
So ... sometimes your string literals are checked at compile-time and sometimes they are not? Seems like a really bad idea, sorry. You should use the enum values directly when you can.
sometimes your string literals are checked at compile-time and sometimes they are not?
If it's a simple string literal - it always checked at compile time (don't know if it's possible to implement though).
Seems like a really bad idea, sorry.
Hmm, I look at it a bit differently, from the user perspective. I write a program and I want the program to be correct and bugs detected as soon as possible.
The way it currently works - enum conversion problems would be caught late, when program is running. With this proposal some of those bugs would be detected immediately. So, from my point of view as a user - it is an improvement.
As for how exactly those checks would be implemented - with compiler, or with linter or some other code analysis tools - it's not that important.
Anyway, feel free to close if it's not aligned with Nim design and principles :)
Ah it's just a tooling convenience ... I suppose we can never have enough of these. Still doesn't look particularly important to do, does it?
Still doesn't look particularly important
I guess it depends on the use case, probably not that important if you don't use enums heavily. In my case I use it a lot, let's write stock scanner (we are looking for good mining stocks with put option insurance available) with string and raw enums:
stocks.find do (s: stock) -> bool:
s.sector in ["copper", "silver", "uranium", "gold"] and
s.stock_risk == "low" and
s.country_risk < "high" and
s.stock_size in ["medium", "large"] and
s.financial_score >= "stable" and
s.option_chain.find_at_least(("put", 0.7, 180)).is_some
With raw enums, it doesn't look that good, and you have to remember all those prefixes.
stocks.find do (s: stock) -> bool:
s.sector in [ssCopper, ssSilver, ssUranium, ssGold] and
s.stock_risk == srLow and
s.country_risk < crHigh and
s.stock_size in [ssMedium, ssLarge] and
s.financial_score >= fsStable and
s.option_chain.find_at_least((orPut, 0.7, 180)).is_some
And it's also used in lots of other places, when you prepare the data, analyse it, write rules etc, lots of enums.
This feature would allow to write DSL-like nicely looking code easily and validate it's correctness (and if conversion not just checked but also done at compile time it would be also fast).
With raw enums, it doesn't look that good, and you have to remember all those prefixes.
Sure, but you don't have to use the prefixes for raw enums. Nor do you have to use raw enums, you can also use .pure
enums.
Yes, I like pure enums, but sadly they still have name conflicts. Maybe instead of this feature it would be possible to improve pure enums so that it would resolve conflicts automatically?
Example:
type
Color {.pure.} = enum red, orange, yellow, green, light_blue, blue, violet
RGB {.pure.} = enum red, green, blue
let c: Color = red
P.S.
As far as I know Nim compiler doesn't do backward type inference because of performance reasons, but in that case it looks like just one step lookup, it should be cheap.
What's so annoying about:
let c = Color.red
?
It's annoying in examples like this one:
proc processInput(w: GLFWWindow) =
if w.getKey(Escape) == GLFWPress:
w.setWindowShouldClose(true)
elif w.getKey(W) == GLFWPress:
camera.processKeyboard(cmForward, deltaTime)
elif w.getKey(S) == GLFWPress:
camera.processKeyboard(cmBackward, deltaTime)
elif w.getKey(GLFWKey.A) == GLFWPress:
camera.processKeyboard(cmLeft, deltaTime)
elif w.getKey(D) == GLFWPress:
camera.processKeyboard(cmRight, deltaTime)
note GLFWKey.A
which has to be prefixed because A is also a gamepad button
EDIT: actually nevermind, it's an artifact of using a wrapper. Using type instead of conversion to int32
should solve it for native Nim programs
This feature would allow to write DSL-like nicely
To me the string based version isn't nicer. What if you want to refactor the names? Refactoring symbols is more obvious and can be assisted by IDEs. With strings you just have lots of hard-coded magic values that may or may not be convertible to enum values.
To me the string based version isn't nicer. What if you want to refactor the names?
@bluenote10 I see, yes symbols would be fine too, if naming conflict would be resolved.
What's so annoying about:
let c = Color.red
?
@Araq clean, nice, expressive code paint(red)
or company.risk = low
looks much better than the paint(Color.red)
or company.risk = CompanyRisk.low
.
P.S.
Seems like discussion moved away from the string enums toward pure symbol enums, maybe I should close this thread and create another RFS for the automatic conflict resolution for pure symbol enums?
Feel free but I'm about to write an RFC about this as well...
Sorry, I didn't get to write the RFC yet. However, this one here is "rejected".
In many cases converters could be checked at compile time.
It should help to decrease runtime errors, improve runtime performance (as conversion done just once at compile time), require no change in the language, and shouldn't slow down compiler (compiler can skip the check if the conversion is too complicated).
It should work for all converters, but I would like to highlight the usage with the example for string enums.
As a bonus, we would get literal types for string that are fast for free.
Fast because
string -> enum
conversions will be done at compile time, and during the runtime the enum (in example I usestring -> string
enum, but it also could bestring -> int
enum) will be used instead of the string, so all the "literal string" enum comparison operations will be in reality fastint
comparisons.P.S.
And it's aligned with plans for 2021 for Nim - stability and less bugs :).