Janet for Mortals

354 points
1/20/1970
a year ago
by ianthehenry

Comments


djha-skin

My question for why Janet was answered:

> My favorite feature of Janet, though, is something that sounds really dumb when I say it out loud: you can actually distribute Janet programs to other people. You can compile Janet programs into statically-linked native binaries and give them to people who have never even heard of Janet before. And they can run them without having to install any gems or set up any virtual environments or download any runtimes or anything else like that.

The space is ripe for a lisp that is easily distributable. Yes, common lisp can be statically compiled, but their binaries (at least with sbcl) can get pretty big [1], even with compression. Making a lisp specifically good at using to make CLI or desktop tools with good c ffi support is compelling.

1: https://blog.djha.skin/blog/50mb-for-hello-world/

a year ago

koito17

The binaries are big because it's shipping a preprended lisp kernel together with the entire programming language in a heap image. It's also largely dependent on the Common Lisp implementation. SBCL is very inline happy and consequently consumes more memory than other Lisp implementations. A fresh CCL image consumes at most 8 MB on my Mac.

If you want small binaries, then you'd want tree-shaking, not an entirely new language. LispWorks is already capable of producing small, graphical hello world examples. Even then, a hello world is a rather silly benchmark for binary size, especially since it totally ignores the fixed cost of a language runtime and no serious person is distributing a hello world.

a year ago

pnathan

- a helm 3 distro is 45M

- a terraform distro is 59M

- a kubectl distro is 44M

getting rust installed on a windows machine required not just a rust distro, but a visual c++ library set over 1G.

at a certain employer, the size of the teams golang tool was well over 100MB.

So - 50MB to start with a full Lisp image? yeah, sure, no worries.

a year ago

nerdponx

Plenty of Scheme implementations produce portable-ish binaries too.

a year ago

pnathan

I've never really schemed, only Lisp'd in a common sort of way.

I've heard that some scheme things will compile out to C even.

a year ago

nerdponx

Yep, Gambit not only compiles to C but also interoperates with it, much like Nim.

a year ago

rtpg

But you don’t need to give people Rust , just the binaries. The original dig is clearly targeted at Python/Ruby/JS

a year ago

joshxyz

you forgot my node_modules folder

a year ago

sebstefan

I used to do that in Lua

https://github.com/LuaDist/srlua

The Lua runtime is 340kB on Windows and there's plenty of projects including the one above (srlua is made by the Lua maintainers) to produce statically linked and dynamically linked binaries.

But it's Lua, so while I loved the language, you have to put up with the tiny list of standard features which can make it a grind.

a year ago

brabel

The project you linked to has been archived. Are you sure they are still maintaining it?

As someone who's playing with Lua to run an incredibly lightweight HTTP server[1] which requires just a few MB on disk and 1MB of RAM (while supporting stuff like JSON, HTTPS, Sqlite DB, Email, MQTT and a lot more), I would be curious what you think are the problems with Lua.

[1] http://barracudaserver.com/ba/doc/

a year ago

ianthehenry

I think Janet is an excellent choice for making redistributable CLI apps. Chapter 12 covers a bit of this, including the implementation of an extremely simple fzf-powered todo list: https://janet.guide/scripting/

a year ago

eimrine

But not if a support of Windows 7 in a CLI app is important.

a year ago

dylan604

in 2023, why would it be? we're talking creating something new in a newish language. we're not talking about supporting legacy code on a deprecated OS

a year ago

eimrine

1. Windows 7 share is 5% of all Windowses right now, that means that a number of Windows 7 machines is more than a number of all Linux ones. That's not an answer to question "why to support 7" but an important note.

2. "Janet runs on Windows" as claimed by their website. Why not change to "Janet runs on Windows 8+" or whatever version is also not supported. I have lost several hours while figuring up this issue. How much time of other dudes have to be spent before somebody will write down this clarification on the webpage? All the Windows history tells me that backward compatibility is the killer feature of Windows.

3. Windows 7 is the last good version of Windows. Also there is a lot of computer equipment which is stuck to Windows 7, for example laptops with ATI videocard only which does not support any modern Linux because of xorg version, x32 machines, machines which are not supposed to be exposed to Internets any more, also most laptops in second-hand has 7 by default and it still just works. I do not think Windows 7 deserves to be forgotten right now.

a year ago

ahtihn

> All the Windows history tells me that backward compatibility is the killer feature of Windows.

Backwards compatibility generally means you can use programs made for older versions of Windows on newer versions of Windows.

What you want is the opposite of that: run a new program on an old version of Windows. Expecting that of all programs would mean no new OS feature or API could ever be used.

Generally staying on an old OS means you accept that you don't get to use newer programs.

a year ago

vindarel

> common lisp can be statically compiled, but their binaries (at least with sbcl) can get pretty big [1], even with compression.

My SBCL binaries are ±28MB, with the complete Lisp runtime and debugger (cool, I can eval and load configuration files or connect to a remote app) and dozens of dependencies, including a web server.

a year ago

djha-skin

I could get it down to 10 with the `:compression` option on[1] for hello world. Perhaps this is the option you use? The compression didn't hurt the run time much as I recall. It's the reason why I'm still okay with common lisp for this use case.

