Hacker News new | past | comments | ask | show | jobs | submit login
A tiny language called Z (2013) (chrisdone.com)
165 points by goranmoomin on July 30, 2019 | hide | past | favorite | 47 comments



Cool idea with splitting function arguments into separate lines. It's a bit verbose, but avoids some of Python's old problems regarding what to do about inline lambdas.

But on the down side, now macros have to do string formatting (like adding indents and newlines) to produce output that is legible code, for example the "when" macro:

  defmacro when input
         fn blocks
            ap "if"
               ++ z:indent-before 3
                                  car blocks
                  ++ "\n"
                     ++ z:indent 3
                                 car cdr blocks
                        ++ "\n"
                           z:indent 3
                                    "unit"
            z:blocks input
That's one place where all languages that replace s-expressions with indentation seem to stumble equally: nested parens may look funny, but metaprogramming in lisps is delightfully easy because everything is a list and whitespace doesn't matter, so it's easy to produce and consume at compile time.


This isn't a problem with the syntax, you could just have macros consume and produce lists and avoid this entirely. In fact, there already exist reader macros that implement pretty much exactly this syntax but for Lisp: https://docs.racket-lang.org/sweet/index.html


Right, so you need to support mixing some lists in, to complement meaningful whitespace, the way sweet-expressions or SRFI-49 do. But that's exactly because the consequences of "whitespace only" syntax are too severe.


G, H, L, N, O, U, W and Y are the remaining letters for programming languages, grab one fast.


The Y language is a future AI programming language that instead of giving directions, it asks the computer questions and thus tries to provoke a response or change in behavior.


So, it's miniKanren?



That's because I is the same as SKK



Should we count PL/I?



But then you can add ++ to the letter effectively doubling the namespace size.



or suffix Script, e.g. JavaScript and the bonus with this one is that it doesn't need to relate to the original language in the least! It's a win-win-win.


objective-[x]Script-- not related to X?


But then that implies a relation with the language without the suffix, which is not usually true for new languages.


I call G!


I thought it was a lisp with a reader based on whitespaces other than parenthesis. An IDE with indentation support becomes a survival tool here. I would put it on the list of esoteric languages.


In fact, can't you achieve the author's point by writing a Lisp or Scheme reader?


That looks a lot like sweet expressions, which have been implemented for both Common Lisp and Scheme. More info here: https://readable.sourceforge.io/


The "Z" notation is easy to explain, but I think it has practical problems. In particular, even trivial functions end up taking a very large number of lines. Here's the blog post example of "Take the first n elements of list xs":

  defun take n xs
        if = n
             0
           unit
           if unit? xs
              unit
              cons car xs
                   take - n
                          1
                        cdr xs
Here's exactly the same thing using sweet-expressions (which I led the development of):

  defun take n xs
        if {n = 0}
           unit
           if unit?(xs)
              unit
              cons car(xs)
                   take {n - 1}
                        cdr xs
Even in this trivial example we see a 20% reduction in line use. We can trivially do a lot more, e.g., the last 3 lines could become one line for a 40% reduction in number of lines:

              cons car(xs) take({n - 1} cdr(xs))
Number of lines matters. Modern screens are typically quite wide but lack height, so a notation that requires the use of lots more lines for simple functionality means you can see far less information at one time (increasing change and debug time). Z-expressions also lack any kind of infix notation, which is a serious problem. Most software developers will not use a language without a built-in infix notation, for the same reason they won't use a line-oriented text editor... there are better alternatives available.

I think it's also especially easy to get things wrong. For example:

                   take - n
                          1
                        cdr xs
Is completely different from:

                   take - n
                        1
                        cdr xs
Indentation-sensitive notations where the amount of increased indentation causes different interpretations can make it very easy to insert unintentional and hard-to-detect bugs.

Anyway, my opinion, but hopefully I've provided some reasonable rationale for my opinion. I don't object to indentation-based syntax (obviously), but unsurprisingly I think there are better alternatives for this use case :-).


Temporary panicked flashback to having to learn Z (the formal notation) at university.


I also thought about that, although I have to slightly disagree because I actually like Z. Having only integers and sets really drove the point for me of "tell me what it does, not how it does it".

I should also mention that naming a project with a single letter guarantees that no search engine will easily find it. It took me forever to find a link to Z, and I knew what I was looking for...

(For those who never heard about Z: https://en.m.wikipedia.org/wiki/Z_notation)


> "tell me what it does, not how it does it"

({1},(∅ o α)) ∈ I̸=I ∧ ((∅ o α),{2,3}) ∈ I⊆I {M : Model; t : W | t ∈ [ e ]E M ∧(∀t :[e ]EM•[e ]]E (M⊕t)=[[e ]]E (M⊕t)) •M􏰀→[e]E (M⊕t)} ⊆ [[μe•e]]E

It's not always obvious to decipher what it does, either.


Can anyone tell me what that does do?


I wanted to give it a try, but the text has unicode errors that behave slightly diferent in every browser I tried, so I'm not sure how it's supposed to be read.

That said, here are two general pointers to get an idea:

