summary refs log tree commit diff stats
path: root/lib/pure/strformat.nim
diff options
context:
space:
mode:
authorArne Döring <arne.doering@gmx.net>2019-04-09 08:14:59 +0200
committerAndreas Rumpf <rumpf_a@web.de>2019-04-09 08:14:59 +0200
commit2c645eded565d8f27b7e85e741dd90d2b54b17b2 (patch)
tree56778e5f475bb9130ef3b75afae9c7928e4dc7b0 /lib/pure/strformat.nim
parent58df5b0a8f9d5d1d6826bd178cbec3f7ea12a499 (diff)
downloadNim-2c645eded565d8f27b7e85e741dd90d2b54b17b2.tar.gz
add strformat limitations section (#10982)
* add strformat limitations section
* Update lib/pure/strformat.nim
Diffstat (limited to 'lib/pure/strformat.nim')
-rw-r--r--lib/pure/strformat.nim59
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/pure/strformat.nim b/lib/pure/strformat.nim
index 1132e6dc7..a8ceecf3d 100644
--- a/lib/pure/strformat.nim
+++ b/lib/pure/strformat.nim
@@ -211,6 +211,65 @@ The available floating point presentation types are:
 =================        ====================================================
 
 
+Limitations
+===========
+
+Because of the well defined order how templates and macros are
+expanded, strformat cannot expand template arguments.
+
+
+.. code-block:: nim
+  template myTemplate(arg: untyped): untyped =
+    echo "arg is: ", arg
+    echo &"--- {arg} ---"
+
+  let x = "abc"
+  myTemplate(x)
+
+First the template ``myTemplate`` is expanded, where every identifier
+``arg`` is substituted with its argument. The ``arg`` inside the
+format string is not seen by this process, because it is part of a
+quoted string literal. It is not an identifier yet. Then the strformat
+macro creates the ``arg`` identifier from the string literal. An
+identifier that cannot be resolved anymore.
+
+.. code-block:: nim
+  let x = "abc"
+  myTemplate(x)
+
+  # expansion of myTemplate
+
+  let x = "abc"
+  echo "arg is: ", x
+  echo &"--- {arg} ---"
+
+  # expansion of `&`
+
+  let x = "abc"
+  echo "arg is: ", x
+  echo:
+    var temp = newStringOfCap(20)
+    temp.add "--- "
+    temp.formatValue arg, "" # arg cannot be resolved anymore
+    temp.add " ---"
+    temp
+
+The workaround for this is to bind template argument to a new local variable.
+
+.. code-block:: nim
+
+  template myTemplate(arg: untyped): untyped =
+    block:
+      let arg1 {.inject.} = arg
+      echo "arg is: ", arg1
+      echo &"--- {arg1} ---"
+
+The use of ``{.inject.}`` here is necessary again because of template
+expansion order and hygienic templates. But since we generelly want to
+keep the hygienicness of ``myTemplate``, and we do not want ``arg1``
+to be injected into the context where ``myTemplate`` is expanded,
+everything is wrapped in a ``block``.
+
 Future directions
 =================