1: http://www.sbcl.org/manual/#Function-sb_002dext-save_002dlis...

a year ago

vindarel

absolutely, I use SBCL compression (following this recipe: https://lispcookbook.github.io/cl-cookbook/scripting.html#bu... that boils down to save-lisp-and-die ultimately). Start-up times are still below the 50ms for me.

a year ago

schemescape

How big is an executable compiled from Janet using jpm?

I'm sure I just missed it, but I haven't been able to find an answer to that question yet.

Edit: Probably pretty tiny based on this [0], right?

> The entire language (core library, interpreter, compiler, assembler, PEG) is less than 1MB.

Edit again: Found an example [1]:

> And the size is quite reasonable for a non systems language: the Pong example using Raylib is about 2.4MB on Mac OS Catalina.

[0] https://janet-lang.org/

[1] https://github.com/phillvancejr/Cpp-Go-Zig-Odin

a year ago

ianthehenry

I just compiled a hello world and got 784k on aarch64 macOS with all the defaults.

a year ago

andrewflnr

Racket can supposedly compile standalone packages with the raco compile command (IIRC). Does anyone have experience with this?

a year ago

shakow

I do, it was extremely useful to quickly whip out a GUI doing some stuff and share it with colleagues under Windows/macOS/Linux.

Cons:

- 200MiB archives

Pros:

- I can develop a GUI doing some stuff on proprietary binary files, extracting & converting data, generating a handful of plots in a couple of days and have all my colleagues enjoy it without any issue.

a year ago

dunham

I haven't used it beyond just trying it out once or twice. But a "hello world" application in the Idris2 language compiles to a 17kb racket file (the default backend is chez, but it also does racket and javascript).

If I run `raco exe` on this, I get a 57MB file. On mac, it's only linking system libraries. (For Idris2 programs, there is an Idris support library that is dynamically loaded.)

I haven't tested transporting it to another system (my test was on an arm mac, so I don't have another system to test that on).

a year ago

butt____hugger

They aren't standalone executables, they need to be distributed along with the lib folder that includes the racket runtime.

a year ago

nsm

Sorry, I meant to respond to this but went to the parent https://news.ycombinator.com/item?id=35392704

a year ago

sebstefan

Surely the lib can be included statically no like Lua does no?

a year ago

nsm

Doesn't raco make followed by raco exe produce fully standalone (except libc) executables? I believe some platforms need an additional raco distribute step.

a year ago

andrewflnr

Oh, raco exe is probably what I was thinking of.

a year ago

sschwarzer

At least in some cases, you need the options --orig-exe (Posix) or --embed-dlls (Windows) to make the binary standalone. For me that worked for command line programs. The options are described at https://docs.racket-lang.org/raco/exe.html . You can use both options at the same time, regardless of running Posix or Windows.

a year ago

medo-bear

50mb for a hello world in common lisp is a bit misleading. its 50mbs for a hello world + an entire interactive common lisp runtime you can use to further extend the application. if you write 2x hello world it aint gonna be 100mb lol

on the other hand, i hear that commercial versions of common lisp can achieve better results. but seriously, is this such an issue for todays computers ? i have pdfs that are hundreds of mb

a year ago

zdragnar

Why would I want a 50mb hello world?

a year ago

thechao

Why do you want hello world, at all? Yes, the nearly-null program is 50MB; also, yes, a fairly nontrivial program is ... 60MB? The core for a computer algebra system is 100MB?

You're paying a higher initial capital cost for lower per-unit costs.

a year ago

thomascgalvin

Why would you want a hello world at all? That isn't a realistic distribution scenario.

a year ago

HelloNurse

A simple "Hello World" is a realistic test scenario, representative of a large class of plain command line tools and approximately reduced to pure overhead.

If you can distribute and run a trivial hello world program, you can expect to be able to distribute and run something like tail or uniq, and that it will be larger (more standard library portions linked) and slower (more actual work executed).

a year ago

[deleted]
a year ago

EggsAndOil

On the contrary, 50 milli bits is quite small for Hello World.

a year ago

iansinnott

I wonder if Jank [1] could be such a Lisp? I haven't played around with it, but I really like the idea and would love to see it get more traction.

[1]: https://jank-lang.org/

a year ago

miroljub

Unless jank rebrands itself as NativeClojure retaining 100% Clojure compatibility with a few more native related goodies, I don't see it offering more than Janet, which is also inspired by Clojure.

Given that they have similar goals, why not merge and join efforts? Would help in softening the rough edges and reducing the bus factor.

a year ago

cellularmitosis

Looks like the key difference is that jank is based on persistent data structures, while Janet embraces mutability.

a year ago

smegsicle

'jank' is a good name then- janky immutable structures sounds flexible and fast, while janky mutable structures sounds like a big mucky headache

a year ago

psychphysic

Maybe I'm being too simplistic but this should be a characteristic of the implementation and not the language?

Then again I don't know much about the technical details here (when do you or don't you need your own runtime). It seems baffling to me with all the cruft and bloat in a modern windows install do you still have to install so many microsoft runtimes.

