Hacker News new | past | comments | ask | show | jobs | submit login
Z – A dynamic functional programming language that compiles to JavaScript (zlanguage.github.io)
65 points by fuzzythinker 32 days ago | hide | past | web | favorite | 40 comments

At first I thought this was some reference to the well-known Z specification language (https://en.wikipedia.org/wiki/Z_notation). Come on guys, pick a name that a) doesn't clash with a language that has been around since the 1970s, and b) can realistically be found in a web search.

The language itself looks decent enough, but what's the compelling reason for using this rather than one of the many other languages? I'm sure there must be one, scratching a personal itch aside, but at least tell us about the rationale.

> doesn't clash with a language that has been around since the 1970s

I don't think 1970 is much of a filter.

That's pretty much the same as saying "doesn't clash with a language since the beginning of time".

To my knowledge, the 70s are mostly not the beginning of time.

In software, it almost is.

It's literally the "beginning" of Unix time, which most systems use.

Yes, I was wondering if I should add "(except timestamps)" where I made my previous post.

> what's the compelling reason for using this rather than one of the many other languages?

vs JavaScript (which it transpiles to) the intro teases more functional programming features like lambdas, but that's the only reference in the doc. The intro to functions section does not mention strict lambdas, only anonymous functions, so it's not clear if they can still access globals.

I would welcome lambda syntax in JS, you can sort of just be strict with yourself, but it takes more effort to _read_ when something is a lambda but you have to manually parse it to be sure.

Yes I use arrow functions all the time but I was under the impression expressions must be strictly closed to be true lambdas? although to be honest i can't find any definitive info on this, so now I suspect my definition might be too strict...

I find it very useful to know that all variables in the expression are bound, expressions with free variable can be more complex to reason about, which is fine, but it would be nice to be able to easily differentiate without having to carefully parse each expression first - so a separate syntax just for that purpose would be nice - I thought that's what true lambda functions were (disallowing free variables), but it looks like i'm wrong, i guess that feature doesn't exist.

Z performs coercion, but it's coercion rules make more sense than JavaScript's:

    "9" + 2 # ==> 11
    "9" ++ 2 # ==> "92"

Yeah, that just doesn't make things better

Why not? It's not entirely explicit but it seems that the `++` operator is only for string concatenation, so using it with anything else that a string means it's going to be converted to string. I'm just curious about how the compiler enforces it.

What is the result of "badger"+2

If + is to be defined on a string and a number then the only sensible meaning is string concatenation. All numbers can be converted to strings but most strings cannot be converted to numbers.

There is a good reason to not define it because it is not associative: in JavaScript 2+2+"x" != 2+(2+"x")

> What is the result of "badger"+2

The same result as `convert_to_number("badger") + convert_to_number(2)`. In Z it seems that converting an invalid string to number yields NaN, so "badger" + 2 returns NaN.

> There is a good reason to not define it because it is not associative: in JavaScript 2+2+"x" != 2+(2+"x")

The problem with + not being associative in JavaScript is because it's actually two different operators: String concatenation and number addition. Z doesn't have this problem because + is only number addition.

Personally I prefer strong typing (and thus `string + number` throwing an error and/or being a compile-time error), but it seems like the way Z does coercing is very sensible and doesn't have the same issues as JavaScript.

I agree. I kind of hate to say this, but Perl (5) got this right by having an explicit concatentation operator for strings (given how common they are in many programming tasks), and then a separate addition operator.

This seems to be the case for Z, too, doesn't it?

Correct me if I'm wrong, but PHP also has the same with the . notation, though perhaps because it was inspired by Perl.

It makes things better.

++ is for concatenation.

+ is for arithmetic.

Coercion or not, it's always puzzled me when languages used the same symbol.

I guess they're both associative and have identity values, but that's about it. One is commutative, the other is not.

* makes about as much sense for concatenation as +.

With similar goals and similar feature set there's LiveScript, probably a decade old at this point: https://livescript.net

It lacks some features of Z, from a cursory glance, for example there's no `match` construct, but it packs most of the features around function currying, piping values, destructuring inputs, composing and so on into a indentation based, low-noise syntax. Syntax preference is of course a personal thing; I prefer the LS one. I've been using LiveScript on and off for years, starting back in the CoffeeScript days on the frontend, then with node, and most recently for Tizen programming. The language is on life support for many years now, meaning no new features - last addition were generator functions - but the feature set is still ahead of JS. There's a bit of an uncomfortable feeling when using constructs like let and const, which compile to very different things than what you get in ES, but well, they were implemented in LS first, so it's understandable.

I may consider Z next time I have a chance, if it's actively maintained and developed. JS may have become a better language, but it's not optimized for functional-first programming - there's no escaping the verbose syntax and the malnoutrished stdlib. It may look like it is, but that's only in comparison with Java or PHP - if you put it beside OCaml and Elixir you'll see it sticking out like a sore thumb. Which isn't bad, of course, JS is a multiparadigm, general-purpose language and it has huge amounts of backward compatibility - with both code and human minds - to uphold. Still, if you want FP-only, it's easier to use another language instead of trying to bend JS almost to the point of breaking with still subpar results.

I see a lot of reasons listed to use Z, most seem to be improved syntax, but what I don’t really see there is the answer to “why?”. Why is Z being developed? Surely not just to smooth out minor syntax annoyances?

> Z also has the ternary operator, though it's syntax is more readable than most programming languages:

I’m kind of a fan of the very terse ternary, I personally don’t feel like

    X = if cond1 value1 
        else if cond2 value2
        else value3
Is particularly more “readable” than

    X = cond1 ? value1 : (cond2 ? value2 : value3)
I do appreciate the multi-line functional if statement, but the big reason for use of a ternary in my book is when I really want or need a one-liner. Plus I like having a very obviously different syntax for the functional if vs the imperative if, I don’t want them to look similar.

That said, readability seems like a weak argument and always prone to subjective debate. For the last several jobs I’ve had we used auto-formatters and have completely gotten rid of stupid programmer debates about readability.

> The first thing Z clarifies is that Exceptions are not baseballs. For some reason, rather than "raising" an issue, you would "throw" it. That makes no sense at all.

FWIW, this text is off-putting, it’d be better to just describe the syntax Z uses without the incredulity. This feels like a titch of bike-shedding. The big problems with exceptions have nothing to do with the keywords and everything to do with the design. That said “settle” feels weird and it’s also going to be potentially confusing when you try to add a “finally” block, or a re-raise semantic.

> If you forget to settle an error, Z will throw a runtime error.

Should that be “Z will raise a runtime error”?

At a quick glance at least it seems that what Z offers is a better (in the eyes of its designer) syntax. I glanced through to about the ternary operator in order to find the USP. After going back just now I found "The Why of Z" and it seems to be that text output typically needs some kind of module import:

    "First off, the import statement is clutter. Why can't the text function be built-in, perhaps?"
So it seems it's not out to solve the bigger issues of programming...

So what's the "killer feature" of this? I.e. how is it better than Elm, Reason, ClojureScript, ScalaScript etc?

This isn't a criticism of OP but my general thoughts about a new programming language project.

I think that every new language should show one thing that the language can do well, wheres other languages can't; in other words, we need motivating examples. I've always having a trouble figuring out why a language was created in the first place.

The best selling feature is coming with a platform, everything else is less important.

If the platforms succeeds, the language is deemed to success and eventually outlive the platform.

Anything else is kind of yet another programming language.

But a platform gets creates if there is a reason to pick the language in the first place, usualy by curious people with time. Nobody in production would choose a new language, sure, that comes later.

UNIX was initially designed in Assembly, C came later after the couple of BCPL and B interations.

LiveScript came after Web as platform was being adopted.

.NET was created to replace COM (did not went accordingly as planned), with VB, Java and C++ on board, with support for multiple languages. C# came later given the outcome of the Sun process.

Using Ruby outside Rails development is not so common.

Younger Python developers might not be aware of this, but there were only two reasons to pick Python on the late 90's, either one disliked Perl and wanted something else, or had to deliver Web applications in Zope.

Looks interesting, but I don't see a compelling reason to choose Z over the myriad of other transpile to JS languages out there. I wonder if the author or user(s) can chime in?

>let x: 5 # ==> x is now 5

>x: "Hola Mundo" # ==> x has changed types

One of the biggest complaints people have about JS is the lack of strict typing. So, this doesn't appear to solve it.

Inversely, one thing a lot of older JS people dislike (I'm an older JS person, but this doesn't apply to me) is how functional JS is getting, so I don't think this will be very popular with that crowd. Especially considering how many features are being added via the ecmascript proposal process/babel transpiration (eg: https://github.com/tc39/proposal-pipeline-operator)

I don't know, it reminds me of LiveScript plus goroutines. http://livescript.net/

Cool, but if you want to sell it, Z needs a "killer app". What does this do better than ANY other language?

Ex: Web server in 5 lines, or super simple matrix manipulation.

I am not a fortuneteller, but I can still predict that programing language designers will soon run out of letters to use as names for their languages.

Mm. Looking at the examples, it seems like the JavaScript snippets are rather verbose and there's not a "fat arrow" in sight. If you're accepting pull requests, I would love to provide more succinct code for comparison's sake.

Side note: how does this compare to other languages that tote cross-compiliation to JS (Haxe, Nim, ReasonML, js_of_ocaml, TypeScript, etc.)?

Nim compiles to C, C++, Objective C as well.

I think the title should be corrected. It is not a strictly functional language, it states that it is a multi-paradigm language, and the examples look more imperative than anything else to me. The docs say it leans toward functional dynamic programming but I'd like to see some justification for that claim.

The "explicit settling" of exceptions is IMHO an excellent idea. I wish more languages had this.

I do think it's interesting to compare Go-style green threading with JS-like async/await syntax. The main question is: are Z threads cooperative (as in JS) or preemptive (as in Go)?

> you can still cause side effects and create impure functions without dealing with monads or working your way through atoms

Why do they have to put a dig to other languages in the opening paragraph?

Quite an ugly language syntactically. I like some of the features like support for literals of any base. But ES2019 is pretty awesome without adding much extra transpiling - I recommend the Elvis operator!


Does it not support bitwise operators? it seems to use ^ for pow, and I can't find them in the docs.

They seem to be available as functions under a global object named "JS":

  JS.&(x, y)
  JS.|(x, y)
  JS.^(x, y)
  JS.<<(x, y)
  JS.>>(x, y)
  JS.>>>(x, y)

What does this language do differently from others? AFAICT it's a vanity project.

I thought this was an "A to Z" for functional languages that compile to JavaScript, but in reverse.

Calling the umpteenth JS obfuscator a language is a bit of a stretch, but hey, it enhances the npm module swamp by one more instance.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact