Live data from Hacker News

The Janet Language

janet-lang.org

181–190 of 203 posts

Re: The Janet Language

#181
post #19

Earlier quoted context omitted.

Normal people prefer syntax-less, unambiguous lisp-languages over the mess we have now. Just look at Javascript, rust or C++ and tell me normal people prefer that. Only worse languages win, because people are masochochists, but throwing away this possible user base is always a win.

> Normal people prefer syntax-less, unambiguous lisp-languages over the mess we have now. Normal people prefer REBOL, but timing and licensing choices...

Well, REBOL was based on Logo, which was based on Lisp...

Re: The Janet Language

#182

Earlier quoted context omitted.

That's a ridiculous statement. Linked lists have real performance benefits in some applications. A good "modern CS toolbox" includes the ability to make the right choice. Which, if you believe they are fundamentally useless, clearly you lack.

> Linked lists have real performance benefits in some applications. Maybe in 0.01% of the cases. In reality they just ruin your cache and memory allocator performance for no real good reason.

In many cases you can get around these issues by being a little more clever in how you allocate nodes. In some cases you don't have the luxury of allocating all elements next to eachother anyway, in which case an intrusive linked list is often the best option to minimise copying. You might say use a vector of pointers or a circular buffer, but if you're in a timing sensitive context you might be unable to realloc.

Hell, memory allocators themselves are often implemented using some form of linked list. You tend to see them quite a bit at very low levels like in kernels.

Re: The Janet Language

#183
post #91

Earlier quoted context omitted.

vaguely kinda related. I want to like lisp for its features but the syntax is too much for me to pick up without serious time investment, which I am not sure I want to make. are there any other languages that support for example lisp-like interactive REPL, eg analyzing program state while it is running?

Funnily, I'm the exact opposite. I love the simple and consistent syntax of Lisp, but I don't want to use a dynamically typed language if I can avoid it.

That's why I fell in love with SBCL, it'll warn me about things like "hey, you told me this variable is an integer, but you're calling length on it, that doesn't make sense."

Re: The Janet Language

#184
post #152

Earlier quoted context omitted.

Agreed. This is why I don't do any math I can't do on my fingers. Parentheses are just too scary, and there's no way that parenthesis math junk actually has any useful ideas.

I understand the reaction, but some people feel just as negatively about parentheses as lispers feel positively. If I can feel positively about a language purely because of the parens, it's no sillier to feel negatively for the same reason.

I actually agree with that entirely, and the point of my jest was just to say that we should look deeper for the important ideas, not refuse to read the book because we don't like the color of the cover.