a year ago

crabbone

I really struggle to think about a language that doesn't usually need a runtime. Some can produce binaries that don't need a runtime, but usually you need to jump through hoops to make that happen.

We just don't notice that typical C programs need libc and pthreads. Or that C++ programs on Windows require that cursed Microsoft Visual C++ Runime DLL which is always missing, but has few dozens of copies all over the system of the miserable Microsoft slave.

Go doesn't produce fully statically linked binaries by default. I used to make "from scratch" Go containers and, in general case, you need libc in them, unless you are willing to go through pain of statically linking with it.

Typical / practical Rust programs will also depend on libc and pthreads (but, sure, you can do w/o).

a year ago

weavie

The difficulty with a lot of dynamic languages is that it is very difficult to determine at compile time what parts of the runtime are not going to be invoked so you largely end up having to include the entire platform in the executable.

a year ago

JohnMakin

can't you compile C into statically linked binaries?

a year ago

vram22

Sure you can. I'm not a language expert, but IIRC, static linking was the only option at first for C, Pascal, FORTRAN, etc., earlier. Dynamic linking came later.

a year ago

tom_

Yes. This language looks like it might be a bit more convenient to use in some respects, though.

a year ago

tpoacher

> you can actually distribute Janet programs to other people. You can compile Janet programs into statically-linked native binaries and give them to people who have never even heard of Janet before

In theory you "can" do that with python too.

"Can" is a very different kettle of fish from "most people are inclined to".

a year ago

djha-skin

Nah, you really can't.

Before you start screaming "cxFreeze/pyOxidizer/pyInstaller", NO. I have gone this route. It is incredibly painful. Python was built with the thought in mind that it would be interpreted. It wasn't engineered well for compilation. A significant amount of effort, often a significant percentage of the total effort, is spent shoehorning things into this as an escape hatch because requirements have changed. This is not the route to choose from the start. Same goes for Clojure and `native-image`. I'm glad the native image project exists, and we all hail babashka as a success story, but it doesn't mean its author didn't have to spend a ton of time with native-image. If you go this route, prepare to spend half your time with the build tool itself, and be prepared for "oh the language technically works with this, but not if I use library x" type disappointments right and left.

The best, most painless route is to go with a language which has thought about the end result of the build pipeline beforehand. Rust and Go are gold standard for this. If I want a Python that is statically compiled, I reach for Go.

So to hear that the language made a bunch of tiny little design decisions up and down the line with the idea of making static executables from the start is, from this DevOps engineer, incredibly compelling.

a year ago

lenkite

Sorry, but you truly need to re-educate yourself on how excellent native compilation supporting infrastructure like GraalVM is. So many HN folks have some decade-old view of old programming language and tools without trying anything out for themselves. And get stuck in a "bias bubble".

It takes ~2minutes TOTAL to download, install and compile Graal VM against Java sources to produce a ~11MB debug build native binary. Utterly painless and even measured. You can reduce that considerably further to ~4MB by seeing what modules contribute to the size using the Graal VM dashboard https://www.graalvm.org/dashboard/ and choosing to omit them with a flag.

Frankly, I found it easier to work with than your Rust+Go standard as I can easily see exactly which modules contribute to binary bloat-up and choose alternatives.

There are also excellent, first-class frameworks built from the ground up for Java native compilation like https://quarkus.io/.

a year ago

djha-skin

I'm sure it's easier with Java, and I apologize for not being clearer. I have recent, unpleasant experience with Clojure, not java. That said, I would still be (pleasantly!) surprised to hear of someone using a sqlite java library and having it work without a hitch on native-image.

a year ago

lenkite

Sadly, another baseless assumption. I just downloaded sqlite java driver from https://github.com/xerial/sqlite-jdbc/. And compiled their sample program on the home page (creates db with table and some rows) to native code. I did all this within ~2min after reading your response.

Its very, very hip nowadays to worship Rust/Go and bash Java and gain HN karma from the younger generation while doing so, but at-least do it on real facts and not assumptions.

    javac Sample.java && native-image -cp .:sqlite-jdbc-3.41.2.1.jar Sample 
    ./sample                                                                                                       
    name = leo
    id = 1
    name = yui
    id = 2    
    ls -al sample.db                                                                                               
    -rw-r--r--  1 OMIT  OMIT  8192 Apr  1 22:22 sample.db
a year ago

_a_a_a_

My Python isn't very good so I'm not familiar with your cxFreeze/pyOxidizer/pyInstaller list, but couldn't you just develop your python using one of these tools from the start?

a year ago

crabbone

Bare Python is mostly useless. People use Python because of the libraries. The kinds of projects that are developed in Python all, save the most trivial ones, rely on stuff that's not written in Python.

For instance, if you do ML, then you use NumPy, Scikit-Learn etc. It's all C / C++ code, which you will have to link with somehow. And even if you figure out how to link with it, your program will still suck because of the unnecessary (as I call it) PyObject layer, i.e. the Python interpreter interface that is used for communicating between Python libraries. Eg. say you wanted to pass a pointer from one library to another. If you were writing in C -- no big deal, just have some externally visible function in one library and call it in another, and you are done. But if you want to connect two Python libraries, at best, you'll have to use a special struct PyCapsule, with two dozens or so of fields, which is allocated by Python's allocator and also needs to be deallocated... The overhead will be tremendous.

