Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I love Lisp (particularly Scheme), and heard that Janet was strongly inspired by Lisp and is "really Lisp underneath", but is really fast and strong at math, so I thought I'd give it a try, and after learning it I started wondering to myself, "why am I not simply using Lisp?"

Though arguably lispy, Janet just wasn't lispy enough for me. It was missing the simple, elegant sexp syntax I dearly loved, and I started to wonder what huge win I was getting from using it instead of just using Lisp or Scheme? Having not found a good answer, I did just that.

That was the last time I bothered trying to learn a "Lisp-like" language that wasn't actually a Lisp, and decided to just stick to Lisp/Scheme. They do everything I need, are good at math, and are plenty fast enough for me.



>It was missing the simple, elegant sexp syntax I dearly love

In what sense does Janet not have sexp syntax? Seems plenty sexpy to me. Purists seem to say it's not a lisp because its underlying data structure is not (cons-based) lists as in classical lisp, but I don't see what syntactic difference there is.


Op was understandably confusing Janet with Julia


Uhm, sorry for asking, but are you sure you're not mistaking Janet and Julia?


Oops.. I think you're right.. It was Julia, not Janet... now I feel like an idiot, and apologize for my uncalled-for, unfair, and undeserved mischaracterization of Janet, a language I never tried.

I wish I could take it back, but HN won't let me delete my post. I apologize. Mea culpa.


You’re confusing your exes, it’s understandable. Now give Janet a fair chance if you’re single


I think its a pretty nice language.

Those extra bits of syntax that makes it "not a lisp" are mostly around defining "not list" kind if data structures. I find it practical.


Lisp usually has a lot of non-list data structures like arrays. records, strings, classes/objects, hashtables, ... For some data structures there is built-in syntax and with an extensible reader (the extensible parser for s-expressions) the user can add additional syntax. Janet uses a non-extensible parser for the data syntax.

What Janet makes a 'not really a Lisp' is that "LISP" stands for "List Processor". Janet isn't exactly that, since it is not using linked lists as a core data structure - unlike Lisp where its List Processing features are built on top of linked lists made of cons cells.

(1 2 3) is called a "tuple" in Janet and represents something like an immutable array.


An array is just a different way to implement a list data structure.


Lisp especially is built upon linked lists, which have different costs for (more or less) primitive operations (add to the front, get the front item, get a rest list, get a random element, add to the end, ...) compare to a primitive vector. There are also other features not easily replicated by vectors.

  CL-USER 40 > (rest '(1 2 3))
  (2 3)
Above REST operation does not allocate any memory.

  CL-USER 41 > (subseq '#(1 2 3) 1)
  #(2 3)
Above SUBSEQ returns a new vector. Alternatively it would need a more clever implementation underneath.

OTOH getting a random element has a different complexity in a linked list vs. a vector.


What data structure isn't just a list with extra steps?


An array in C is a list with fewer steps. Just a continguous chunk of memory of sizeof type * length.

You could fill that with linked list nodes, but it would be pointless.


…anything that requires hashing as a fundamental part of the guarantee. Which happens to be quite a lot of the structures most of us use every day. Sets, maps, etc.


Sets and maps do not required hashing. Specifically std::map and std::set in the C++ standard library are based on ordered trees.


They’re often called “hash sets” or “hash maps” in other languages - they are called this for a reason, and certainly not because they could be implemented as a list.

std::map is not a good example anyway, you want to consider std::unordered_map for a more appropriate comparison. C++ is weird that way. (What C++ calls a map is not what most languages call a map. std::map doesn’t even satisfy O(1). You’d be surprised how many working C++ developers don’t even realize the unnecessary performance cost they take when they decide to use std::map, because it’s not a proper hash map. )

But this thread is not about the finer differences in implementation of maps but rather whether or not they are basically just lists. They are not.


Agree broadly that this thread has gotten too long off what was basically a joke, but!

Please measure before you make changes to your maps for perf reasons. Yeah this forum all knows their big-O, but B-tree maps like std::map often perform better than hash maps on real-world architectures.


You said "requires" hashing. Sets and Maps do not require hashing. Through it is correct to observe the unfortunate naming convention in the c++ std lib.

std::set and std::map should be std::ordered_set and std::ordered_map sts::unordered_set and std::unordered_map should be std::hash_set and std::hash_map

If this were so then it might make the incorrect usage of these two options less prevalent. But they are both map and set structures just each version has other guarantees that in some scenarios may be more or less useful.


You interpreted my reply as “all sets and maps require hashing“ instead of “sets and maps are examples of data structures that can require hashing”… which they are.

Imagine someone says, every fruit in the world is sour, and someone answers, no there are plenty of fruits that are sweet, such as apples, and then an entire thread gets launched in an irrelevant direction pointing out that actually some apples are sour, which has no bearing on the original point.


> But they are both map and set structures just each version has other guarantees that in some scenarios may be more or less useful.

And similarly, linked lists and arrays are just different "versions” of the same data structure: a list.


Let's simplify it even more - everything is just ones and zeroes.


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.


So what about streams? Functions? Closures? Call/cc structures?

I understand your point if you are speaking in literal terms about just simple cons cells, but in practical Lisp/Scheme code, you don’t really rely on just the basics to do things.

I think there’s a hyperfocus sometimes on the simplicity of the core of lisp, the apply/eval balance, but it’s quite possible and often easy and convenient to perform normal programming tasks with these languages as well.


> I understand your point if you are speaking in literal terms about just simple cons cells, but in practical Lisp/Scheme code, you don’t really rely on just the basics to do things.

Agreed.

> So what about streams? Functions? Closures? Call/cc structures?

Those are interesting examples. They are all data structures in a sense (especially streams and closures), but to me they are more like functions than data (yes, yes, functions are values, blah, blah). Call/cc is a reification of execution control; thinking of it in terms of data stretches my brain.


If by "list" you mean "linked list", then those are never used in practice. There is no place for this data structure in a modern CS toolbox.


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.


The people behind the Elixir programming language certainly disagree.


Maybe that's why Elixir never gained real traction.


Op was thinking of Julia


The list of features available out if the box is pretty impressive, especially if you are scripting something concurrent. I would tolerate the syntax quirks in exchange for that.

Or maybe your particular Scheme has all of that out of the box, too. Which one do you normally use, if you don't mind?


Op was thinking of Julia




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

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

Search: