One thing I love about Nim, is the fact that functions/methods are all equal - that you can use the object-dot syntax vs function-call syntax, as well as property-syntax (no parens) all on the same functions. Brilliant, in every sense of the word!
I'm wondering what you think of introducing a fourth function-calling syntax, resembling literal XML?
This could be extremely useful when building document models, rendering forms etc.
For example:
var form = <form action="/login">
<input type="text" name="username" value=login_form.username />
<input type="text" name="password" value="" />
<button type="submit" value="Log in" />
</form>
The whole thing expands to a function call graph, e.g. calling a form() function with a named argument action="/login".
The nested tags could be unrolled as tags in one of two ways, I'm not sure which is best or more meaningful, but I suppose either top-down or from leaf-nodes towards root-nodes - e.g. either form(action="/login").input(type="text"...).input(...) etc. or form(action="/login", children=[input(type="text", ...)]) etc.
It's a very half-baked idea, obviously, I'm just throwing it out there - the Opa language has something like this. I don't understand precisely how it works in Opa either, but it's one of the killer features that makes it very familiar and useful for web-development.
With support for macro/template calls as well, this feature could be crazy powerful. Imagine for example something like Bootstrap forms being possible with dedicated bootstrap tags, with everything getting expanded at compile-time for incredible flexibility and extremely low run-time overhead.
Or something like database schema models or other configuration structures being built in this manner, but statically type-checked against method signatures, totally extensible, and with IDE support and compile-time checks for everything, it would actually be better and safer than real XML for a lot of the stuff people use XML for at the moment.
Thoughts? :-)
This is just a macro away. The final syntax then would be:
var form = xmlCall"""<form action="/login">
<input type="text" name="username" value=login_form.username />
<input type="text" name="password" value="" />
<button type="submit" value="Log in" />
</form>"""
Most of the time, Nim doesn't need more features. ;-)
Actually the syntax would be
nimble install templates
import annotate
var form = xml"""
<form action="/login">
<input type="text" name="username" value=login_form.username />
<input type="text" name="password" value="" />
<button type="submit" value="Log in" />
</form>
"""
The XML would also be syntax-highlighted if you use the NimLime sublimetext plugin, like this: http://imgur.com/geOJIHr
Of course that's HTML, so you can also use html""" ... """
Just wanted to mention that the best server side web framework I have ever used uses an internal DSL for HTML generation. So similar idea but IMHO more powerful. See some code snippets here:
http://seaside.st/documentation/callbacks
I have built a fairly advanced issue tracker in Seaside and this mechanism combined with a continuation based component model (abstracting away the whole request/response cycle) creates a very powerful "its all code" way of building web apps - especially useful in making complicated UIs.
Now... server side HTML generation is NOT the "modern way" (although still useful of course) - HTML5 makes it possible to do all the HTML generation/modification on the client in javascript. Avi Bryant has made tons of really funny and good presentations, and this one at Rails Conf explains it quite well "Rails is obsolete (but so is everything else)":
http://confreaks.com/videos/359-gogaruco2010-rails-is-obsolete-but-so-s-everything-else
...and that was 5 years ago!
In the Smalltalk community Amber does exactly this and has "copied" the component model and "HTML as Smalltalk" style that Seaside uses. I also know Nicolas Petton (author of Amber) has written a similar framework for "raw javascript" (Nicolas and I used it at a customer):
https://github.com/NicolasPetton/htmlCanvas/blob/master/counter.js
Note the renderOn method where the form and its callbacks are defined in this similar DSL.
@Orion
I know you can solve this with macros - what I was hoping to get out of it though, is static binding.
My wish is not simply to embed XML in code, or to parse XML and generate code at compile-time - but rather to have a function-calling syntax designed for tree structures of function calls, with awareness (and static binding) for parent/child relationships.
Making it XML-like in terms of syntax is just a means of reusing an already-familiar syntax for tree structures. What I'm proposing is not pure XML - note how the attributes (named arguments) are literal code expressions which can reference variables or other members.
I don't know, maybe there's a better way? I don't know Nim very well yet. But passing a long string to a macro at compile-time doesn't really seem to accomplish what I'm after.
@gokr
server side HTML generation is NOT the "modern way"
Er, that completely depends on what you're doing - if you're rendering content you want to get picked up and indexed by a search engine, server side HTML is still necessary. For forms, I agree, it's maybe not that critical - but may be simpler and in some cases safer than working with client-side data binding.
It just depends on what you need/want for a particular solution - but certainly server-side HTML generation is not obsolete, it's still quite relevant for some things.
…but rather to have a function-calling syntax designed for tree structures of function calls, with awareness (and static binding) for parent/child relationships.
Something like htmlgen?
Something like htmlgen?
Hmm, yes, but the evaluation order here is still leaf-to-root, right?
So a child can't know about it's parent - I think maybe that's the point of the XML-like syntax, evaluation order is from the root towards the leaves, with children being added to parents and/or children being aware of their parent.
It's sort of similar to how a SAX parser works, where the parent nodes are created first, then child nodes are created in the order they are encountered.