Lispers don't feel positive about Lisp because of parentheses; change them to curly braces or brackets or ^ and $—that's really not what matters. Lisps with brackets go all the way back to the beginning (https://en.wikipedia.org/wiki/M-expression). Indentation-based Lisps have been done too (https://readable.sourceforge.io/).

The point is an expression-based syntax that directly models the code tree, is written in the data structures of language, and is convenient for meta-programming. It's a fundamentally different approach that yields massive benefits (see my other comment in the thread if you want to hear that spelled out in more detail).

But we don't see that when we just stop at unfamiliar syntax.

Lispers have been structurally-editing code as a matter of course since at least 1970. Most of the rest of the world only got a taste of that when tree-sitter came out circa 2018 (I know I'm rounding the edges here, but the point stands). Half a century later! Why is that? It's not just curly braces vs parens—something deeper is happening here.

I do apologize if I came off rude. I'm just so frustrated at hearing this same line year after year after year from people who are missing out some of the most powerful ideas in programming because they prefer this ASCII glyph over that one. It's nothing more than parochialism.

It just makes me want to scream (perhaps uncharitably) "surely you're not a serious engineer who works on serious problems if your biggest concern while coding is which character is used to group code?!" I want tools to help me think more clearly, ways to operate at higher levels of abstraction, better concurrency semantics—surface characteristics be damned. Sure, I have my preferences about orthography, but the tail doesn't wag the dog.

Look deeper! Learn what each language has to teach you! Then keep the parts that move our craft forward and use whatever glyphs you want. But don't reject the automobile because it doesn't have handlebars.

Moreover, the things that look familiar probably have the least to teach you.

I believe we have the ability to do so much better as an industry, but it's not going to happen if we reject the unfamiliar just for being so.

Re: The Janet Language

#185
post #174
post #159

Earlier quoted context omitted.

I certainly don't fault you for having that reaction, but I would encourage you to look deeper and not dismiss one of the most interesting families of programming languages on the basis that it looks weird. Far from atrophying your skills in other languages, many people say that learning Lisp makes them better programmers even when they're coding in other languages. Lisps don't arbitrarily look weird—there's a deep,…

That example is quite unfair. You could just write println(is_me ? "me" : "you") which has exactly the same amount of symbols.

I specifically called out the tertiary operator in my text so as to be fair, but tried to keep things simple in my example. Perhaps too simple.

Of course you can do that simple case with a tertiary operator but:

1. It's a construct that really has no reason to exist (I argue) as distinct from `if`.

2. It doesn't compose with statements.

This duality is primarily what I'm arguing against.

A better example would have been a case statement inside of the `println`:

  (println
   "Log in by"
   (case user-id
     0 "root"
     1 "local admin"
     (format "regular user (id: %d)" user-id)))
In C, you have to introduce a variable for no good reason (or do some non-idiomatic, ugly, nested tertiary operators that get uglier the more cases we have).

And even then, you can't just say

  user_name = switch { ... }
Because switch is an statement.

Re: The Janet Language

#186

I just can't let go of infix notation.

With macros, someone can write an infix sublanguage for you to use in those mathy bits of code. Probably better just to get used to prefix notation, though. Just pretend everything is a function call.

> Just pretend everything is a function call

D uses Universal Function Call Syntax, where:

    f(a)
    g(f(a))
can be written as:

    a.f
    a.f.g
It's a very popular feature.

Re: The Janet Language

#187

One thing that bothers me about languages that compose functions like this f(g(x)) is that when programming interactively f is typically an afterthought. So, you start out with g(x) and then need to go all the way back and add f . Similarly, when x turns out like it needs to be elaborated, and you either have to go all the way back, or edit the expression in place making it longer and inevitably facing problems with…

you're totally right that it's often easier to read in the order the functions are being applied. That's why just about every lisp/scheme family language has thread-first and thread-last macros -> and ->> so f(g(h(x))) could be written as: (-> x h g f) Janet, clojure and racket and probably others have them built in, emacs lisp has it in dash.el, common lisp has it in cl-arrows and other libraries It's really just ab…

Emacs Lisp actually has threading macros natively (seemingly since at least 2016), but they're (IMHO) obnoxiously named `thread-first` and `thread-last`.

Re: The Janet Language

#188
post #172

Oh hey! Nice to see this on the front page here. I love Janet -- I've been using it for about year and a half, and it's now my go-to scripting language when I need something more powerful than bash, or when I want to hack on goofy little side project (some examples in my profile). Parsing expression grammars (think, like, declarative parser combinators?) are a really great feature for ad-hoc text parsing -- and nicer…

Is there somewhere I can keep up to date with books progress?

I'll announce it on my RSS feed/newsletter/twitter once it's done, if you use any of those. I'd estimate that it'll be out by the end of March; I won't write any public updates until it's ready for people to read.

Re: The Janet Language

#189

Earlier quoted context omitted.

Almost anything but a list

Any examples to add, or you just want to leave it at pithy comment?

Sure, my thinking is that a cons cell can build singly linked lists and node-based binary trees. Some data structures are based only on those, but most involve an array of some kind. In scheme, for example, it's the combination of cons (i.e. lists and trees) and vector (i.e. arrays) that allows for arbitrary data structures. It's very constraining to have only the lists.

- array: not a singly-linked list.

- hash table: often an array of singly-linked lists, so not a list.

- red-black or AVL tree: can be built with cons cells.

- doubly-linked list: not a singly-linked list

- double-ended queue: array of double-ended queues, so not a list. Could also be implemented as a doubly-linked list.

Re: The Janet Language

#190

Earlier quoted context omitted.

With macros, someone can write an infix sublanguage for you to use in those mathy bits of code. Probably better just to get used to prefix notation, though. Just pretend everything is a function call.

> Just pretend everything is a function call D uses Universal Function Call Syntax, where: f(a) g(f(a)) can be written as: a.f a.f.g It's a very popular feature.

Scheme has a shorthand for (cons a b) that's just (a . b), and (cons a (cons b c)) as (a b . c)

Racket, a scheme-based language, extended the syntax so that any symbol appearing between two periods and not at the end of a list gets moved to the head of the list, so (a . b . c) becomes (b a c), which some people use so that (a . + . b) becomes (+ a b).

The D syntax you describe is what schemes call the "threading macro," or the thrush combinator in non-macro contexts.

Post reply on HN