Why you absolutely should avoid Now

The syntax is inspired by Tcl!

The author really liked to write in Tcl (he says that it's the only language in which he can go back to a project after a year and continue working as if it was day 2 -- see, we're not even talking about Now itself and already concluded the author is stupid!), but was annoyed by some clunky constructions using multiple nested command execution, like when a command is used as argument to another command, especially noticeable when indexing lists or dicts.

So, instead of writing this:

set lista [list a "This value gets printed" c d]
puts [lindex lista 1]
# This value gets printed
    

In Now you could write this:

set lista [list a "This value gets printed" c d]
print [o $lista : get 1]
# This value gets printed
    

Yeah, but no. The syntax is actually crazy!

I know you're looking into the above example and thinking: "why?". Of course! Why try to improve a syntax that's awful from the beginning? Why keep building over such a terrible foundation?

Well, that's not even half of the problem. You could write that same code in yet another manner. The first line, for instance, could be written as that:

list a "This value gets printed" c d | as lista
    

Actually, there's even a preferred way of writing these "pipelines":

list a "This value gets printed" c d
    | as lista
    

The "pipe" (`|`) has a special meaning. Or not. It depends on how each "command" decides to interpret it.

You can understand it better by looking into how `print` works:

print "--> " [list 1 2 3]
# --> (1 , 2 , 3)
list  10 20 30 | print "--> "
# --> (10 , 20 , 30)
    

You see? A pipe will basically make the result of the previous command to be used as the last argument for the next one.

And it gets worse

Getting an item from a list was done using `:`, that is like a pipe, but indicates that the next command is a method of the previous command's result. So, in this case:

print [o $lista : get 1]
    

You're basically telling Now to get the object "lista", call the method "get" with "1" as argument, then print the result of that.

But, as you already know, we could also write it as:

o $lista
    : get 1
    | print
    

But what is that "o"???

I hear you. What is that `o`?

You see, in Now there's only one strict format for doing the most basic thing, that is calling commands, and that is:

command arguments?
    

So, this works fine:

print
    

And also this:

print lista
    

But not this:

$lista | print
    

Because `$lista` is not a command. It's simply a value.

So we need a command to reference a value. And this command is o. It takes some arguments and returns exactly these same arguments.

o $lista
    | print
# (1 , 2 , 3 , 4 , "etc")
    

And there's yet another way to "get"...

print ($lista . 1)
    

You remember I just said there's "only one way" of doing things in Now? Well, it seems that rule is already broken!

Actually what happens is that the parentheses are a form of syntatic sugar: what they do is to turn an prefix notation into infix notation.

For instance, in this case:

print (1 + 2 + 3 + 4 + 5)
# 15
    

What is actually happening is:

print [+ 1 2 3 4 5]
# 15
    

The "language" sacrifices being coherent in the name of being easier to the developer. Preposterous!

Now, if you think about it, this construction:

o (a , b , c , d)
    

Is actually this:

o [, a b c d]
    

So it means the comma is actually an alias to `list`?

Yes, it is.

It focus too much on pipelines

Instead of mimicking the battle-tested behavior of good old languages, Now focuses on having powerful pipelines. The idea is to be able to do most of what you need without having to break the flow of the data from the first command to the last.

Again, preposterous

So stopping your train of thought to set a new variable is kinda considered an anti-pattern in Now.

A normal person would write code like this

# Remove the current user from /etc/passwd
o $env
    : get "USER"
    | as username
path "/etc/passwd"
    | as filepath
o $filepath
    : read.lines
    | as lines
o $lines
    | foreach line {
        if [o $line : contains $username] {
            skip
        } {
            print $line
        }
    }
    

But a seasoned Now programmer would write this, instead

scope "Remove the current user from /etc/passwd" {
    o $env
        : get "USER"
        | as username
    path "/etc/passwd"
        : read.lines
        | filter {o : contains $username : eq false}
        | {print}
}
    

Explicit is better than implicit, amiright?

Did you noticed there's this weird `| {print}` in the end of the above program? That's an implicit foreach. And we all know that "explicit is better than implicit". Because it is.

But Now, instead of following this divine rule, tries to make the developer life easy by avoiding to write this all the time:

    | foreach line {
        print line
    }
    

And you know what? There's even a implicit transform!

list  1 2 3
   | {o : mul 10}  # this thing
   | {print}
# 10
# 20
# 30
    

But we won't bend to this sloppy way of thinking, of course we would write this much more correct, more explicit!, version:

list 1 2 3
    | transform x {
        return ($x * 10)
    }
    | foreach x {
        print $x
    }
    

Ah, much better! Look how many characters we are typing, now.

Line-continuation is marked by a dot

Again, instead of doing things the way everybody does, that is, escaping the newline character using a \ in the end of one line, Now let the end of the line alone and indicates that the next line is, in fact, a continuation of the previous one.