Similarly, if you do Web development, you need some HTTP server that can run fast. I haven't touched this part of Python in a long time, but the last thing I came to use was Tornado, which was a C library with Python bindings.

When it comes to infra, there are plenty of tools that are also written in C, various database drivers, Kafka client, encryption library... and so on.

---

Bottom line, even if you defeat the system and manage to make it all compile together... it won't work well, not as well as it could have if only you could ditch Python entirely from this equation. And if you could, then... well... you'd be just writing in C...

a year ago

ActorNightly

Reading through your comment history, it seems like you are on a personal crusade against Python, but your arguments boil down to this:

"Python is a shit language because it doesn't do/have [insert a niche thing that you think a language should do]"

Which is failing to grasp the role Python plays. You can make this sort of argument against any language, and generally you would be correct in the fact that languages can be improved.

But the fact remains that Python is widely used, and no, its not because people are dumber than you and don't know better, its because they simply dgaf about any of the niche cases you talk about.

For example, nobody is going to look at Numpy and realize its C, and ask the question of "Hmm, I wonder why Im using Python in the first place if its really just C under the hood". Not to mention that the practice of patching Python libraries through C like you describe pretty much never happens. Not to mention that core ML isn't even the standard C, its open cl or CUDA C which are specialized, and how you get to defining those kernels is largely irrelevant for functional sake, but largely relevant in how efficient and simple it is, which is why Python is used.

For all your other issues across comments (like venv, pip dependency), you seem to assume that when someone runs into the issue, it somehow causes everything to break and things to fail. None of what you describe really plays out in reality on a large scale. Things work because people are smart enough to realize what they are doing. It could be that you personally have issues with your company, which is the source of your frustration, but I can assure you that is not the case across all of industry. Google, despite its many issues, has built plenty of good things using Python, and defaulting to C/C++/Go when they need to.

Google, despite its many issues, has built plenty of good things using Python, and defaulting to C/C++/Go when they need to. When you start building better things than Google in other languages and prove that the thing is better because of the language choice, then you will have a point.

In your reply to my other comment, you said

"But, even, imagine that in your fairy-tale world Python is somehow so super-important and successful? Didn't I already explain how this is possible while still being a garbage language?"

This is the equivalent of you just standing in the middle of the busy street with a sign that says "everyone is on a path to hell with your choices in life, you must repent and follow Jesus". You are entitled to your opinion, but I hope you realize that you aren't making any real points.

a year ago

_a_a_a_

That's a very strange post that doesn't sound like it's coming from a professional programmer. "Do everything in C" really misses the value of using a glue language. Furthermore you overlook the cost of python as glue, which can be relatively quite low under the right circumstances. Everything is a trade-off.

a year ago

crabbone

What glue? Did you even read what you replied to?

a year ago

_a_a_a_

Respectively, Python, and Yes I did.

https://html.duckduckgo.com/html?q=glue%20language

a year ago

crabbone

Well, reading may mean different things... When I use this word, I mean that comprehension is involved.

a year ago

_a_a_a_

So I failed your comprehension test; explain then what your point was.

a year ago

cjohnson318

For a script with a few dependencies, pyInstaller isn't too bad. I love Python, but it's an interpreted language first and foremost. Distributing Python code is never easy, no matter what you throw at it. Things that are supposed to "just work" almost never work when you need them to on someone else's machine.

a year ago

progre

Sure you can, but last I tried (admitedly a good long while ago) the exe included everything except that fucking Visual Studio DLL that everything requires.

a year ago

actuallyalys

Native image has been getting better, with the Graal project recently making it much easier to get builds working on Windows. So it’s getting to be quite painless, so that I think it’s already worth it for people already familiar with Clojure.

But if you’re looking specifically to write small tools distributed as native binaries, Janet sounds like a much better choice.

a year ago

djha-skin

I will be most interested when this gets easier, in particular if it works with sqlite and the unzip libraries. Those libraries are the major snags. I could not get it running on windows (the repo in question[1]).

1: https://github.com/djhaskin987/zic

a year ago

cjohnson318

Go for the win. It's not too hard to pick up, it builds fast, it runs fast, and cross-compilation is easy.

a year ago

leoc

I think it's fair to say that that sentence almost screams "this is my adoption strategy". And fair enough, of course.

a year ago

ianthehenry

I am not the author of the Janet programming language, just a user who likes it enough to write a book about it. That is my real favorite feature, not a strategy of any kind :)

a year ago

muyuu

chicken scheme comes to mind

anyone around knows how does it compare to Chicken?

a year ago

zem

chicken scheme can do this too, for what it's worth

a year ago

freilanzer

Who cares about these sizes though? I know I don't and nobody I know would either. 100Mb are downloaded in roughly 6 seconds with my connection at home.

a year ago

Malcx

You forgot the /s right? Most of the world doesn't have that kind of connection.

a year ago

freilanzer

I don't see how this is a huge problem. You don't need to download the executable once per minute.

