Skip to content

Instantly share code, notes, and snippets.

@sogaiu
Last active November 25, 2025 11:59
Show Gist options
  • Select an option

  • Save sogaiu/a180b3fc377dae1bcf96312ad11f1fa6 to your computer and use it in GitHub Desktop.

Select an option

Save sogaiu/a180b3fc377dae1bcf96312ad11f1fa6 to your computer and use it in GitHub Desktop.
use of def and let in janet

(sketching out own thoughts -- explicit examples would likely help in making things clearer)

on the topic of my own use of def and let in janet...

  • often default to using def

    • doesn't increase indentation so line lengths are not increased [1]
      • all of the relevant code within a let is shifted to the right
        • the binding bits extend further to the right
        • the body extends further to the right
    • def seems to work better with the idea of "define close to first use of name"
      • doing this with let can result in multiple nested let forms which can adversely impact perception sometimes (i.e. code might be less clear)
    • generally it seems easier to insert debugging code when using def compared to let. clojure has a kind of hacky way of attending to this by doing stuff like (let [a (my-fn) _ (print a)] ...), i.e. using _ to bind results of debugging code. this point is less relevant for languages that have a source level step debugger. clojure now has a few things like this but they are not built into the language. as far as i know, janet doesn't have a source level step debugger (yet?).
  • sometimes use let

    • "one-off" or "temporary" names that one doesn't need for "too much" of the corresponding containing form
    • can be nice for branches of if, certain parts of cond, etc. as a way to avoid having to use do

why might some of the above be particularly relevant for janet?

possibly it is related to janet supporting an imperative style of programming, but it may also ne that janet relies pretty heavily on arrays and tables specifically instead of linked lists as is the case in common lisp, emacs lisp, or scheme.

in clojure's case, there are persistent data structures and there is a heavy emphasis on not mutating / avoiding imperative programming (and also having had a heavy influence from common lisp as rich hickey was quite into common lisp).

janet is its own thing -- the syntax is mostly lispy and there are macros, but it is quite different underneath from the other ones mentioned above...quote from the janet repository readme:

Is this a Clojure port?

No. It's similar to Clojure superficially because I like Lisps and I like the aesthetics. Internally, Janet is not at all like Clojure, Scheme, or Common Lisp.


[1] long line lengths can lead to reduced comprehension at a glance but also make side-by-side comparison more difficult...see here for more on line lengths.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment