nim-lang / RFCs

A repository for your Nim proposals.
135 stars 26 forks source link

The `fmt` macro should handle any expression #366

Closed al6x closed 3 years ago

al6x commented 3 years ago

Currently fmt wont' work with object creation, if/else and other limitations.

It's possible to workaround those problems, as in example below, but would be nice if fmt would support any expression. Maybe even make string interpolation part of language as it's used very frequently.

proc MessageEl(message: Message): string =
  let edit    = action("edit", (id: message.id))
  let delete  = action("delete", (id: message.id))
  fmt"""
    <div id={message.id} class="message flashable">
      <span>{message.text.escape_html}</span>
      <button on_click={delete}>Delete</button>
      <button on_click={edit}>Edit</button>
    </div>
  """

proc MessagesEl(messages: seq[Message]): string =
  fmt"""
    <div id="messages">
      {messages.map(MessageEl).join("\n")}
    </div>
  """
haxscramper commented 3 years ago

Making string interpolation a part of a language is strictly inferior solution on my opinion, as it requires hardcoding a particular behavior that can easily be implemented using reader macro.

Current implementation does not support using if/else only because it is implemented using rather straightforward expression parser https://github.com/nim-lang/Nim/blob/f25243140baa00db4a663d453a262e41f8d9073f/lib/pure/strformat.nim#L564 it would be very annoying to have to reimplement parser for "any expression", but if/else is common enough case, and quite simple to fix.

shirleyquirk commented 3 years ago

only stared at this for five minutes, but the fact that ':' is used in the DSL as the format specifier delimiter seems to be the main issue. adding fmtChar=':' tostrformatImplandfmt`, would at least allow users to override that delimiter and use for loops and if statements. it's not perfect but at least it wouldn't break anything.

Araq commented 3 years ago

The format specifier delimiter was taken from Python fwiw. But I haven't checked if Python allows for other constructs that also use the colon (slicing comes to mind).

bluenote10 commented 3 years ago

Python can handle colons in slices. I think they rely on colons being wrapped in [ ... ] though, i.e. parsing may be handled similarly to colon in quotes. For instance declaring a lambda doesn't work:

image

Araq commented 3 years ago

This is now supported but colons have to be inside any kind of parenthesis.

al6x commented 3 years ago

Awesome! Thanks guys! :)