a year ago

eru

Yes, some of us have faster internet. (Assuming freilanzer talked about megabits, not megabytes.)

a year ago

tmtvl

Exactly, and loading stuff into memory is free, everyone has an SSD, and RAM and L1 cache are exactly as fast as each other \s.

But on a more serious note, I actually do care because I have around 4,500 packages installed on my system. If all of those were 100MB in size I'd have a problem.

a year ago

krinkatt

Searching *.exe in Everyting and select all -> 12 779 objects.

With 50MB a piece that would be ~0.5TB. That is 50% of my system SSD.

a year ago

shaicoleman

There are no code examples on the home page, so here's one:

    (defn bottles [n]
      (match n 
        0 "No more bottles" 
        1 "1 bottle" 
        _ (string n " bottles")))
    
    (loop [i :down [99 0]]
      (print 
        (bottles i) " of beer on the wall\n" 
        (bottles i) " of beer\nTake one down, pass it around\n" 
        (bottles (- i 1)) " of beer on the wall\n\n"))
https://rosettacode.org/wiki/99_bottles_of_beer#Janet
a year ago

cmiles74

I had some time a while back to work on a project of my own, I coded up a bencode parser in Janet. It was a fun project, I liked Janet alot. :-)

https://github.com/cmiles74/bencode/blob/master/src/bencode....

a year ago

[deleted]
a year ago

mdgrech23

bottles 99 of beer on the wall? That's not the lyrics or am I just not understanding janet?

a year ago

bombastry

The prefix notation may be throwing you off or perhaps you have mistaken the function `bottles` for the string "bottles".

The code `(bottles i)` in the loop is calling the function `bottles` (defined at the top) with the argument `i`. The value of `(bottles 99)` is `(string 99 " bottles")` which evaluates to "99 bottles", as expected.

a year ago

colonCapitalDee

You aren't understanding Janet. (bottles i) invokes the bottles function with parameter i, so the lyric is "99 bottles of beer on the wall".

a year ago

nerdponx

One obvious point I'm missing here, and that I've been missing from Janet discussion in general: why Janet and not Scheme?

Gauche for example implements the latest (and IMO greatest) R7RS, its standard library is huge and "batteries-included" including a wide array of RFCs to the point of rivaling Python, and has a package manager in the form of Akku. Chicken has a similar story. Racket is arguably more useful "out of the box", but its community seems so heavily focused on using it for PL research that it's harder to justify using it for day-to-day programming. And there's Clojure as well, which I know comparatively less about, but is well-loved by its users.

Heck, even Common Lisp has a lot going for it, but the Standard and the conventional Lisp dev tools are kind of chaotic and idiosyncratic enough that it's understandable if people don't want to use it.

To be clear, Janet seems like a great little language. But as someone with limited time and energy who is interested in using it, I want to know why I should spend the time learning it, compared to Scheme

a year ago

giraffe_lady

Janet has close integration with C going both ways. It has built in C ffi and you can easily build and distribute a janet binary that uses C libraries.

It's also easily embeddable in C programs the same way lua is, making it possible to use it as a config, extension, or scripting language in a larger program.

Aside from that having used it a fair bit I think it's got a very "practical" orientation. It provides immutable structures, but doesn't enforce immutability semantics the way clojure does. It has a good concurrency system but is cleanly single-threaded and performant by default. And imo the standard lib is a really good balance, neither forcing you to build EVERYTHING yourself (lua) or having the whole last 50 years of CS research in it (racket).

a year ago

crabbone

> is cleanly single-threaded

And here I immediately lost my interest. Anything that cannot do real concurrency is a toy in my book. There's no excuse for a language developed for practical computers in 21'st century to not be able to utilize concurrency which is practically built into every existing computer.

a year ago

jlokier

You misread the sentence. Janet supports full parallel execution on multiple CPU cores using native operating system threads, while using clean and fast single-threaded data structures by default on each thread.

a year ago

tmtvl

Then it's a good thing those words were preceded by:

> It has a good concurrency system

a year ago

crabbone

It has none. When code isn't executed concurrently, that's not concurrency. There's idiotic fashion to call unrelated things "concurrency", but it's the same as calling various soy drinks "milk". It just adds confusion for no reason. This language has zero concurrency. It has some mechanism to randomly / unpredictably execute bits of different functions in succession: this is worthless, but has nothing to do with concurrency.

a year ago

shadytrees

I think you're using concurrency in a non-traditional sense https://stackoverflow.com/questions/1050222/what-is-the-diff... and I also think you're being a little bit uncharitable

a year ago

crabbone

Really? You are going to quote StackOverflow for an expert opinion? Why should anyone care about what that site users have to say? "Concurrent" means that something happens at the same time. It's that easy. The use of the word you refer to is a marketing trick used to bait you and switch the products before you pay. It's used by people who want to justify the existence of a worthless tool by pretending it has something to do with the one you really want. Very similar to "vegan cheese", which is really not a cheese in any way, but it's sold to you labeled as "cheese" because you wanted cheese, not ground cashew nuts.

a year ago

c-cube

You're wrong on all points :-)