So, this:

print alfa beta gama
    

Can also be written like this:

print
    . alfa beta gama
    

Or even:

print
    . alfa
    . beta
    . gama
    

Is this supposed to look like some sort of ASCII art???

What a joke!

You can handle errors inside the pipeline

We all love a good block of try/catch, right? But Now decided it's too normal for it to implement and, instead, have this thing called "events" that also serve to handle errors.

Like this:

http.get "http://example.com/teste"
    ! 500 {print "Maybe the server is down?" ; return error}
    ! 404 {print "Shit, this page doesn't even exist!" ; return error}
    ! * {print "Shit, some other error occurred..." ; return error}
    | return
    

It's not so catchy at first glance, but imagine you're doing it directly in your shell, like:

$ now :cmd 'http.get "https://example.com/teste" ! * {exit 1} | print'
    

It's not a multi-purpose programming language

If it's not supposed to solve every possible problem, how can it be any useful?

It's not even a programming language!

The author is emphatic in calling it a tool...

You don't write programs, you write documents

This may be the worst part.

Imagine that! Instead of writing a "script" or a "program", you are supposed to write a document! With a title, a description and... and... sections!

Just like this:

[Example Document]

This document exemplifies some of the syntax
of a Now document.

[procedures/hello]
parameters {
    who {
        type string
    }
}

print "Hello, $who!"

[commands/run]
parameters {
    who {
        type string
        default "world"
    }
}

hello $who
    

Like... you can't simply shove code into a file and call it a day. No, you have to follow the proper form, just like some ascient COBOL code.

And what about these 'commands'?

A Now document saved as `Nowfile` in the current directory will make running `now` without any arguments drop this in your terminal:

$ now
Now Website

 passwd ---------> Test the code for 'grepping -v' the /etc/passwd file
 build ----------> Build the Website.
    

Now you see why Now forces you to write a title for your document...

In order to actually do something, you call one of the available commands, like `now build`.

It lives in a gray area between a shell and a real programming language

Now definitely is not something you could use as a shell, since you have to declare "system_commands" in order to call anything from the system it's running on.

[system_commands/ls]
command {
    - ls
}

    

Isn't that awful? Now even checks if the command actually is available before running your prog... document. It may be nice to not have any command not found being found during runtime, but if that's the price, I don't know, maybe it isn't worth paying.

It's written in D -- and nobody uses D

D is nice, but the language has no direction, no plans, right? You probably didn't even heard that before, since nobody talks about D.

Now has almost 8k LOC written in D. What a shameful decision that was!

It barely has standard library

Yeah, really. It has a whole lot of various commands, but nothing even close to Java or C#.

It has zero database connectivity baked in

In order to use a database, one have to rely on a "library". And libraries are not like shared-object libraries as normal people would expect: in Now, a library is implemented using a form of IPC: it keeps an external program running and send or receive calls to procedures using the standard input and output to send messages serialized in JSON.

So, technically, it's kinda easy to write a library to any DBMS, but who would do that?

It can't even work with YAML!

Yeah, it was abandoned because the author consider that there's no hope for YAML, that the format is terrible and overly complex. Now you have to convert everything to JSON if you want to work with data that's originally in YAML.

It implements weird concepts like "shells" and "commands"

Imagine your program have to call a bash script. Of course you're going to have it in a file somewhere in your project folder! But, no, in Now you can write this same script virtually like any other section in the document and call it a script, to be executed by some shell.

Like this:

[shells/bash/scripts/date]
parameters {
    format {
        type string
        default "%Y-%m-%d"
    }
}

date +$format

[commands/run]

date "%Y"
    | collect
    : first
    | print "The current year is "
    

You can even define many shells that will call other programs and then write the "scripts" inside the document. Like, imagine having a document where you can write Markdown and it's capable of rendering itself.

And that's a waste. A folder with a 'document.md' and a 'run.sh' will have the same effect.

It's not Web-focused

What's the use on anything that can't serve HTTP???

Now is fully capable of serving SCGI, though, but what's the point? SCGI probably stands for SlowCGI, right?, the exact opposite of FastCGI! Who cares if it's simple? What we all need is fast!

Because every single Website we create absolutely must support 100k clients per second. We all know that.

And all that is only the tip of the iceberg...

You can even define many shells that will call other programs and then write the "scripts" inside the document. Like, imagine having a document where you can write Markdown and it's capable of rendering itself.

And that's a waste. A folder with a 'document.md' and a 'run.sh' will have the same effect.

It's not Web-focused

What's the use on anything that can't serve HTTP???

Now is fully capable of serving SCGI, though, but what's the point? SCGI probably stands for SlowCGI, right?, the exact opposite of FastCGI! Who cares if it's simple? What we all need is fast!

Because every single Website we create absolutely must support 100k clients per second. We all know that.


Stay away

My advice: stay away from the project repository on Github .