[HN Gopher] The Janet Language
       ___________________________________________________________________
        
       The Janet Language
        
       Author : xrd
       Score  : 278 points
       Date   : 2023-02-18 02:42 UTC (20 hours ago)
        
 (HTM) web link (janet-lang.org)
 (TXT) w3m dump (janet-lang.org)
        
       | kensai wrote:
       | Sounds a lot like the space of Lua. How do they compare?
        
         | ianthehenry wrote:
         | They're similar! The author of Janet previously wrote
         | https://fennel-lang.org/, a compile-to-Lua language.
         | 
         | Janet has more traditional scoping rules than Lua. Tables and
         | arrays are separate types in Janet, and arrays are 0-indexed.
         | Biggest runtime difference is probably that Janet has value
         | types.
         | 
         | I think the compile-time programming is the real
         | differentiator, but it's hard to summarize what that means in a
         | comment.
         | 
         | Performance is pretty similar to the vanilla Lua interpreter in
         | the benchmarks I've seen and run (Janet typically wins
         | slightly), but there's no LuaJIT.
        
       | dvh wrote:
       | [flagged]
        
         | rurban wrote:
         | 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.
        
           | dvh wrote:
           | var distance = sqrt(x * x + y * y)
           | 
           | That is something very similar they may had in high school.
        
             | tasuki wrote:
             | Math notation is familiar, yes. Are you also saying math
             | notation is good? Is it an example to emulate?
             | 
             | I always thought math notation was atrocious to the point
             | of discouraging me from the subject. Who knows, had
             | mathematics used saner (simpler, consistent, perhaps
             | _slightly_ more verbose) notation, I might 've been better
             | at it.
        
               | andsoitis wrote:
               | > Are you also saying math notation is good?
               | 
               | If mathematics notation were as terrible, horrible ad you
               | say, wouldn't mathematicians have changed it by now?
        
               | gus_massa wrote:
               | Math notation is terrible! I write like 4 or 6 midterms
               | for Algebra and Calculus for the first year in the
               | university. We are using LaTeX (for most of them), but we
               | need to write LaTeX assuming the copy machine is not very
               | well maintained.
               | 
               | For example, we can't write $e^{-\frac{x}{2}}$ because
               | the minus and the bar of the fraction may not be clearly
               | separated. Also x and 2 will be too small. A solution is
               | to use \dfrac to make them bigger, but the 2D structure
               | of the formula will make the e and 2 be too close and
               | confusing. After some year of trying, one of my coworkers
               | insisted in using $e^{-x/2}$ that is ugly but copy-
               | machine-poof.
               | 
               | We also need huge integrals for
               | $\int_0^7\dfrac{1}{1+x^2}\ dx$. The standard one is too
               | small. I tried to write a macro for that, but the 0 and
               | the 7 must be in weird positions. Also, there are too
               | many cases, because the limits may be missing. Finally,
               | we are using https://ctan.org/tex-
               | archive/macros/latex/contrib/bigints with some tiny macro
               | to rename it to \lint because I don't like the names the
               | author used.
               | 
               | The math notation is very good to write in dead tree
               | paper with a pencil in 2D, but in 1D with a keyboard or
               | automatic processing is horrible.
        
             | wheelerof4te wrote:
             | Literally a one-liner that is way more readable than
             | whatever _that_ was in the OP example.
        
             | xigoi wrote:
             | Math notation also features one-letter variable names, weak
             | typing and lots of ambiguity. Do you want those in code?
        
               | eimrine wrote:
               | > weak typing
               | 
               | Let me disagree! The type is always one, Number (not Int
               | or Float).
        
               | xigoi wrote:
               | No. There are several numeric types: N, Z, Q, R, C, ...
               | However, mathematicians nearly always implicitly convert
               | between them because having explicit conversions all over
               | the place would be extremely annoying and useless.
        
           | tgv wrote:
           | Yes, they do prefer JS over Lisp.
           | 
           | > throwing away this possible user base is always a win.
           | 
           | Ok, then.
        
           | dragonwriter wrote:
           | > Normal people prefer syntax-less, unambiguous lisp-
           | languages over the mess we have now.
           | 
           | Normal people prefer REBOL, but timing and licensing
           | choices...
        
             | timbit42 wrote:
             | Well, REBOL was based on Logo, which was based on Lisp...
        
           | apetrovic wrote:
           | Yoir sample of "normal people" is vastly different than mine.
        
             | rurban wrote:
             | Good so
        
         | dang wrote:
         | Please don't take HN threads into programming language
         | flamewar. It's the last thing we need here.
         | 
         | https://news.ycombinator.com/newsguidelines.html
        
         | deusum wrote:
         | The parentheses would appear to antagonize the humours.
        
         | tasuki wrote:
         | > Normal people don't like lisp, it looks weird.
         | 
         | Have you considered that this is perhaps not a problem with
         | lisp? Normal people do not much like writing computer programs
         | at all.
        
           | oblio wrote:
           | The empirical evident would be against you, as tens of
           | millions of programmers prefer writing code in those other
           | languages that lack the parent :-)
        
             | tasuki wrote:
             | My claim was that normal people preferred not to write any
             | programs at all in any language. As to programmers,
             | obviously there are smarter ones and less smart ones and to
             | each his own.
             | 
             | Here, a weirdly misplaced smiley back at you :-)
        
               | oblio wrote:
               | Smugness doesn't make one smart. Lispers have plenty of
               | the former, though ;-)
        
             | christophilus wrote:
             | They may or may not. I prefer lisp, but I mostly program in
             | TypeScript and Go. My theory is that if most programmers
             | tried lisp for a month or two, they'd end up preferring it.
        
               | mst wrote:
               | I learned lisp (well, mostly scheme) just enough to be
               | dangerous - and to have a lot of fun.
               | 
               | I don't end to find myself -writing- lisp very often but
               | in a lot of cases I end up -thinking- in lisp and then
               | translating across to whatever language I'm implementing
               | in before I start typing.
        
         | dragonwriter wrote:
         | > I feel the need to say it every time I see new lisp-like
         | language. Normal people don't like lisp, it looks weird.
         | 
         | So? Normal people aren't computing enthusiasts, so...
         | 
         | > Are lisp-like language designers aware of that?
         | 
         | No, lisp-like language designers have never hears the
         | parenphobes that jump into every discussion of lisp-like
         | languages to make their feelings known.
         | 
         | Also, no one involved in Python, YAML, etc., has ever heard
         | anyone complain about indent-sensitive syntax.
         | 
         | > You are throwing away sizeable portion of the possible user
         | base.
         | 
         | Parenphobes are throwing away a sizable portion of their
         | potential toolkit. If they are okay with that, I am sure lisp-
         | like language designers (especially the ones doing it as a
         | labor of love and not getting paid for it) can live with losing
         | the neediest, most entitled segment of their "potential user
         | base".
        
           | andsoitis wrote:
           | > So? Normal people aren't computing enthusiasts, so...
           | 
           | even many (most?) computing enthusiasts aren't into lisp. I
           | am. Since this language is lisp-y but not deeply lisp, you're
           | now finding that not only are anti-lispers put off, but also
           | lispers.
        
             | mbnull wrote:
             | Would you also say that musicians should only create and
             | perform popular music?
        
               | andsoitis wrote:
               | absolutely not! people should do whatever they want but
               | if you're going to make atonal music in a non-traditional
               | scale, you shouldn't be surprised if you have a limited
               | audience.
        
               | xigoi wrote:
               | So? Nobody is surprised that lisps aren't popular.
        
           | return_to_monke wrote:
           | 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?
        
             | dragonwriter wrote:
             | > I want to like lisp for its features but the syntax is
             | too much for me to pick up without serious time investment
             | 
             | There's atoms, and lists, and at the highest level of a
             | program, the head of the list is the thing to be invoked
             | (function, macro, special form) and the tail is a list of
             | args. At lower levels, the higher level context says what a
             | list means, but either a list itself or the same head/tail
             | interpretation are the main things.
             | 
             | And there are some quoting constructs that control if
             | things are bare atoms or references to the values of names,
             | etc., and that's about it. Lisp has very little syntax. I
             | mean, unless your main language is raw assembler or some
             | esoteric toy like brainfuck, lisp almost certainly has much
             | less syntax.
             | 
             | > are there any other languages that support for example
             | lisp-like interactive REPL, eg analyzing program state
             | while it is running?
             | 
             | Erlang.
             | 
             | Ruby (via Pry).
             | 
             | Lots of others.
        
             | tasuki wrote:
             | > the syntax is too much for me to pick up without serious
             | time investment
             | 
             | Umm, do you know _any_ language with simpler syntax than
             | Lisp has?
             | 
             | For me, the main problem with Lisp is that there's so many
             | Lisps. I think I philosophically prefer Scheme over Common
             | Lisp, but then again there are so many Schemes to choose
             | from!
        
             | xigoi wrote:
             | 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.
        
             | cess11 wrote:
             | Lisp syntax is a lack of syntax, it takes five minutes to
             | learn. Everything being an expression, expressions being
             | replaceable by their evaluation, quote/unquote/quasiquote,
             | macros is what'll take time to adapt to.
             | 
             | Conveniently analysing program state while it's running is
             | more a feature of languages that run in an image than
             | something lisplikes have in common, like Common Lisp,
             | Factor and Pharo, but not Racket or Guile.
        
         | sph wrote:
         | i do not get why they keep writing heavy metal music. "Normal
         | people" (sic) do not like it.
         | 
         | Are metal bands aware of that? They are throwing away a
         | sizeable portion of fans and record sales.
         | 
         | --
         | 
         | I'm not sure you're acting in good faith when you say normal
         | people hate Lisp, thus it's only weirdos that use it. There is
         | no constructive discussion to be had here.
        
           | throwbadubadu wrote:
           | I feel humming Marilyn Manson's s/The beautiful people/The
           | normal people/g (aaah) is now appropriate! (:
        
         | beepbooptheory wrote:
         | There was a time when computerey people prided themselves in
         | not being "normal." You can take your normie rust, I'm quite
         | happy with my parentheses.
        
           | oblio wrote:
           | Turns out, even computer things are social since we're at our
           | best when apes work together to build complex things.
        
             | auggierose wrote:
             | That is true, unfortunately most apes just build messy
             | things these days. So, select your tribe with care.
        
         | tmtvl wrote:
         | Well, projects like Wisp* or Readable** exist, but the people
         | who use Lisp tend to prefer S-expressions, so those projects
         | don't gain a lot of mindshare.
         | 
         | It's kinda like M-expressions, a "normal" syntax gets proposed,
         | but Lisp hackers prefer S-expressions, so the new syntax just
         | kind of founders.
         | 
         | * https://srfi.schemers.org/srfi-119/srfi-119.html
         | 
         | ** https://readable.sourceforge.io/
        
       | iainctduncan wrote:
       | If you like things like Janet, you might also like s7 Scheme. It
       | is also a minimal Scheme built entirely in C and dead easy to
       | embed. I used it to make Scheme for Max and Scheme for Pd,
       | extensions to the Max and Pd computer music platform to allow
       | scripting them in Scheme.
       | (https://github.com/iainctduncan/scheme-for-max) Janet was one of
       | the options I looked pretty closely at before choosing s7.
       | 
       | The author (Bill Schottstaedt, Stanford CCRMA) is not too
       | interested in making pretty web pages, ha, but the language is
       | great! https://ccrma.stanford.edu/software/snd/snd/s7.html
        
       | gigatexal wrote:
       | The lisp style syntax is jarring
        
         | wheelerof4te wrote:
         | Honestly, to me it is unreadable. Defining function inside a
         | function inside yet another function where you use a for loop
         | kind of function.
         | 
         | It requires a much different line of thinking to be applicable
         | in the real world, which goes against historic human nature of
         | following specific instructions, one instruction at a time.
        
           | piranha wrote:
           | Not really, you're looking at this very superficially. It's
           | just an unfamiliar syntax.
           | 
           | If you're really interested, just try to get through that
           | syntax once and you'll find that it's not that alien.
        
           | nordsieck wrote:
           | > Honestly, to me it is unreadable. Defining function inside
           | a function inside yet another function where you use a for
           | loop kind of function.
           | 
           | Perhaps you think the same thing about JS where that was (and
           | maybe still is?) a common idiom. Except that people didn't
           | give those functions names.
           | 
           | And for sure, it's possible to do it in all sorts of
           | languages: python, ruby, js, go, and of course lisp
           | 
           | I get that the syntax is "weird", but honestly, the only two
           | real difference is that the parens are "on the wrong side"
           | for functions/expressions, and the indentation is truncated
           | (the trailing side of the paren pyramid is accumulated and
           | stuck to the end of the last functional line).
        
             | wheelerof4te wrote:
             | Doing that stuff in Python would further slow down an
             | already slow language to a crawl.
             | 
             | Calling non-builtin functions in cPython is super
             | expensive.
        
       | noting0002 wrote:
       | The Janet language seems very easy to learn once you know Lisp
       | and Clojure. But there are not community examples, for example
       | for using regular expressions, and the http/request is not loaded
       | in the repl when you don't install the system. Don't know why,
       | since the net module seems to work. Overall it seems a nice
       | language to play.
       | 
       | Community examples for regex gives
       | https://janetdocs.com/regex/source and the result is: opps 404
        
         | ianthehenry wrote:
         | Janet doesn't have regular expressions built in to the
         | language. Instead, you write parsing expression grammars.
         | https://janet-lang.org/docs/peg.html
         | 
         | Spork has a regex-like syntax for constructing PEGs, but the
         | semantics are slightly different.
         | 
         | And http is also part of spork, which you have to install
         | separately. (jpm install spork)
        
       | hislaziness wrote:
       | a bunch on examples on the first page - https://janetdocs.com/
        
       | spikyllama wrote:
       | line noise much? man, that example is not pretty
        
         | klyrs wrote:
         | Pro-tip: move every open-paren to the right of its first
         | enclosed token.
        
           | gus_massa wrote:
           | It also help to move each closing paren to it's own line, so
           | instead of                     )))           it looks like
           | )         )       )
           | 
           | It's almost the same number of parens, just a different
           | formatting.
        
             | epgui wrote:
             | Please don't do this... There's plugins for working
             | effectively with lisps. You probably just need the rainbow
             | parens or better contextual highlighting.
        
         | nostrademons wrote:
         | It's a Lisp. For anyone acquainted with other Lisp dialects,
         | it's about as readable as it gets.
        
         | epgui wrote:
         | If you're not used to working with lisps, your reaction is
         | basically just unfamiliarity, and not actual discernment. Lisps
         | are inarguably and objectively syntactically simpler than non-
         | s-expression languages.
        
           | [deleted]
        
           | [deleted]
        
       | WalterBright wrote:
       | I just can't let go of infix notation.
        
         | MathMonkeyMan wrote:
         | 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.
        
       | simon_acca wrote:
       | Interesting! Janet clearly stands on its own with many unique
       | features, that said if you are looking for a "scripting Clojure",
       | also consider Babashka which can tap into many very high quality
       | libraries from the Clojure ecosystem.
       | 
       | https://github.com/babashka/babashka
        
       | 2h wrote:
       | this is really cool. I love how small it is. with the Windows
       | package for example, you actually only need "janet.exe", which is
       | only 791 KB.
        
       | tmtvl wrote:
       | It's a shame the new Lisps tend to not rip off Common Lisp's type
       | system, being able to declare my types and having SBCL admonish
       | me when I'm doing something stupid is something I would hate to
       | lose.
        
         | BaculumMeumEst wrote:
         | Isn't it more accurate to call that unspecified SBCL behavior
         | than "common lisp's type system"?
        
           | lispm wrote:
           | The syntax to declare types is specified. What to do with the
           | declared types is then to be specified by a specific
           | implementation.
           | 
           | Typical possibilities:
           | 
           | * ignore
           | 
           | * use for optimizations
           | 
           | * use for type assertions and type checking
        
           | tmtvl wrote:
           | It is. SBCL does a lot of really nice things and it would be
           | nice if someone who were to design a modern Lisp would take
           | inspiration from it.
           | 
           | That said, Common Lisp is hyper advanced alien technology, so
           | it is hard to improve upon.
        
       | noreact wrote:
       | [flagged]
        
         | billfor wrote:
         | Dammit Janet.
        
       | [deleted]
        
       | cfiggers wrote:
       | Janet is really powerful. Here's a small TUI text editor I'm
       | writing in it, if you want to see a non-trivial example:
       | https://www.github.com/CFiggers/joule-editor
        
         | DennisP wrote:
         | Ooh, nice. I've been messing around with a weird text editor
         | that started with that same tutorial, but in Nim. Janet is
         | intriguing, I'll be digging into your code.
         | 
         | How was the debugging experience?
        
           | cfiggers wrote:
           | > I'll be digging into your code.
           | 
           | My apologies in advance, then! (Ha.) The "main" function is
           | at the very bottom of src/joule.janet. So I'd recommend
           | starting there.
           | 
           | As for debugging, Janet embraces REPL-driven development, so
           | the debugging experience is all about setting up,
           | interactively querying, and step-wise updating your program's
           | state, live in memory, using the REPL. It's quite a bit
           | different from a lot of languages--not better, intrinsically,
           | just different. But I like it a lot.
           | 
           | Is your Nim editor public anywhere? I've heard a lot of good
           | things about Nim and wouldn't mind exploring a real-world
           | example.
        
             | DennisP wrote:
             | Thanks :) Mine's not public yet, so far it barely does
             | anything. I'm using a piece table and some other stuff that
             | ended up being tricky to get right (hence my debugging
             | question!), then I ended up taking a break. I haven't done
             | much REPL-based work, maybe that would have sped things up.
             | 
             | Maybe I should start looking at that again.
        
         | BWStearns wrote:
         | Thought the link was broke but GH looks broken now?
         | 
         | Edit: Back up now
        
       | jimbo9991 wrote:
       | This is really cool, surprised it has so few stars and I've never
       | seen it talked about here. I like the LISPs but I've always
       | thought not having a CPython type thing was a bit of a deal
       | breaker for making it a go-to "primary" language that I would use
       | everyday.
       | 
       | I'm definitely going to try with Janet though.
        
         | masklinn wrote:
         | > I've always thought not having a CPython type thing
         | 
         | What cpython type thing? Do you mean a rich(er) set of built-in
         | datatypes?
         | 
         | Because lots of lisps have that, some (e.g. clojure) also have
         | reader macros for pseudo-literals.
         | 
         | Even Scheme has had a built-in hashmap since R6RS (2007), and
         | R5RS _implementations_ usually provided hashmaps even if they
         | were not spec-defined. Common Lisp has had a hashmap more or
         | less all along (at least since before ANSI standardisation)
        
         | iLoveOncall wrote:
         | > surprised it has so few stars and I've never seen it talked
         | about here
         | 
         | Why? It's a niche language in a dated syntax, with use cases
         | already covered by other languages.
         | 
         | You will downvote because you don't like that, but it doesn't
         | make it less true.
        
           | xigoi wrote:
           | How is the syntax dated? I'd argue that S-expressions are
           | timeless.
        
             | iLoveOncall wrote:
             | ((Oh,) (I (don't (know.))) (Just (a (random (thought (I
             | (got.))))
        
               | xigoi wrote:
               | How(is(it(different(from(C-style(function(calls)))))))?
        
       | crabbone wrote:
       | 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 terminal length and
       | terminal input being determined by when you press  "Enter".
       | 
       | I like Lisp languages, and would take Scheme over Python for my
       | job in a heartbeat, if I was allowed to. But, I think, that if we
       | want interactive Shell-like programming, we really need to
       | address the issues above in the language. Shell pipes are a good
       | start, but they are quite restricted in what they can do and
       | require xargs "extension". Some languages also have the "where"
       | form, where arguments to a function can be elaborated after the
       | function call.
       | 
       | If I was ever to design a language for interactive programming,
       | I'd certainly try to have these two features in it.
        
         | ianthehenry wrote:
         | Thank you for making an actually relevant point about syntax. I
         | agree with this 100%, and I love Janet, and was recently doing
         | a lot of interactive Janet programming for a generative art
         | playground.
         | 
         | So I added postfix function application. So instead of _(f (g
         | x))_ , you can write _(g x | f)_.
         | 
         | I liked the syntax a lot, but it looked really weird with
         | operators: _(calculate x | + 1)_. So I made operators
         | automatically infix: _(calculate x + 1)_.
         | 
         | I also didn't like that the transformation from _foo_ to _(foo
         | :something)_ (record field access) required going back and
         | adding parentheses before the value, so I added _foo.something_
         | syntax that means the same thing.
         | 
         | The result is something that's very easy for me to type and
         | read:                   (def eyes           (eye-shapes
         | | color (c + 0.5)           | color (c - (dot normal (normalize
         | eye-target) - 0.72                   | clamp -1 0
         | | step 0))           | color [c.b c.g c.r]))
         | 
         | (Excerpt from the logo of https://toodle.studio -- https://gist
         | .github.com/ianthehenry/612c980f0db04ea3c2ccab27...)
         | 
         | Is this even Janet anymore? I dunno. It's a Janet dialect, and
         | it's implemented as regular old Janet macros. But it's much
         | easier for me to type like this. I recognize that it makes my
         | code necessarily single-player, but that's fine for the sorts
         | of dumb projects that I do for fun.
         | 
         | I think a lot of lisp programmers use paredit exactly so that
         | they can write _(f (g x))_ in the order _g x f_ , but with
         | their editor re-positioning their cursor and taking care of
         | paren-wrapping automatically. But I don't use paredit, and I
         | don't want to wed myself to a particular mode of editing
         | anyway. So I like a syntax that lets me type in the order that
         | I think.
        
         | bo-tato wrote:
         | 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 about readability preference though not ease
         | of editing, lisp like languages will have paredit/sexp editing
         | shortcuts in your editor, so when you're on (f x), you press
         | one key and it's turned into (<cursor here> (f x))
        
         | twism wrote:
         | Maybe what you are looking for is threading
         | https://stuartsierra.com/2018/07/06/threading-with-style
        
         | lispm wrote:
         | The 'terminal' restriction is long gone. Most Lisp read-eval-
         | print-loops run inside an editor or another specialized tool.
         | 
         | In Common Lisp:                 CL-USER 37 > (sin 3)
         | 0.14112            CL-USER 38 > (cos *)       0.9900591
         | 
         | Above really is (cos (sin 3)). The variable * is bound to the
         | last result.
        
           | crabbone wrote:
           | How'd you go about multiple-value-bind? Same problem with
           | handler-case.
           | 
           | When used interactively, Python also has _ to store the
           | previous value (but Python only ever really returns single
           | value, which is sometimes a tuple or a list that can be
           | deconstructed into variables, iirc in CL if you don't request
           | other return values, they are gone.)
           | 
           | More generally, you'd want more of xargs-like functionality
           | (eg. split result into chunks and feed them to the next
           | function in chunks, perhaps in parallel). Or maybe you'd want
           | something like a tee, to split the results of the previous
           | function into multiple streams and processed by different
           | functions? Java-like languages don't immediately support
           | something like that, but Shell-like do with redirection
           | syntax, tee, xargs.
        
             | lispm wrote:
             | > Java-like languages don't immediately support something
             | like that, but Shell-like do with redirection syntax, tee,
             | xargs.
             | 
             | But in Lisp you are not bound to the language syntax of
             | Java. You can inside the language write tools to process
             | forms. That's one of the main differences between Java and
             | Lisp. Lisp has reader macros (to change the surface syntax
             | of s-expressions) and macros to change the expression
             | syntax. That would allow you to write tools to process code
             | and results in arbitrary ways.
             | 
             | Multiple-values results in a REPL are handled by the
             | variable /. That one is the list of the last values.
             | CL-USER 4 > (values 1 2 3)       1       2       3
             | CL-USER 5 > (multiple-value-bind (a b c) (values-list /)
             | (list a b c))       (1 2 3)
             | 
             | But anyway, I would not write Common Lisp in a pure
             | terminal without editing support.
             | 
             | Something like GNU Emacs can use tools like SLIME or has a
             | SHELL mode. That one works fine in a terminal.
             | 
             | SLIME is one of the Common Lisp IDE extensions for GNU
             | Emacs and works fine in a terminal. Writing even the most
             | complex code inside an GNU Emacs & SLIME terminal session
             | is no problem at all. If I have a function call (foo a) and
             | I want to wrap code to the front, I would just move the
             | cursor one s-expression back and type. I'm sure that's
             | easier with one of the other editor extensions which make
             | editing s-expressions kind of structural.
             | 
             | EVEN then, many people write the actual Lisp code in an
             | editor buffer (say GNU Emacs in a terminal connected to a
             | Lisp process via SLIME) and send the expression for
             | evaluation to a connected or underlying interactive Lisp
             | sessions. The editing of s-expressions in a terminal to
             | move forward, backward, upward, etc is really a non-issue.
             | 
             | Interactive read-eval-print-loops does not mean one is
             | forced to use a terminal without editing support.
        
         | tincholio wrote:
         | I'm not familiar with Janet, but I know it's Clojure-inspired,
         | so it probably has threading macros, which are like shell pipes
         | on steroids. In practice, when doing REPL-based development,
         | it's very common to use these as opposed to (g(f x)).
        
           | turbohz wrote:
           | Janet does indeed have those.
        
         | adrianmsmith wrote:
         | > So, you start out with g(x) and then need to go all the way
         | back and add f.
         | 
         | That's one thing I will say after coming from Perl/PHP to Java,
         | is that despite its verbosity and the uselessness of having to
         | write .stream(), I much prefer Java's
         | stream.map(...).filter(...) syntax over the more functional-
         | style filter(map(list, ..), ..) syntax. The Java syntax reads
         | left-to-right, which is the order you want when you're thinking
         | about code, and also as you say writing it. I think if I were
         | creating a programming language I too would try to make stuff
         | read left-to-right as much as possible.
        
           | nordsieck wrote:
           | In addition to the examples other people have given, I think
           | Ruby does this very nicely by making map, filter, and reduce
           | methods on collection data structures.
           | 
           | Of course, Ruby is a bit of a mixed bag, but for the
           | applications where it fits, it can be very nice.
        
           | temporallobe wrote:
           | Not sure about other Lisp languages, but Clojure has thread
           | operators that allow you to compose function calls this way,
           | allowing you to visualize code in that preferred left-to-
           | right (or top-to-bottom) order.
        
           | ocimbote wrote:
           | Aligning reading order with flow of actions is so important!
           | 
           | That's why I use and msybe tend to abuse the `->` and `->>`
           | macros in Clojure and the pipe operator `|>` in Elixir.
           | 
           | Hopefully soon in JS as well, if I've read correctly.
        
           | mst wrote:
           | It's notable that raku (previously known as perl6) lets you
           | write things in either direction, if I remember correctly
           | something like                 @source >>> map { ... } >>>
           | grep { ... } >>> my @sink;
           | 
           | though note I'm typing from memory on my second coffee so I
           | may have got that slightly wrong.
           | 
           | Plus of course there's many languages with a |> operator so
           | you can do                 g(x) |> f
           | 
           | I also (the example is specialised for I/O but the
           | implementation technique could trivially be borrowed for
           | something that wasn't) implemented something sort of in this
           | direction for perl once: http://p3rl.org/IO::Pipeline
           | 
           | I'm not convinced that left-to-right is -always- the best
           | option and prefer having the choice of both, but I wouldn't
           | be at all surprised if a survey of developers found that if
           | they could only pick one they'd pick left-to-right, and while
           | I'd find it hard to choose for myself alone I'd probably pick
           | left-to-right on the basis that it'd likely make it easier to
           | onboard people to any given codebase.
        
             | tmtvl wrote:
             | Raku also has map and grep methods for collections, so it
             | could be written as...                 my @sink =
             | @source.map({...}).grep({...}).sort;
             | 
             | Which also makes multithreading the operation easy:
             | my @sink = @source.hyper.map({...}).grep({...}).sort.list;
             | 
             | That said, I think the operator you're looking for is the
             | feed operator, ==>:                 my @sink;       @source
             | ==> map {...} ==> grep {...} ==> sort ==> @sink;
             | 
             | It also has the corresponding reverse, <==, because why
             | not. The docs* mention that ==> may at some point do
             | automatic parallelization, but I don't know what the status
             | of that feature is.
             | 
             | * https://docs.raku.org/routine/==%3E
        
       | gleenn wrote:
       | Syntax looks a whole lot like Clojure. I immediately appreciate
       | the optional immutability built in too.
        
         | exitb wrote:
         | Make a note though that the immutable counterparts are not
         | persistent, as the Clojure ones are.
        
       | jgrodziski wrote:
       | There is also the jank language [0] that plays in similar fields.
       | 
       | > jank is a general-purpose programming language which embraces
       | the interactive, value-oriented nature of Clojure as well as the
       | desire for native compilation and minimal runtimes. jank is
       | strongly compatible with Clojure.
       | 
       | [0]: https://jank-lang.org/
        
       | BWStearns wrote:
       | So this is kind of like a lightweight non-jvm clojure? I like it.
       | Looks like it could be a nice swiss army knife for data munging.
        
         | haspok wrote:
         | You mean Python, not Clojure. A number of key underpinnings,
         | such as (almost) exclusively immutable datastructures are
         | missing from this language.
         | 
         | It is more of a Python with a LISP syntax.
        
           | BWStearns wrote:
           | I meant Clojure. Janet's "more default looking" data
           | structures are the immutable ones which is a pretty strong
           | nudge. I don't see any explicit callout about data sharing
           | for Janet but if that's really all that's missing I still
           | feel good about citing Clojure first.
        
             | masklinn wrote:
             | > I meant Clojure. Janet's "more default looking" data
             | structures are the immutable ones which is a pretty strong
             | nudge.
             | 
             | Except they're not immutable in the clojure sense (of
             | persistent data structures), they're just fozen / readonly,
             | as can be seen from their complexity bounds (and the lack
             | of transients). And a quick check didn't show any
             | incompatibility between the two worlds either.
        
           | SyrupThinker wrote:
           | I'm pretty sure GP meant Closure, considering the language
           | has matching immutable data structures for mutable ones [^1]
           | and even its own (limited) version of EDN called JDN. It's
           | definitely also inspired by it.
           | 
           | [^1]: https://janet-lang.org/docs/data_structures/index.html
        
             | masklinn wrote:
             | > I'm pretty sure GP meant Closure
             | 
             | Closure is not a language so hopefully not?
             | 
             | > the language has matching immutable data structures for
             | mutable ones [^1]
             | 
             | Looking at the lingo being used, the extremely limited
             | breadth of ABI, and the complexity they assert around
             | "immutable" data structures, they're clearly imperative
             | data structures you can't mutate rather than the persistent
             | data structures you'd expect from a strong clj inspiration.
             | 
             | This page looks a lot more like a description of python
             | datatypes than clojure, the only bit that Python lacks is
             | an official frozendict.
        
               | SyrupThinker wrote:
               | > Closure is not a language so hopefully not?
               | 
               | Very true, the typo is strong in this one.
               | 
               | > rather than the persistent data structures you'd expect
               | from a strong clj inspiration
               | 
               | What do you mean by persistent here? I assume some kind
               | of shared memory instead of copying? Or something with
               | more practical implications like deep immutability?
               | 
               | > looks a lot more like a description of Python datatypes
               | 
               | I am surprised where this sentiment comes from. Because
               | of the initial comment? Basically any language nowadays
               | has maps, sequences and byte strings. If I had to draw a
               | similarity to Python it would be something along the
               | lines of first-class generators.
        
               | masklinn wrote:
               | > What do you mean by persistent here?
               | 
               | I mean the class of data structures called persistent:
               | https://en.wikipedia.org/wiki/Persistent_data_structure
               | 
               | > I assume some kind of shared memory instead of copying?
               | 
               | Sure.
               | 
               | > I am surprised where this sentiment comes from. Because
               | of the initial comment?
               | 
               | Because "tuple" for an immutable sequence is rather
               | specific to Python.
               | 
               | And data structures related to clojure (or functional
               | languages in general) would have some sort of logarithmic
               | component because they'd be tree-based. Pretty much the
               | only O(1) operation in functional data structures is
               | prepending to a linked list.
        
               | SyrupThinker wrote:
               | Thanks for clarifying, I did not find anything decisive
               | searching persistent in combination with Clojure, weird.
               | 
               | > Because "tuple" for an immutable sequence is rather
               | specific to Python.
               | 
               | As someone with a background in Swift, Rust and C#, all
               | of which have the concept of a tuple, I did not make that
               | connection, but thanks again.
        
               | masklinn wrote:
               | > As someone with a background in Swift, Rust and C#, all
               | of which have the concept of a tuple
               | 
               | They all have tuples, but AFAIK in none of them is a
               | tuple _a sequence_ (well not sure about C# it might be
               | there, but I 'd be surprised). Usually a tuple is a form
               | of lightweight, anonymous, structure, so it's addressed
               | by field (even if the fields are positions), you usually
               | can't iterate through tuples, or "index" them using
               | runtime variables (except through reflection).
               | 
               | That it is so in Python is somewhat peculiar, but makes
               | sense within the context of the language (unpacking works
               | on iterables, and thus sequences).
        
           | dgb23 wrote:
           | If anything it's major inspirations seem to be Clojure and
           | Lua.
           | 
           | It has some of the affordances of the former in terms of
           | semantics, but is stripped down and friendly like Lua.
           | 
           | The use cases also seem to overlap with Lua, as a fast,
           | embeddable scripting language that you can easily keep in
           | your head (see docs).
           | 
           | It seems to be simpler than Lua because it doesn't complect
           | arrays and dicts into tables, as arrays are a separate
           | construct. And it affords you with immutable versions of
           | those.
           | 
           | To me it looks like a Clojure-like for Lua use cases.
        
             | n42 wrote:
             | The Lua similarity is not exactly a coincidence, the author
             | of Janet also previously created Fennel[0], a Lisp for Lua.
             | [0]: https://fennel-lang.org/
        
           | jacknews wrote:
           | Or python with clojure syntax?
           | 
           | The author also wrote fennel, a lisp/clojure-ish wrapper for
           | lua, so I think that's the influence.
        
       | moffkalast wrote:
       | Is it a good place Janet or a bad place Janet though?
        
         | epgui wrote:
         | This is Lisp, it's definitely the Good Place (TM).
        
       | pmoriarty wrote:
       | 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.
        
         | nine_k wrote:
         | 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?
        
           | ravi-delia wrote:
           | Op was thinking of Julia
        
         | dri_ft wrote:
         | >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.
        
           | ravi-delia wrote:
           | Op was understandably confusing Janet with Julia
        
         | progre wrote:
         | 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.
        
           | ravi-delia wrote:
           | Op was thinking of Julia
        
           | lispm wrote:
           | 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.
        
             | xigoi wrote:
             | An array is just a different way to implement a list data
             | structure.
        
               | lispm wrote:
               | 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.
        
           | cosmojg wrote:
           | What data structure isn't just a list with extra steps?
        
             | MathMonkeyMan wrote:
             | Almost anything but a list
        
               | adenozine wrote:
               | Any examples to add, or you just want to leave it at
               | pithy comment?
        
             | otabdeveloper4 wrote:
             | 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.
        
               | drdec wrote:
               | The people behind the Elixir programming language
               | certainly disagree.
        
               | otabdeveloper4 wrote:
               | Maybe that's why Elixir never gained real traction.
        
               | mtlmtlmtlmtl wrote:
               | 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.
        
               | otabdeveloper4 wrote:
               | > 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.
        
               | mtlmtlmtlmtl wrote:
               | 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.
        
             | jb1991 wrote:
             | ...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.
        
               | injidup wrote:
               | Sets and maps do not required hashing. Specifically
               | std::map and std::set in the C++ standard library are
               | based on ordered trees.
        
               | jb1991 wrote:
               | 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.
        
               | glasshug wrote:
               | 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.
        
               | injidup wrote:
               | 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.
        
               | xigoi wrote:
               | > 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.
        
               | mirekrusin wrote:
               | Let's simplify it even more - everything is just ones and
               | zeroes.
        
             | krapp wrote:
             | 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.
        
         | joaogui1 wrote:
         | Uhm, sorry for asking, but are you sure you're not mistaking
         | Janet and Julia?
        
           | pmoriarty wrote:
           | 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.
        
             | grugagag wrote:
             | You're confusing your exes, it's understandable. Now give
             | Janet a fair chance if you're single
        
       | tsujp wrote:
       | Some prior threads:
       | 
       | - https://news.ycombinator.com/item?id=28850861
       | 
       | - https://news.ycombinator.com/item?id=28255116
       | 
       | - https://news.ycombinator.com/item?id=23164614
        
         | dang wrote:
         | Thanks! Macroexpanded:
         | 
         |  _Show HN: Make 3D art in your browser using Lisp and math_ -
         | https://news.ycombinator.com/item?id=32738654 - Sept 2022 (38
         | comments)
         | 
         |  _Janet - a Lisp-like functional, imperative programming
         | language_ - https://news.ycombinator.com/item?id=28850861 - Oct
         | 2021 (135 comments)
         | 
         |  _Janet Programming Language_ -
         | https://news.ycombinator.com/item?id=28255116 - Aug 2021 (114
         | comments)
         | 
         |  _Janet: a lightweight, expressive and modern Lisp_ -
         | https://news.ycombinator.com/item?id=23164614 - May 2020 (269
         | comments)
         | 
         |  _Janet - A dynamic language and bytecode VM_ -
         | https://news.ycombinator.com/item?id=19179963 - Feb 2019 (50
         | comments)
         | 
         |  _Janet, a Clojure inspired language for scripting, or
         | embedding in other programs_ -
         | https://news.ycombinator.com/item?id=19172510 - Feb 2019 (1
         | comment)
         | 
         |  _Janet, a bytecode Lisp vm_ -
         | https://news.ycombinator.com/item?id=18759277 - Dec 2018 (1
         | comment)
        
       | ianthehenry wrote:
       | 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 than regular expressions, in my opinion, for
       | anything longer than about ten characters.
       | 
       | The language itself is also a great introductory language-with-
       | lots-of-parentheses, so you can explore compile-time
       | metaprogramming with familiar runtime semantics -- think
       | JavaScript plus value types minus all the wats. The embeddability
       | and easy distribution (compiles to a static binary on any
       | platform) is a huge plus as well.
       | 
       | Honestly I like Janet so much that I'm writing a book about it,
       | because I think it's a shame that the language isn't more well-
       | known. It's great! You should check it out right now!
        
         | mike_hock wrote:
         | I went there, saw the Lisp syntax, and noped back out.
        
           | sergiotapia wrote:
           | Same reaction here... wow that is a rough looking language.
           | Then again I always disliked those kinds of languages like
           | Clojure. The syntax is just too much for me. I feel like if I
           | used it, it would atrophy my skills in other more traditional
           | languages.
        
             | mypetocean wrote:
             | The funny thing is that it's _not_ more parentheses,
             | roughly, than one would expect to find in any
             | Algol/C-inspired language, like C# or JavaScript.
             | 
             | The opening paren is simply relocated to the other side of
             | the function name or keyword.
             | 
             | What we're experiencing is just a cognitive bias which
             | causes us to prefer the more familiar over the less
             | familiar ([the mere-exposure effect, also called the
             | familiarity principle](https://en.wikipedia.org/wiki/Mere-
             | exposure_effect)).
             | 
             | I've never used a Lisp-family language, but I find the
             | reaction against parentheses to be overblown.
             | 
             | The reading order of the code is also _consistent,_ rather
             | than the frequent switching between infix notation, prefix
             | notation, and postfix notation which we have to learn and
             | parse in most languages outside the Lisp family. This is a
             | benefit which deceptively looks like it is _more_
             | complicated, despite being simpler to parse visually (and
             | otherwise). Another example of the familiarity principle at
             | work.
        
               | tremon wrote:
               | _The funny thing is that it 's _not_ more parentheses,
               | roughly, than one would expect to find in any
               | Algol/C-inspired language, like C# or JavaScript._
               | 
               | This tired trope needs to die. Yes, there are more
               | parentheses, because lisp also uses parentheses where
               | other languages use [] or {} or ;.
               | 
               | The _real_ thing is that people from C-like languages are
               | used to seeing different block markers for different
               | constructs. It takes effort to read Lisp coming from
               | other languages, because those other languages have a
               | richer symbol vocabulary. Learning to read code without
               | those symbols is like reading English where all
               | punctuation has been replaced with a single space. Sure
               | you ll get there eventually but it s a very cheap straw
               | man argument to pretend that the only complaint people
               | have about Lisps is the positioning of the parentheses.
        
               | seanstrom wrote:
               | Not a lisp apologist haha, but I think Clojure tries to
               | use fewer smooth parens "()" in general. Square parens
               | "[]" and curly parens "{}" are used to help with things
               | like variable declarations and stuff like data
               | structures.
               | 
               | I recently started using Clojure and I've used languages
               | like C#, JavaScript, and Python a lot. My two cents is
               | that a Clojure-like language should try to embrace the
               | aesthetics of a white-space language like Python, but use
               | the parens as clues for scopes or blocks. So much could
               | be done with formatting rules that just make parens
               | easier to scan without some extra IDE highlighting or
               | something.
               | 
               | The best part of parens is that you can try to pick a
               | consistent format, but ya know that sometimes doesn't
               | happen because everybody likes to use parens differently
               | lol.
        
               | mypetocean wrote:
               | Oh, I guess Markdown doesn't work. Huh. Well, shoot.
        
               | tmtvl wrote:
               | HN comment formatting options can be found here:
               | https://news.ycombinator.com/formatdoc
        
               | jdrek1 wrote:
               | There are strictly more parentheses since other languages
               | also use [] and {} (and <>) instead for different things.
               | Or even ; or whitespace. Ignoring the majority of
               | available brace types is just stupid if you ask me. The
               | parentheses being at the wrong positions is something I
               | can deal with (still no fan of RPN, but w/e), but
               | intentionally crippling syntax that could help is just
               | not a good idea. Syntax is your friend, use it.
        
               | ravi-delia wrote:
               | Janet also uses [] and {}, and there is a reason people
               | like the really consistent syntax. For me that reason is
               | blind aesthetics, but I swear to you I sincerely find
               | lisp code easier to read than non-lisp code. It's not
               | "intentionally crippling syntax" it's a genuine
               | difference in taste.
        
             | nnadams wrote:
             | I've been using Lisp for hobby projects for a few years.
             | Yes the syntax takes some time, but
             | 
             | > I feel like if I used it, it would atrophy my skills in
             | other more traditional languages.
             | 
             | was not the case for me at all. If you go into a text
             | editor and remove all the parentheses, I find that's how
             | Lisp programmers tend to see Lisp, (function argument)
             | isn't that far from function(argument).
             | 
             | Learning Lisp has only improved my skills as a programmer,
             | after getting ideas like code as data, macros, let over
             | lambda, CLOS and the metaobject protocol. It's a simple
             | model that to me shows how other languages have picked an
             | abstraction and stuck with it, but Lisp has all the tools
             | to implement those abstractions and more.
             | 
             | More mainstream languages are great at focusing the
             | developer, and that makes them very practical. It is
             | amusing though to watch many of the "new features" in
             | languages come out even though Lisp had them years ago.
        
             | camdez wrote:
             | 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,
             | principled, elegant reason for it; Lisp code represents how
             | the code will be evaluated in the most direct way, without
             | relying on (some would say needlessly) complex parsing /
             | precedence rules. There are no surprises and no arbitrary
             | rules to learn. There are no useless semicolons to forget,
             | and you'll never have to wonder if `+=` returns the RHS or
             | the result of the operation (or does it even have a return
             | value?).
             | 
             | You don't have this meaningless distinction where you can't
             | directly reduce with `+` because--ugh--it's not a function,
             | it's an operator. You just say `(reduce + [1 2 3])`.
             | 
             | You never have to do this ugly Ruby stuff...
             | words.map &:length       # or       words.map { |w|
             | w.length }
             | 
             | ...because methods are _really_ just polymorphic functions,
             | but language designers chose syntax that doesn 't compose
             | elegantly.
             | 
             | You don't have this useless distinction between statements
             | and expressions that limits how you can compose code. You
             | never have to drop down to some ugly, limited tertiary
             | expression form (`COND ? X : Y`) of `if` because--
             | whoops--`if` is a "statement". You just write:
             | (println (if me? "me" "you"))
             | 
             | Because, duh, we wanted an `if`.
             | 
             | What do we gain by adding all of this noise?:
             | if (is_me) {         println("me");       } else {
             | println("you");       }
             | 
             | Absolutely nothing. The parens on the conditional, the
             | curly braces, the semicolons, the `else` keyword--they're
             | essentially meaningless incantations to appease the
             | compiler. And we've introduced an undesirable opportunity
             | for the two branches to accidentally diverge over time.
             | 
             | But most importantly, our code is written in the data
             | structures of our language. Code as data means we can
             | manipulate code as easily as we manipulate data, which
             | means we can trivially (re-)write code with code (i.e.
             | macros). And not shitty string generating macros, or macros
             | that can only do a handful of sanctioned things--we can
             | write our own control structures in couple lines of code.
             | We can add new abstractions to the programming language
             | from user space.
             | 
             | Wish the language had an `if-not` construct? You can add it
             | with, like, 3 lines of code. Wish functions could have
             | optional parameters? Add it. Wish it had a pattern matching
             | functions like SML or Erlang? Cool. Java-style annotations?
             | Logging that is fully removed when running in high
             | performance mode? A different OO model? Multi-line string
             | literals? String interpolation? A graph of dependent
             | calculations that only get run when used? A more convenient
             | way to load dependencies? It's all easily doable.
             | 
             | I've coded in Lisps (and a dozen other languages) for at
             | least 20 years, and every time I have to use a non-Lisp
             | syntax I just think "wow, these people really missed the
             | boat". It's like having to write math in Roman numerals
             | (would you rather calculate "D + L + IX" or "500 + 50 +
             | 9"?); there's a better way, and that better way has
             | elegant, recursive, underlying design principles that make
             | the ergonomics way better.
             | 
             | But, yeah, it doesn't look like C code. And people seem to
             | be really attached to their C syntax.
        
               | jdrek1 wrote:
               | That example is quite unfair. You could just write
               | println(is_me ? "me" : "you")
               | 
               | which has exactly the same amount of symbols.
        
             | eggy wrote:
             | Quite the opposite. Learning a Lisp or an Array language
             | will build your skills and make you a better programmer.
             | Syntax should fade as a criteria as you become proficient
             | in various PLs.
             | 
             | For example, the sum of a list (not running or cumulative
             | sum, but total sum. Should equal 10, not 1, 3, 6, 10):
             | 
             | Lisp:                 (+ 1 2 3 4)
             | 
             | J/APL[0]:                 +/1 2 3 4
             | 
             | Python:                 Sum = sum([1,2,3,4])
             | print(Sum)
             | 
             | They all do the same. I prefer the conciseness of J/APL and
             | Lisp in this case, and the application of a function over
             | the list or vector. The beauty of the REPL is that you see
             | the result without a 'print' statement.
             | 
             | Solving problems in these other languages will influence
             | how you program in your base language as well, and usually
             | for the better. I am also guilty of syntax bias. I prefer
             | LFE (Lisp Flavoured Erlang)[3] over Elixir and Gleam.
             | Gleam[1], another language that runs on the Erlang VM
             | (BEAM), had a more ML syntax, but then it chose to join the
             | syntax popularity contest and move to a more Algol/C/Rust
             | syntax. I prefer vanilla Erlang over it too.
             | 
             | [0] https://www.jsoftware.com/#/ [1] https://gleam.run/ [3]
             | https://lfe.io/
        
           | malodyets wrote:
           | Nope as a verb is new to me - just heard it for the second
           | time this week. First time was from my child.
        
             | adrusi wrote:
             | It's somewhat youthful internet slang. You'd hear it at the
             | American public highschool I was at 12 years ago.
        
           | camdez wrote:
           | 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.
        
             | ravi-delia wrote:
             | 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.
        
           | dunefox wrote:
           | Your loss.
        
           | co_dh wrote:
           | Me too
        
           | pmoriarty wrote:
           | Lisp syntax is a huge plus for me, and if a language doesn't
           | have it I know it's not for me.
        
         | weavie wrote:
         | Is there somewhere I can keep up to date with books progress?
        
       | davbryn wrote:
       | I think the language is unreadable. For me, the purpose of a
       | programming language is to let a human talk to a machine. Show me
       | (for instance) control flow for the example function on the home
       | page. It just isn't making things easier
        
         | StreamBright wrote:
         | I guess: f x -- obscure and mathematical
         | 
         | (f x) -- too many parentheses
         | 
         | f(x) -- PERFECT
        
           | ElfinTrousers wrote:
           | Well hold on, what's wrong with (f) x?
        
           | fm2606 wrote:
           | >> (f x) -- too many parentheses
           | 
           | >> f(x) -- PERFECT
           | 
           | They have the same number of parentheses.
           | 
           | f(x) is probably something you have seen for the majority of
           | your life as this is how math is taught.
        
             | StreamBright wrote:
             | I was just saying that syntax arguments most of the time
             | are silly. I like LISP and ML languages, so for me it
             | doesn't really matter if I need to write LISPy code or ML
             | code.
        
         | hnlmorg wrote:
         | Readability can be a subjective property.
         | 
         | For anyone who's spent even a casual amount of time with
         | S-Expressions, the example code is extremely readable. But if
         | ALGOL-like code is your main source of experience, then Janet
         | will look like executable line noise.
        
         | bmacho wrote:
         | I tried to translate it to python, I translated
         | (defn sum3           "Solve the 3SUM problem in O(n^2) time."
         | [s]                (def tab @{})           (def solutions @{})
         | (def len (length s))                (for k 0 len
         | (put tab (s k) k))                (for i 0 len             (for
         | j 0 len                    (def k (get tab (- 0 (s i) (s j))))
         | (when (and k (not= k i) (not= k j) (not= i j))
         | (put solutions {i true j true k true} true))))
         | solutions)
         | 
         | into                   def sum3(s) :             """Solve the
         | 3SUM problem in O(n^2) time."""                      tab = {}
         | solutions = {}             l = len(s)                      for
         | k in range(0,l) :                 tab[ s[k] ] = k
         | for i in range(0,l) :                 for j in range(0,l) :
         | k = tab.get( -s[i]-s[j] )
         | if k and k != i and k != j and i != j :
         | solutions[ {i:True, j:True, k:True} ] = True
         | return solutions
         | 
         | pretty much the same. Python is not working because it can't
         | hash dicts, while janet interprets {1:True, 2:True} the same as
         | {2:True,1:True} when these are keys (I think?).
         | 
         | In the example janet returns                   (map keys (keys
         | solutions))
         | 
         | instead of the "solution" dict that converts dicts like
         | {{1:True, 2:True} : True} into [[1,2]], but I don't get it how.
         | 
         | But syntactically janet is not much worse(?).
        
           | jpk wrote:
           | One thing the Python version doesn't suffer from is lines
           | that have to end in something like "))))". Syntax readability
           | may be subjective, and I agree that the business logic in
           | both examples are equally readable, but I think having to
           | read and write a bunch of repeated punctuation at the end of
           | a line, depending on how deeply the final statement is
           | nested, is annoying. I don't know how Janet in particular
           | handles error messaging around unmatched parens, but most
           | languages have trouble localizing errors to the place where
           | missing parens, curlies, etc actually are. This can be
           | alleviated by rainbow highlighting paren pairs, or even
           | having the editor auto-insert closing parens to make you less
           | likely to forget one. But I think if you need additional help
           | from the editor to make using the syntax a nice experience,
           | that may be an objective sign that the syntax isn't the best.
        
             | runevault wrote:
             | You don't HAVE to write lines that way, though it is the
             | convention which as a mostly outsider I've never been a
             | huge fan of. Think about languages like c# where you often
             | have multiple closing curly braces but the convention is
             | separate lines. You could write them like Lisp if you
             | wanted but no one does.
        
               | jpk wrote:
               | I assume "))))" is idiomatic because of the typical depth
               | of nesting required in languages like this. If you always
               | used newlines and indents to align the closing character,
               | you'd waste a lot of vertical space. That's less of an
               | issue in something like C# where you don't have to nest
               | as deeply.
        
             | nmz wrote:
             | This is kind of unfair, unless you're in an indent based
             | language you cannot get rid of this. The only other
             | solution I've seen was in a pascal-like language, where you
             | did end function NAME and that would close everything
             | inside.
        
               | jpk wrote:
               | True, but there are two things languages like C have over
               | this one: (1) Enclosing stuff in parens and curlies
               | happens less often than they do in this one. So the depth
               | of nesting is typically shallower. (2) The idiomatic way
               | to handle closing multi-line blocks is to use newlines
               | and indents to visually align the closing character with
               | the start of the line containing the opening character.
               | But, like a sibling comment points out, nobody does that
               | and "))))" is idiomatic here, so I feel like it's a fair
               | call-out.
        
         | modernpink wrote:
         | I assume you've not done LISP or LISP-like languages before?
        
         | xigoi wrote:
         | How does the example not show control flow?
        
       ___________________________________________________________________
       (page generated 2023-02-18 23:02 UTC)