Vegan cheese is not named this way to trick you, it's for vegans who want something functionally similar to cheese. Same goes for oat milk and the likes, they're used _like_ milk, in coffee, etc.

Concurrency can mean doing several things that are interleaved, even if they're not literally running on multiple cores. Otherwise, you literally couldn't have concurrent network connections because the NIC only sends one packet at a time. Similarly, fibers, promises, etc. are valid implementations of concurrency as they're running different, unrelated strands of logic in an interleaved fashion.

a year ago

crabbone

I'm not a vegan, so the vegan "cheese" isn't named like this to trick me. It's named like this to trick vegans.

Apart from that, there are organizations that act on behalf and to protect consumers' rights. Some of that goes against false advertisement. This is why, for example, products that aren't meant for children or puppies aren't allowed to have children or puppies on the packaging, or the reason why it would be illegal for different products to have packaging that inflates the perceived amount of good that you buy by essentially, selling you air. This is also the reason that in many countries vegan "cheese" is not allowed to be called "cheese" in advertisements on on the packaging. Same goes for vegan "milk" and similar products.

It doesn't have to be about vegan products, it was just a convenient example. In some countries "crab" sticks are only allowed to be called that if they actually contain some crustacean meat. Or products aren't allowed to be called "juice" if they have less than a certain % of actual juice in them and so on.

"Concurrency" in languages like Janet is exactly the same thing. It is false advertisement. You pay with the lost ability to debug and to predict code execution path for nothing, whereas that would've been the price you might have wanted to pay for executing code concurrently. That's swindling. Most likely unintentional in the case of the people working on Janet, but for you, as a user, it makes little difference.

a year ago

giraffe_lady

Maybe you should reread that sentence bc I don't think it says what you think it says.

a year ago

crabbone

[flagged]

a year ago

ianthehenry

I don't think Janet and Scheme have very much in common. If you're looking for a huge, batteries-included language, you will not have a good time with Janet :)

Janet is much closer to Lua, in scope and applications, than it is to any Scheme or Common Lisp or Clojure implementations.

a year ago

pull_my_finger

Janet has a lot in common with Lua: tables, coroutines, easy embedding, lots of API similarities. Compared to a language like Lua, Janet is bursting with "batteries". Almost to a Ruby level where whenever you think to do something, you check the docs and find yourself saying "of course there's a function for that". I have to disagree completely with your assessment.

a year ago

headhasthoughts

r5rs is significantly smaller than Janet.

a year ago

Koshkin

This was the last good Scheme.

a year ago

medo-bear

it seems to me that gebril scheme fits janet's use cases

https://cons.io/

a year ago

dri_ft

Scheme feels really verbose to me. I get that it's 'minimal' and 'elegant' and everything, but then why are all the identifiers so long? I feel like I have to do a lot of typing to get anything done. Maybe it's better if you're using emacs and have good lispy autocomplete, I don't know. But broadly, it makes me feel like the people who developed scheme were working from a very specific definition of 'elegant', and it doesn't align with mine. Janet feels better for that.

a year ago

imwithstoopid

Janet users are not encumbered with the historical cruft of scheme like hiding libraries behind unmenorable srfi numbers, or the ancient an un-portable oop implementations etc etc

a year ago

agumonkey

This should be studied a bit. At what point a partial reboot benefits the community/language before.

a year ago

munificent

The writing style of this is so good I accidentally got halfway through the first chapter despite not really needing a Lisp or scripting language in my life. I love it.

a year ago

vanderZwan

For those who don't know, Bob "munificent" Nystrom wrote "Game Programming Patterns" and "Crafting Interpreters", so that's quite a compliment

[0] http://gameprogrammingpatterns.com/

[1] http://craftinginterpreters.com/

a year ago

giraffe_lady

Oh cool I love janet, I've been using it everywhere I can recently. There definitely weren't many good resources on it last year, though it wasn't too hard to learn despite that.

This language also completely converted me to PEGs for entire classes of problems, and I'm now often annoyed in other languages that don't have them. Libraries exist, but having it built in is so nice, and the s-exp syntax works much much better for them than almost anything else you could come up with.

A moderate issue I had was finding functions for what I wanted, since the docs were set up more tutorial style, then there was just a huge list of every function. Spent a lot of time skimming through that guessing what I could be looking for.

Another thing I ran into is the concurrency/fiber system still feels like a work in progress. There are several different ways to handle concurrency depending on how you want to combine the abstractions, and some parts of the (otherwise excellent) standard lib don't work well with it. It also combines nastily with a lot of C libraries, which is rough in a language that seems to expect you to use C bindings often. Understandable limitation and there's probably not a good clean solution.

Anyway this book looks great, I really hope it brings more people into janet. It's an excellent language for a lot of applications where people reach for the imo extremely overrated lua.

a year ago

sph

Thanks, I was looking forward to this, after you sent me a draft months ago. I completely forgot about Janet as I've been very busy lately, but this is a good opportunity to get back into it.

--

See also, from the same author: https://bauble.studio/ — interactive 3d sandbox in Janet

Previously discussed at: https://news.ycombinator.com/item?id=32738654

a year ago

harryvederci