1. Z uses sets, functions, and integers as its basic "type", on top of which you write more complicated "types". Therefore, in Z you often write specifications of the type "I have this element that belongs to this set, a function that maps elements of this 'type' to other types, and this operation says that my element is inserted into this mapping function" (without you writing down how the insertion is computed). Note that I write "type" in quotes because Z is not a programming language, and my use of the word type is a bit careless.

2. The comment is being a bit cheeky, since Z has comments, function names, and whitespace for better understanding that the comment is not using. The comment is right that the syntax can get complex at times, though, but calling your varibles "t" and "M" doesn't help.

Random fact: the Wikipedia example is a bit clearer, but written in Spanish. It details how to write a toy birthday agenda. It turns out that it was uploaded by a guy I personally know, which should give you an idea of the size of the Z community...


> The comment is right that the syntax can get complex at times, though, but calling your varibles "t" and "M" doesn't help.

For what it’s worth, this was posted verbatim from the spec :-D


We had to do extensive work in pen and paper and I just found it tortuous. I wouldn’t say I disliked the language itself or the rationale (although it’s not been something I’ve reached for in my career to date).


There's nothing like going up to a white board and covering it in obscure Z-Notation hieroglyphics for winning technical arguments


Are there languages that try to ignore whitespace as much as possible like Lisp and avoid almost most "redundant" enclosing delimiters like Python through advanced use of prefixes, separators and other fancy punctuation?

Most programming languages have very simple rules like "tokens end at incompatible characters or at whitespace" or "statements ends at the end of the line or at a semicolon"; there's probably an opportunity to spend some complexity on low-level syntax to reap benefits like macros without boring text and token manipulation.


The APL family of languages makes very limited use of delimiters. They are a bit more common in k and q, but in Dyalog APL and J, the use of adverbs makes almost always possible to write expressions without using any parens or with a very low number of them.

Concatenative languages such as (or derived from) Forth also use a very low number of delimiters, since they can usually be replaced by stack manipulation words.

I am not sure this is what you were asking, but if you do not know APL and/or Forth, I recommend you to have a look. It's a funny rabbit hole in which to get lost.


I know Forth, and I think it escapes the whitespace vs. delimiters dilemma by "cheating" in a very elegant but uninteresting way: manipulating the stack at runtime instead of munging strings and syntax trees at compile time, so that abstractions that would be macros in Lisp-style languages or relatively complicated classes, functions etc. in mainstream procedural languages can be a much simpler DSL of words that just do something to the stack and other execution state, without the burden of other concepts and representations.


In my mind, Forth "escapes" the whitespace-vs-delimiters issue by not having variadic functions. Forth code is more or less a direct transcription of the parse tree in the same way that lisp is, just postorder instead of preorder. And if you eliminated variadic functions from lisp, you wouldn't need its parentheses either.


I haven't Forthed in a long time, but you can write variadic words (e.g., "keep popping until a negative number is reached"). You just (a) shouldn't, probably; and (b) can't document their stack effect properly.


As someone spending a lot of time on the command line SSH'd into various servers I use vim for editing alot, and a language with easy editing (everything is line-based) seems like a cool idea, it reverses the trend of building more and more sophisticated (and complicated) IDE integrations for code formatting, splitting etc., instead favoring simple editing along newlines.


Great, but there is no word spelled "alot".



Is this like a lisp meets python?



Seems spiritually similar to Befunge: https://en.wikipedia.org/wiki/Befunge


I love it. A suggestion is to have something for parallel computations because personally I know I won't even try a language that doesn't have something for that. I think the way the language handles parallelism is key to its design and syntax. Other than that, it's really cool.


IMHO your editor should be formatting your Lisp with this kind of indentation anyway, parentheses or not. If you have that, Z-expressions seem kinda moot.


To me, the only syntax type I dislike more than tons of parentheses is significant indentation. But with s-expressions that's a presentation issue that can be solved with proper formatting and de-emphasising the parentheses visually, whereas significant indentation to me feels actively programmer hostile.

But while I also don't like the appearance of significant indentation, if it was just a presentation choice of an underlying more robust representation, I'd be fine with that.

So I sort-of agree - it seems like something that could be a neat editor plugin etc. on top of a s-expression based language and would be better for it than as the only/default syntax.


This is absolutely delightful! It's so different. It's like a kind of Forth or Lisp with unique structuring.


Z has very, very simple syntax. Weird, but simple. Here's how it works, function application is of the following form:

    name argument
This was the explicit design of Smalltalk. (Also of the non-C parts of Objective-C.) Subject verb.

    nameReference keyword: arg1 withArgs: arg2
The nameReference is the subject. The keyword:withArgs: is the verb.


The indentation style reminds me of Urbit's higher-level language Hoon.

https://urbit.org/docs/learn/hoon/style/


Nothing special. I am using templates and two times processing, so the template may have `<%= (some expression) %>` and such will be evaluated before it comes to Markdown processing. With thousands of pages it does matter if the Markdown processor is fast or if it has some "built-in" processing stuff that would cause delayed creation of pages.

Using templates and selective evaluation is simple and better.




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

Search: