Limitations of the method call syntax

The expression x in x.f needs to be semantically checked (that means symbol lookup and type checking) before it can be decided that it needs to be rewritten to f(x). Therefore the dot syntax has some limitations when it is used to invoke templates/macros:

  1. template declareVar(name: untyped) =
  2. const name {.inject.} = 45
  3. # Doesn't compile:
  4. unknownIdentifier.declareVar

Another common example is this:

  1. from sequtils import toSeq
  2. iterator something: string =
  3. yield "Hello"
  4. yield "World"
  5. var info = something().toSeq

The problem here is that the compiler already decided that something() as an iterator is not callable in this context before toSeq gets its chance to convert it into a sequence.

It is also not possible to use fully qualified identifiers with module symbol in method call syntax. The order in which the dot operator binds to symbols prohibits this.

  1. import sequtils
  2. var myItems = @[1,3,3,7]
  3. let N1 = count(myItems, 3) # OK
  4. let N2 = sequtils.count(myItems, 3) # fully qualified, OK
  5. let N3 = myItems.count(3) # OK
  6. let N4 = myItems.sequtils.count(3) # illegal, `myItems.sequtils` can't be resolved

This means that when for some reason a procedure needs a disambiguation through the module name, the call needs to be written in function call syntax.