The author is super helpful in the Janet community, I'm sure this is absolute gold. I encourage Ian to put a donate button on the website.

What I like about Janet is that anything seems possible with it, and that code from others is very approachable and understandable to me. In no other language do I ever find myself hacking on someone else's library to add a feature that I need. In Janet, it always seems easy.

Some stuff I created that I wouldn't quickly find myself doing in other languages:

- a wrapper around my web app that runs it like a CGI script (for ultra-cheap deploying on shared web hosts)

- a logging function (macro) that logs the input (both the unevaluated way it was called and what it evaluated to) + line number of the code that called it

- a framework for creating web apps (not public yet, but used in production on my website)

- (with Ian's help) a macro that I can use to create functions that require explicitly specified parameters

a year ago

throwaquestion5

The site has a Janet repl (downloads pressing Esc) with autocomplete. That's enough, now I have to give the book a spin.

The fact the author points out, being able to distribute the program without requirements, is a big plus. Multiple times I have been doing some bash script that later I can't share with my non-techy friends until I translate it in some google sheets or something they can use. If Janet can let me do simple script stuff and let me share it just sending the binary as a file on some chat app, then I'm more than interested

a year ago

thyrsus

I think I read that the image you distribute expects to use a C compiler in it's execution, and not every computer has a C compiler - or did I misunderstand? The run-in-browser blob cannot make that assumption, but perhaps that's a special case?

a year ago

Graziano_M

I'm a fan of janet. I did 2021 Advent of Code using it. I am not a fan of Lua, since it's ugly and too barebones (no string split?), but I understand its ubiquity due to its small size and ease of embedding in programs. I wish/hope for Janet to fill this niche.

a year ago

catketch

Take a look at fennel. Same author as Janet, but it transpiles to Lua. https://fennel-lang.org/

a year ago

Graziano_M

Yeah I actually opt to use fennel over Lua at every chance, including my Neovim config.

a year ago

bongobingo1

Fennels cool. I use it a lot, but it inherits all the ugly bits of lua still.

a year ago

keb_

Surprised to hear someone call Lua ugly, as I find it pretty and simple. The barebones-ness is part of the appeal for me as well.

a year ago

jimmahoney

I used janet for Advent of Code 2021 too. My first exploration of the language. Small world. I found janet fun but quirky. My work is at https://github.com/jimmahoney/advent-of-code/tree/master/202... .

a year ago

kelipso

Is cutesy language like this as offputting for anyone else? I couldn't get past the second paragraph due to the overly cutesy ridiculously simplified language. Who is the audience here?

a year ago

munificent

No, I love it.

I don't need sesquipedalian nomenclature in order to respect the content of a written work.

a year ago

vamega

I'm reading your book, and have previously read Ian's adventures on Nix.

I love the writing style in both of them! It may not be for everyone, but I can appreciate works that use language to make topics less intimidating.

Thanks to both you and Ian for your writings.

a year ago

cfiggers

I really like the writing style. I wouldn't describe it as "cutesy" at all, just informal.

a year ago

replwoacause

Nope, I like the writing style. It's approachable and enjoyable to me.

a year ago

jamesgill

I'm not in the audience for Janet, but I really appreciate efforts like this--to write about software in a creative and interesting way. I wish there were more.

a year ago

_benj

I’m quite excited about this!

Janet looks like a nice small, embeddable, fun language with a lively community!

The documentation and site felt like a close-knit community of insiders, which I wanted to become one of them :) hopefully this book shows the path!

a year ago

sgentle

Fun Janet feature that I don't see in many languages: you can pause a fiber (coroutine), serialise it, deserialise it somewhere else and resume it again.

A bunch of caveats to using it in practise, but it's still a little bit magical.

a year ago

whydoineedthis

I wish Ian Henry (the author) wrote all of my technical books. He is both whimsical, but also to the point.

I don't think i'm the biggest fan of Janet, but I really appreciate his writing and may just read the whole book anyways.

a year ago

galaxyLogic

This would seem like a good tool for creating small binaries which are meant to be combined by shell-pipelines later (?)

a year ago

progre

> 4. Pegular expressions

Good one. PEGs feels like having a parsing superpower compared to regexes.

a year ago

billfruit

How does this compare with Carp, which is often featured here.

a year ago

ianthehenry

The only thing they have in common are parentheses. Carp is a statically typed language that compiles to native code without a GC. Janet is a dynamically-typed language that compiles to bytecode and runs in a virtual machine with a GC. Janet’s closest relative is probably Lua, despite appearances.

a year ago

[deleted]
a year ago

eimrine

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp [1] . Maybe Janet is a human version of C, and that half of Lisp which is implemented here is the part of Lisp which is relatively easy to learn.

[1] Greenspoon's tenth rule

a year ago

Cyphase

I was about to comment on the "Chapter Fibe" typo, but I decided to check the chapter contents first. So in case anyone else is thinking about doing the same thing, it's intentional.

a year ago

thih9

> this book contains a repl, and you can summon it whenever you’d like by pressing the escape key on your keyboard.

Is there an alternative shortcut for people without an esc key?

I’m on iOS and my keyboard doesn’t have one.

