diff --git a/changelog.md b/changelog.md index 7ecc7dd235595..e1f4c56fe4ab5 100644 --- a/changelog.md +++ b/changelog.md @@ -54,7 +54,8 @@ - Added `minIndex` and `maxIndex` to the `sequtils` module - Added `os.isRelativeTo` to tell whether a path is relative to another - Added `resetOutputFormatters` to `unittest` -- Added new `sugar` `.@` outplace operator: `@[2,1,3].@sort()` +- Added new `outplaces` module with `.@` outplace operator: `@[2,1,3].@sort()` to avoid duplicating API's + with inplace and outplace variants; instead only the inplace variant is needed now. ## Library changes diff --git a/lib/pure/sugar.nim b/lib/pure/sugar.nim index bac78d22643be..575dd5f11ba54 100644 --- a/lib/pure/sugar.nim +++ b/lib/pure/sugar.nim @@ -189,58 +189,6 @@ macro capture*(locals: openArray[typed], body: untyped): untyped {.since: (1, 1) result.add(newProc(newEmptyNode(), params, body, nnkProcDef)) for arg in locals: result.add(arg) -macro outplace*[T](arg: T, call: untyped; inplaceArgPosition: static[int] = 1): T {.since: (1, 1), deprecated: "use sugar.`.@`".} = - expectKind call, nnkCallKinds - let tmp = genSym(nskVar, "outplaceResult") - var callsons = call[0..^1] - callsons.insert(tmp, inplaceArgPosition) - result = newTree(nnkStmtListExpr, - newVarStmt(tmp, arg), - copyNimNode(call).add callsons, - tmp) - -proc outplaceImpl(arg, call: NimNode): NimNode = - expectKind call, nnkCallKinds - let tmp = genSym(nskVar, "outplaceResult") - var callsons = call[0..^1] - var found = false - for i in 1.. 0. - ## **Since**: Version 1.2. - runnableExamples: - import algorithm, strutils - doAssert @[2,1,3].@sort() == @[1,2,3] - doAssert "".@addQuoted("foX").toUpper == "\"FOX\"" - doAssert "A".@addQuoted("foo").toUpper[0..1].toLower == "a\"" - proc bar(x: int, ret: var int) = ret += x - doAssert 3.@bar(4, _) == 3 + 4 # use placeholder `_` to specify a position > 0 - doAssert @[2,1,3].@sort(_) == @[1,2,3] # `_` works but unneeded in position 0 - result = copyNimTree(rhs) - result = replaceOutplace(lhs, result) - proc transLastStmt(n, res, bracketExpr: NimNode): (NimNode, NimNode, NimNode) {.since: (1, 1).} = # Looks for the last statement of the last statement, etc... case n.kind @@ -278,6 +226,16 @@ proc transLastStmt(n, res, bracketExpr: NimNode): (NimNode, NimNode, NimNode) {. template adder(res, v) = res.add(v) result[0] = getAst(adder(res, n)) +macro outplace*[T](arg: T, call: untyped; inplaceArgPosition: static[int] = 1): T {.since: (1, 1), deprecated: "use outplaces.`.@`".} = + expectKind call, nnkCallKinds + let tmp = genSym(nskVar, "outplaceResult") + var callsons = call[0..^1] + callsons.insert(tmp, inplaceArgPosition) + result = newTree(nnkStmtListExpr, + newVarStmt(tmp, arg), + copyNimNode(call).add callsons, + tmp) + macro collect*(init, body: untyped): untyped {.since: (1, 1).} = ## Comprehension for seq/set/table collections. ``init`` is ## the init call, and so custom collections are supported. @@ -333,28 +291,6 @@ macro collect*(init, body: untyped): untyped {.since: (1, 1).} = when isMainModule: since (1, 1): - import algorithm - - block: - var a = @[1, 2, 3, 4, 5, 6, 7, 8, 9] - doAssert a.@sort() == sorted(a) - #Chaining: - var aCopy = a - aCopy.insert(10) - doAssert a.@insert(10).@sort() == sorted(aCopy) - doAssert @[1,3,2].@sort().@sort(order = SortOrder.Descending) == @[3,2,1] - # using 2 `.@` chained together - - proc bar(x: int, ret: var int) = ret += x - doAssert 3.@bar(4, _) == 3 + 4 - - import random - - const b = @[0, 1, 2] - let c = b.@shuffle() - doAssert c[0] == 1 - doAssert c[1] == 0 - #test collect import sets, tables diff --git a/lib/std/outplaces.nim b/lib/std/outplaces.nim new file mode 100644 index 0000000000000..f96613b9376d7 --- /dev/null +++ b/lib/std/outplaces.nim @@ -0,0 +1,46 @@ +import std/macros +include system/inclrtl + +proc outplaceImpl(arg, call: NimNode): NimNode = + expectKind call, nnkCallKinds + let tmp = genSym(nskVar, "outplaceResult") + var callsons = call[0..^1] + var found = false + for i in 1.. 0. + ## **Since**: Version 1.2. + runnableExamples: + import algorithm, strutils + doAssert @[2,1,3].@sort() == @[1,2,3] + doAssert "".@addQuoted("foX").toUpper == "\"FOX\"" + doAssert "A".@addQuoted("foo").toUpper[0..1].toLower == "a\"" + proc bar(x: int, ret: var int) = ret += x + doAssert 3.@bar(4, _) == 3 + 4 # use placeholder `_` to specify a position > 0 + doAssert @[2,1,3].@sort(_) == @[1,2,3] # `_` works but unneeded in position 0 + result = copyNimTree(rhs) + result = replaceOutplace(lhs, result) diff --git a/tests/stdlib/toutplaces.nim b/tests/stdlib/toutplaces.nim new file mode 100644 index 0000000000000..8370be503cc2d --- /dev/null +++ b/tests/stdlib/toutplaces.nim @@ -0,0 +1,30 @@ +import std/outplaces +import algorithm +import random + +proc main() = + var a = @[1, 2, 3, 4, 5, 6, 7, 8, 9] + doAssert a.@sort() == sorted(a) + #Chaining: + var aCopy = a + aCopy.insert(10) + doAssert a.@insert(10).@sort() == sorted(aCopy) + doAssert @[1,3,2].@sort().@sort(order = SortOrder.Descending) == @[3,2,1] + # using 2 `.@` chained together + + proc bar(x: int, ret: var int) = ret += x + doAssert 3.@bar(4, _) == 3 + 4 + + const b = @[0, 1, 2] + let c = b.@shuffle() + doAssert c[0] == 1 + doAssert c[1] == 0 + + block: + var a = "foo" + var b = "bar" + doAssert "ab".@add("cd") == "abcd" + let ret = "ab".@add "cd" # example with `nnkCommand` + doAssert ret == "abcd" + +main()