-
Notifications
You must be signed in to change notification settings - Fork 23
Description
There have been a couple of competing designs in order to add outplace and chaining to Nim. Here is a new one that tries to be convenient to use, simple to implement and without gotchas. Names have been chosen instead of operators for two reasons:
- How they interact with the "dot notation" is obvious.
- Many people prefer words over Perl-like custom operators.
outplace / dup
The current outplace should be renamed to dup focussing on the "works on a duplicate/copy" aspect. dup looks like the following:
macro dup*[T](x: T; calls: untyped): T = discard "implementation not part of the spec"
# examples
var a = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
doAssert a.dup(sort()) == sorted(a)
var aCopy = a
aCopy.insert(10)
doAssert a.dup(insert(10).sort()) == sorted(aCopy)
doAssert a.dup(insert(_, 10).sort()) == sorted(aCopy)As can be seen in the examples, the 2nd argument to dup is a list of "dot call expressions". The call expression can contain _, if so the _ is replaced by the copy that dup introduces. Otherwise the copy is passed as the first argument to the call.
chain / operateOn / on / use
The operateOn macro should be renamed to use. It looks like this:
macro use*[T](x: T; calls: untyped): void = discard "implementation not part of the spec"
var w: Window
w.use(setColor(green).setPosition(10, 20).setVisible(true))The same rules apply as for dup, the 2nd argument is a list of dot call expressions with optional _ markers. Notice that dup returns an expression of type T and that use returns an expression of type void.
Block syntax
Both operations also work with a "block syntax", the 2nd argument then is a block of statements that is transformed.
use w:
setColor(green)
setPosition(1, 2)
setVisible(true)
@[1, 2, 3, 4, 5].dup:
insert 10
sort()
filterByIt it != 4The block syntax does not support control flow, if etc are not allowed, only a flat list of call expressions and for every call the first argument is injected. The macros are deliberately not smart.
Alternatives to consider
- Use
withinstead ofusesince it's now very close to Pascal'swithstatement (only better, because no guesswork is involved). - Use
,for the non-block chaining syntax as it avoids ambiguities and feels more natural:
doAssert a.dup(insert(10), sort()) == sorted(aCopy)
This has the benefit that then simple calls can be written without the ():
doAssert a.dup(algorithm.sort) == sorted(aCopy)