a year ago

ianthehenry

You can click the REPL icon in the bottom left corner, but the experience is pretty bad on mobile.

a year ago

bmacho

Anyone knows how to run multiline programs in the REPL? Nothing works for me (enter, alt/shift/ctrl+enter, etc) in edge and in firefox.

a year ago

ianthehenry

Oh hey! Ha. I forgot to implement a way to do that. I just added it -- ctrl-enter or cmd-enter, depending on your OS, should work now.

a year ago

Uehreka

So the word LISP does not appear in the entire introduction. If you’re introducing a language thats a LISP, that’s really the kind of thing you’ve got to state up front.

You can define the term for those unfamiliar, and you don’t have to dwell on it, but people who are turned off by LISPs will feel a little swindled if they get 3 book-pages in before finding out. And people who specifically like LISPs might pass this over without realizing what it is and miss out.

a year ago

wodenokoto

Chapter 1 deals with your frustration:

> And now you’re just wondering when I’m going to use the L-word. You want me to use it so you can go write a long screed about how Janet isn’t a real one. But I’m not going to give you the satisfaction. I’m not going to use that word until Chapter Fourteen.

a year ago

philsnow

also

> Note that Janet’s `nil` is not the empty list. If you don’t understand why I’m calling that out here, you can safely ignore this paragraph.

beautiful, succinct, and not a jab at lisp-y languages

a year ago

weatherlight

this guy is a hero, i love it.

a year ago

giraffe_lady

If you call it a lisp you summon the lisp lawyer demons who will litigate your namespace & symbol semantics and start a big beef among themselves about what a lisp is and what makes lisp lisp and how much this is lisp and whether lisp even exists it's just a whole huge headache.

It uses parens and prefix notation. Not every language that uses parens and prefix notation is a lisp, I guess, maybe, I don't care. But not wanting to have that argument is an excellent reason to never make this assertion about a language imo.

a year ago

YuukiRey

So someone might be 3 pages in and really like what they're seeing but upon hearing the word LISP they turn around and decide they suddenly dislike it?

Considering that people can't even really decide on what constitutes LISP (Is Clojure a LISP?) I don't think there's any merit in this kind of resource to mention a term that's more likely to give people a false impression of what this really is or isn't.

a year ago

superdisk

He pokes fun at this type of comment in chapter 1.

a year ago

fallat

I really argue the opposite: it's really something you dont. A ton of people see LISP and get scared away.

a year ago

tgv

The first (defun will take care of it if you don't. If they stay, and can stomach ))))), I doubt they'd be scared off by mentioning LISP. Hell, you can even mention it after the first examples.

a year ago

superb-owl

Here I was hoping for an introduction to the work of Pierre Janet.

a year ago

BillinghamJ

I thought it might be about this JANET: https://en.wikipedia.org/wiki/JANET

a year ago

mentos

Is the ‘for mortals’ thing a Steve Jobs-ism?

a year ago

ianthehenry

The Janet language is named after a fictional immortal being from the television show The Good Place, who exists to help mortals in the afterlife -- that was the inspiration for the title.

a year ago

cnasc

I think a reference to Q For Mortals https://code.kx.com/q4m3/

a year ago

sph

Given that it is a Lisp, it should be "for mortals seeking divine beauty and purity".

a year ago

Koshkin

It's a LISP

a year ago

kunley

It's alive^Wa lisp!!;)

a year ago

cpufry

this is neat and all, idk why i feel so exhausted every time i see a new language these days

a year ago

afry1

It's the "sadness of mortal men" as Tolkien put it. So many awesome languages in this world, so little time to learn and use them.

a year ago

nerdponx

If you're anything like me, it's because you're getting older and have increasingly limited free time and energy that you can no longer dedicate to learning new programming languages.

a year ago

weatherlight

Because learning new things is hard and hard things tire us out. we should endeavor to learn new things everyday.

a year ago

smegsicle

some people have reported aspirin providing relief from long covid

a year ago

replwoacause

huh?

a year ago

smegsicle

a reference to 'long covid' causing exhaustion, and aspirin breaking up the blood clots thought responsible- you can tell it's a joke by the dim color of the text

a year ago

[deleted]
a year ago

oleganza

As a wise programmer once said: "Lisps are created by those who are lazy to write proper parsers"

Homoiconicity does not mean your syntax should be backwards. Look at Io language: it is basically a Lisp, but it has parens in the familiar places.

Same with Forth: it is a small and powerful language, but it's good for implementing low-level stuff. You will quickly run into desire to have normal(language(with, familiar, syntax)) for writing non-trivial programs.

a year ago

kazinator

The programmer may have been wise, but their remark doesn't testify to that.

a year ago

stefncb

How would you write the let macro in Io syntax? I can't think of a good way.

Lisp is just less familiar, not necessarily wrong.

a year ago

tmtvl

Allow me to disagree, I personally am very fond of the regularity and structure of plain old S-expressions. They suit the way my brain works. If I weren't as fond of them as I am I would still be using Raku, which is the most pleasant non S-expression based language I've ever used.

a year ago

[deleted]
a year ago

weatherlight

syntax < semantics

a year ago