Skip to content

outplace and chaining #192

@Araq

Description

@Araq

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 != 4

The 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 with instead of use since it's now very close to Pascal's with statement (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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions