Nim
Nim copied to clipboard
typetraits: implements `value in type`
This is useful for safe runtime type conversion, especially in range-heavy code.
Example:
type
AllowedPort = range[1024..65535]
stdout.write("Please enter a port [1024-65535]: ")
stdout.flushFile()
let port = stdin.readLine().parseInt()
if port in AllowedPort:
setupServer(AllowedPort(port))
else:
stderr.write("Invalid port number")
Unrelated CI failures.
it would be ok to have flow typing for that . e.g. making usage of port as AllowedPort an error in the other branch: is this something that the z3-based tool can do ?
That'd be a good idea. I don't know how to use drnim though, so probably this can be added by someone with the knowledge after this PR.
To be honest I don't think it a good idea to mix types and runtime values this way. IMO, constants are much better for your use case:
const AllowedPort = 1024..65535
stdout.write("Please enter a port [1024-65535]: ")
stdout.flushFile()
let port = stdin.readLine().parseInt()
if port in AllowedPort:
setupServer(AllowedPort(port))
else:
stderr.write("Invalid port number")
Possibly you can come up with more convincing example.
An use case that I have is for parsers (yes, I'm aware of times.parse, this is just an example):
import times, strscans, typetraits
func parseDate(s: string): DateTime =
var y, m, d: int
if scanf(s, "$i-$i-$i", y, m, d):
if m notin Month:
raise newException(ValueError, $m & " is not a valid month")
if d notin MonthdayRange or d == 0:
raise newException(ValueError, $d & " is not a valid day of the month")
result = initDateTime(d, Month(m), y, 0, 0, 0)
else:
raise newException(ValueError, "No valid date found")
Note that slices are not a replacement for range types. If a value is of a range type, it means that the value is guaranteed to be within the range, thus we can forward it without having to perform any checks. The main issue is that the stdlib don't provide any (ergonomic) way to perform the first check. This PR is meant to solve that.
Note that range type is just one possible use case. Other use cases include conversion between enum and int (useful when you store the enum in a database, for example), safe conversions from/to unsigned types, etc.
@cooldome We can already do array[SomeEnum, T]; it makes sense if you think of enums as a set of their valid entries.
But then you could also say it makes sense to do a in uint8 ...
Opened #15232 as an alternative where the separation between types and values is more pronounced.
Agree, last example is convincing. #15232 is more appealing
This pull request has been automatically marked as stale because it has not had recent activity. If you think it is still a valid PR, please rebase it on the latest devel; otherwise it will be closed. Thank you for your contributions.
Rebased
This PR can use some additional polish now that there are facilities for dealing with holey enums. However I want to know whether upstream would like this solution before investing more time into it.
I'm actually surprised that this isn't already implemented.
Note that slices are not a replacement for range types. If a value is of a range type, it means that the value is guaranteed to be within the range, thus we can forward it without having to perform any checks. The main issue is that the stdlib don't provide any (ergonomic) way to perform the first check. This PR is meant to solve that.
This is especially true now that Defects are a thing (and it's always been possible to turn range checks off anyway).
This pull request has been automatically marked as stale because it has not had recent activity. If you think it is still a valid PR, please rebase it on the latest devel; otherwise it will be closed. Thank you for your contributions.