-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Implement generic fromBin|Oct|Hex in strutils #11107
Conversation
Is it possible to design generics for this? I don't like the idea of hardcoding types (int, uint, etc) in proc names. |
There was an awesome effort put in by @timotheecour a while back: #10346, but unfortunately they PR got closed. See nim-lang/RFCs#84. |
@kaushalmodi I think this could be easily done by: import parseutils
proc parseFromBin*[T: SomeInteger](v: var T, s: string) =
let p = parseutils.parseBin(s, v)
if p != s.len or p == 0:
raise newException(ValueError, "invalid binary integer: " & s)
var bin: int8
bin.parseFromBin("0b11011")
doAssert bin == 0b11011 ... or something. But there is already the proc |
Then may be that should be deprecated? Asking @Araq to weigh in on this. |
Mistery - koch changes oct literal when generating doc examples! my code in strutils.nim: runnableExamples:
let a = "0o_123_456_777"
doAssert a.parseOctInt8() == 0o377'i8
block:
let a = "0o_123_456_777"
doAssert a.parseOctInt8() == 0o777'i8 # <--- see this! and fails with the error:
If I try |
0o777 is 0x1FF in hexadecimal, a byte can represent from 0x00 to 0xFF. And 0xFF is 0o377 so the output is correct modulo the int8 range. |
The thing is - I put in runableExamples But how can it be that this change happens while extracting my code into separate examples file? |
Well the "extraction" is ... er... special. :-) |
parseXIntX in the docs, but parseXintX by fact. |
@data-man Yes, you are right, there would be a problem for autocompletion as you say. proc fromBin*[T: SomeInteger](v: var T, s: string) =
let p = parseutils.parseBin(s, v)
if p != s.len or p == 0:
raise newException(ValueError, "invalid binary integer: " & s)
var x: int8
x.fromBin("0b11011") Especially when there are already procs And then we could probably deprecate |
Personally I'd prefer universal |
They add this parseTernaryInt in their own library just like I did here: https://github.com/status-im/nim-stint/blob/6853ebe97c21426952ce64c2df6278514797dc3f/stint/io.nim#L116-L117 func parse*[bits: static[int]](input: string, T: typedesc[Stuint[bits]], radix: static[uint8] = 10): T =
## Parse a string and store the result in a Stuint[bits].
func parse*[bits: static[int]](input: string, T: typedesc[Stint[bits]], radix: static[int8] = 10): T =
## Parse a string and store the result in a Stint[bits] or Stuint[bits]. |
lib/pure/strutils.nim
Outdated
@@ -1068,44 +1068,145 @@ proc parseFloat*(s: string): float {.noSideEffect, procvar, | |||
|
|||
proc parseBinInt*(s: string): int {.noSideEffect, procvar, | |||
rtl, extern: "nsuParseBinInt".} = | |||
## Parses a binary integer value contained in `s`. | |||
## Parses a binary integer value contained in `s` and returns `int`. |
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.
"And returns int"? Do we need to assume nobody can read Nim type declarations?
I appreciate the effort but this should use generics indeed. You can then deprecate the non-generic variant or simply leave it as it is. |
@Araq When talking about generics, what variant would you prefer: proc fromBin*[T: SomeInteger](x: var T, s: string) =
let p = parseutils.parseBin(s, x)
if p != s.len or p == 0:
raise newException(ValueError, "invalid binary integer: " & s)
var x: int8
x.fromBin("0b11011") or proc fromBin*[T: SomeInteger](s: string): T =
let p = parseutils.parseBin(s, result)
if p != s.len or p == 0:
raise newException(ValueError, "invalid binary integer: " & s)
var x: int8
x = fromBin[int8]("0b11011")
# by the way, x = "0b11011".fromBin[int8] would not work:
# cannot instantiate: 'T' and other errors |
This variant: proc fromBin*[T: SomeInteger](s: string): T =
let p = parseutils.parseBin(s, result)
if p != s.len or p == 0:
raise newException(ValueError, "invalid binary integer: " & s)
var x: int8
x = fromBin[int8]("0b11011")
# by the way, x = "0b11011".fromBin[:int8] would work perfectly fine. |
I feel like we're back to typedesc vs generics API design here with a sprinkle of backward compatibility concerns (nim-lang/RFCs#40) Anyway, I would be happy to merge the non-controversial state from here: c1d7ea9 and discuss/split the later commits with API issues in a separate PR. |
The stdlib uses |
runnableExamples tests will not pass until #11131 is fixed. |
What should I do about that?
|
This is fixed now.
Where does |
@narimiran, it's in |
Ah, I found it. It is
This can then be fixed by patching the mentioned package by having this line: import strutils except fromHex |
Merged status-im/nim-blscurve#21 and retriggering CI. Can we put Appveyor under a Nim organisation. I can restart Travis builds but not Appveyor's. |
This is ready for review. |
Implement all families of proc like
parseBinInt8
,parseBinInt16
, ...,parseBinUint64
(and Oct|Hex) in strutils returning their respective types of integer.