Skip to content
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

typetraits: add rangeof(T), a shortcut for low(T)..high(T) #15232

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@
- Added `deques.toDeque`, which creates a deque from an openArray. The usage is
similar to procs such as `sets.toHashSet` and `tables.toTable`. Previously,
it was necessary to create an empty deque and add items manually.

- `std/with`, `sugar.dup` now support object field assignment expression:
```nim
import std/with
Expand All @@ -168,6 +168,29 @@
cannot be applied to every use case. The limitations and the (lack of) reliability
of `round` are well documented.

- Added `typetraits.rangeof` which returns a slice with the full range of
a given type. This is a shortcut for `low(T)..high(T)` aiming to improve
the ergonomics of performing safe type conversions, especially between
range types. Below is an example usage of the new function:
```nim
import typetraits, strutils

type
AllowedPort = range[1024..65535]

proc setupServer(port: AllowedPort) =
# Setup a webserver...
discard

stdout.write("Please enter a port [1024-65535]: ")
stdout.flushFile()
let port = stdin.readLine().parseInt()

if port in rangeof(AllowedPort):
setupServer(AllowedPort(port))
else:
stderr.write("Invalid port number")
```
Comment on lines +175 to +193
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since when do examples go into the changelog?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a trend started by Nim 1.2 where we put examples of new syntactic sugar to the change log.

Copy link
Member

@timotheecour timotheecour Jul 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

example belongs where the API is defined, not in the changelog (DRY, plus follows current convention, plus changelog is too big already for adding such examples)



## Language changes
Expand Down
29 changes: 29 additions & 0 deletions lib/pure/typetraits.nim
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,32 @@ since (1, 1):

type T2 = T
genericParamsImpl(T2)

func rangeof*(T: typedesc): Slice[T] {.inline, since: (1, 3, 5).} =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be named sliceof and then it's ready to go as far as I'm concerned.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sliceof sounds weird IMO. Example:

assert 42 in sliceof(Positive):

It's hard to understand that statement without knowing what slices are in Nim, and even then you'd need to whip out the docs just to know what sliceof() does.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it returns a Slice[T] so I have to know Nim's slice type.

Copy link
Collaborator Author

@alaviss alaviss Aug 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but arguably, comparing between these:

assert 42 in rangeof(Positive)

assert 42 in sliceof(Positive)

The former does a better job at saying "I want to make sure that 42 is within the range of type Positive".

You can know Slice[T] and still have to stop to look at the docs because sliceof(type) just sound alien.

## Returns a slice containing the full range of type `T`. This is a shortcut
## for `low(T)..high(T)`.
##
## This proc is useful for verifying whether value of one type
## can be safely converted to an another:
##
## .. code-block:: nim
## :test: "$nim $backend $options"
##
## import strutils
##
## type
## AllowedPort = range[1024..65535]
##
## proc setupServer(port: AllowedPort) =
## # Setup a webserver...
## discard
##
## stdout.write("Please enter a port [1024-65535]: ")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

example is way too complex especially for this simple API; good examples should illustrate semantics and edge case, that's it

## stdout.flushFile()
## let port = stdin.readLine().parseInt()
##
## if port in rangeof(AllowedPort):
## setupServer(AllowedPort(port))
## else:
## stderr.write("Invalid port number")
low(T)..high(T)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly think this is too short to justify it's own stdlib function, people can just write that themselves.