sequtils now support strict effect tracking (#18782)

This commit is contained in:
Andreas Rumpf 2021-09-02 14:35:25 +02:00 • committed by GitHub
commit 69cabaa81c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 9 deletions

View file

@ -84,6 +84,11 @@ import std/private/since
import macros import macros
when defined(nimHasEffectsOf):
{.experimental: "strictEffects".}
else:
{.pragma: effectsOf.}
macro evalOnceAs(expAlias, exp: untyped, macro evalOnceAs(expAlias, exp: untyped,
letAssigneable: static[bool]): untyped = letAssigneable: static[bool]): untyped =
## Injects `expAlias` in caller scope, to avoid bugs involving multiple ## Injects `expAlias` in caller scope, to avoid bugs involving multiple
@ -356,7 +361,7 @@ func distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] =
first = last first = last
proc map*[T, S](s: openArray[T], op: proc (x: T): S {.closure.}): proc map*[T, S](s: openArray[T], op: proc (x: T): S {.closure.}):
seq[S]{.inline.} = seq[S] {.inline, effectsOf: op.} =
## Returns a new sequence with the results of the `op` proc applied to every ## Returns a new sequence with the results of the `op` proc applied to every
## item in the container `s`. ## item in the container `s`.
## ##
@ -382,7 +387,7 @@ proc map*[T, S](s: openArray[T], op: proc (x: T): S {.closure.}):
result[i] = op(s[i]) result[i] = op(s[i])
proc apply*[T](s: var openArray[T], op: proc (x: var T) {.closure.}) proc apply*[T](s: var openArray[T], op: proc (x: var T) {.closure.})
{.inline.} = {.inline, effectsOf: op.} =
## Applies `op` to every item in `s`, modifying it directly. ## Applies `op` to every item in `s`, modifying it directly.
## ##
## Note that the container `s` must be declared as a `var`, ## Note that the container `s` must be declared as a `var`,
@ -401,7 +406,7 @@ proc apply*[T](s: var openArray[T], op: proc (x: var T) {.closure.})
for i in 0 ..< s.len: op(s[i]) for i in 0 ..< s.len: op(s[i])
proc apply*[T](s: var openArray[T], op: proc (x: T): T {.closure.}) proc apply*[T](s: var openArray[T], op: proc (x: T): T {.closure.})
{.inline.} = {.inline, effectsOf: op.} =
## Applies `op` to every item in `s` modifying it directly. ## Applies `op` to every item in `s` modifying it directly.
## ##
## Note that the container `s` must be declared as a `var` ## Note that the container `s` must be declared as a `var`
@ -420,7 +425,7 @@ proc apply*[T](s: var openArray[T], op: proc (x: T): T {.closure.})
for i in 0 ..< s.len: s[i] = op(s[i]) for i in 0 ..< s.len: s[i] = op(s[i])
proc apply*[T](s: openArray[T], op: proc (x: T) {.closure.}) {.inline, since: (1, 3).} = proc apply*[T](s: openArray[T], op: proc (x: T) {.closure.}) {.inline, since: (1, 3), effectsOf: op.} =
## Same as `apply` but for a proc that does not return anything ## Same as `apply` but for a proc that does not return anything
## and does not mutate `s` directly. ## and does not mutate `s` directly.
runnableExamples: runnableExamples:
@ -429,7 +434,7 @@ proc apply*[T](s: openArray[T], op: proc (x: T) {.closure.}) {.inline, since: (1
assert message == "01234" assert message == "01234"
for i in 0 ..< s.len: op(s[i]) for i in 0 ..< s.len: op(s[i])
iterator filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): T = iterator filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): T {.effectsOf: pred.} =
## Iterates through a container `s` and yields every item that fulfills the ## Iterates through a container `s` and yields every item that fulfills the
## predicate `pred` (a function that returns a `bool`). ## predicate `pred` (a function that returns a `bool`).
## ##
@ -453,7 +458,7 @@ iterator filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): T =
yield s[i] yield s[i]
proc filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): seq[T] proc filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): seq[T]
{.inline.} = {.inline, effectsOf: pred.} =
## Returns a new sequence with all the items of `s` that fulfill the ## Returns a new sequence with all the items of `s` that fulfill the
## predicate `pred` (a function that returns a `bool`). ## predicate `pred` (a function that returns a `bool`).
## ##
@ -480,7 +485,7 @@ proc filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): seq[T]
result.add(s[i]) result.add(s[i])
proc keepIf*[T](s: var seq[T], pred: proc(x: T): bool {.closure.}) proc keepIf*[T](s: var seq[T], pred: proc(x: T): bool {.closure.})
{.inline.} = {.inline, effectsOf: pred.} =
## Keeps the items in the passed sequence `s` if they fulfill the ## Keeps the items in the passed sequence `s` if they fulfill the
## predicate `pred` (a function that returns a `bool`). ## predicate `pred` (a function that returns a `bool`).
## ##
@ -685,7 +690,7 @@ since (1, 1):
if pred: result += 1 if pred: result += 1
result result
proc all*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): bool = proc all*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): bool {.effectsOf: pred.} =
## Iterates through a container and checks if every item fulfills the ## Iterates through a container and checks if every item fulfills the
## predicate. ## predicate.
## ##
@ -727,7 +732,7 @@ template allIt*(s, pred: untyped): bool =
break break
result result
proc any*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): bool = proc any*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): bool {.effectsOf: pred.} =
## Iterates through a container and checks if at least one item ## Iterates through a container and checks if at least one item
## fulfills the predicate. ## fulfills the predicate.
## ##

View file

@ -8,6 +8,9 @@ import std/sequtils
import strutils import strutils
from algorithm import sorted from algorithm import sorted
{.experimental: "strictEffects".}
{.push warningAsError[Effect]: on.}
# helper for testing double substitution side effects which are handled # helper for testing double substitution side effects which are handled
# by `evalOnceAs` # by `evalOnceAs`
var counter = 0 var counter = 0
@ -507,3 +510,5 @@ template main =
static: main() static: main()
main() main()
{.pop.}