~pepe/pan.earth

4521dc3b9bac49b529fb0ada80de9071af7c5f15 — Josef Pospíšil 2 years ago f1f30ee
Move all posts
M content/index.mdz => content/index.mdz +2 -5
@@ 1,10 1,7 @@
{:author "Josef Pospíšil <josef.pospisil@laststar.eu>"
 :title "Pan Earth home page"
 :title "Pan Earth"
 :template "/templates/index"}
---

@html[ <img src="logo.svg" alt="logo" id="logo"/> ]

## What?

As 2020 is roaring around, I found it very hard to stay in the state of


@@ 14,6 11,6 @@ As 2021 flood the world again, I needed to resolve.

Not that I have any plan or ambition to save the Earth.

I just want to share some actual stuff, that can be of help to you.
I just want to @link[/posts/][share some actual stuff], that can be of help to you.

Or not.

A content/posts/how-i-became-janet.mdz => content/posts/how-i-became-janet.mdz +102 -0
@@ 0,0 1,102 @@
{:author "pepe"
 :title "How I became a Janet"
 :description "Musings about how I got to love Janet programming landugage"
 :date "2021-01-01"
 :template "/templates/blog"}
---

You may already understand, after reading @link[/posts/janetuary.html][Janetuary]
that next post on this new blog of mine is about the programming language.
But why not one of the famous or even the rising one. No, the language is
not very well known or followed. And I am not writing about the language,
but about my relationship with it and why I chose this particular one for
my further development needs. Its name is, you guessed it, Janet.

Janet is the name of the language and programmer. Yes as of now, we as the
programmers in the Janet programming language are calling our selves Janets.
Also, I like to use female pronouns for the language, against the English
custom I fear, but one thing I strongly believe in is that males have created
our profession toxic panopticon and the only way out of it is to lose the
grip and invite the female phenomenon into it more. And no, I do not talk
about genders here.

### Lisp curse

About fifteen years ago, I was very into Ruby. I had the talk about Cucumber
at the IT conference organized by my faculty college and the man who got me
back to programming (in SmallTalk no less). After the main course I have met
him and was talking about how Ruby fulfils my OOP dreams, he told me that I
should check Lisp. And I was telling my self: no way I am constructing AST
with parenthesis and my bare hands.

And happily after. I stayed more than ten years with Ruby as my main lang. Of
the work and the interest. Until I started to believe in more frontend,
which gravitated me towards some other language designs. Then I have seen a
tweet by Tonda about the cljs tooling, and future of the web. Re-frame was
born around that time, and I jumped in.

Same as with Ruby I got one long-running project on the green field. I chose
feathers.js for the API backend and huge SPA in ClojureSscript. And man I
had dreams about mother function and finally got what Vojta was telling me
ten years prior. There is something admirable in FP. Luckily for me before I
got radicalized for it (as I did for OOP once), I have attended talk about
the programming paradigms, and it somehow opened my eyes forever. Every
paradigm has its place and meaning.

I used only ClojureScript, cause I have not liked JVM in my brief time as
a Java programmer. But somehow I was not happy in the Clojure world. And
I have met some of the brightest minds programming-wise in its world. Some
uneasiness I felt.

### Early adopter

Then at the beggining of the last year, when I was not having only my main
project, but also side-kick for US company I have found
@link[https://github.com/andrewchambers/janetsh][janetsh] by Andrew
Chambers. It was of small value for me, cause my fish config is too much to
convert easily. But it took me to Janet, and I have seen the light. I believe
there were less than two hundred stars when I added mine on GitHub. Whatever I
tried, it just worked. It had all the rubyness of shortest time from writing
to run, it had repl at the Clojure level, and it is easy to understand how
to write C extensions and wrappers.

Guess what. After 25 years of not touching it, I wrote my first substantial,
not to educate my self, or be educated with it, C program. And it leaked
and crashed and burned, but still, it worked, and it is now at the core of
my dev stack.

Best of all I finally started to work for the community, cause the Creator
of the lang is the best person I have ever met at this level of wizardry,
and the community is full of very bright and friendly people. I know you have
heard it before, and probably about your community. Still, I am ready for
any challenge, even the beer one. I fixed more bugs in others code in the
last months than in my previous developer life. I worked on documentation,
and I helped at the Gitter chat.

### Living in the hard times

Just before the lockdown started here in the Czech Republic, my wife undertook
routine surgery. We had plans, how we will send kids to the grandparents'
house, and I will take care of her at our cottage. Lockdown scratched that
plan, and we ended up in the cottage, five people, me at the helm and the
floor of the whole family.

And things were looking scary at the time, and my depression came back after
almost twenty years. The only time I was happy, was when I was programming in
Janet. Not in any other langs I use for my work I felt such joy and feeling
of the freedom of the mind.

Maybe, that this little solitude saved my life at that time. I am not sure,
what was the ingredient, I am just sure that it was Janet.

I started @link[https://git.sr.ht/~pepe/jff.git][jff] and
@link[https://git.sr.ht/~pepe/neil][Neil], which is my main project for the
time being. I learned a lot more about the lang and virtual machine design.

### To be continued

In the next instalment, I would like to show you my reasons why I am using
Janet as my primary language. Finally, some technical talk.

Stay safe, do good and do not believe the hype!


A content/posts/index.mdz => content/posts/index.mdz +7 -0
@@ 0,0 1,7 @@
{:author "pepe"
 :title "Blog"
 :template "/templates/blog-index"}
---

## Posts


A content/posts/janetuary.mdz => content/posts/janetuary.mdz +42 -0
@@ 0,0 1,42 @@
{:author "pepe"
 :title "Janetuary"
 :description "What is Janeruary"
 :date "2020-12-21"
 :template "/templates/blog"}
---


### Dry month

For more than ten years, I abstain from the alcohol for the first month of
the year (formerly known as January).  I have the family predispositions for
losing it to alcohol, and that is never pretty.

The last couple of years, I have spent this surplus time on various personal
and work projects. But this year I have another goal in mind.

### Enter Janetuary

As you can guess the name of this post and the month from now on, is the
play at the @link[https://janet-lang.org][Janet] programming language name.

So what is on my mind, you can ask? Well, I would love to spend most of
my time by the computer to develop, document and just care for the Janet
language. There will be more post like this one, I would like to make
stream with examples of the day to day usage of Janet in my desktop setup,
consolidate my @link[https://sr.ht/~pepe/good-place/][personal project in Janet],
help others with their project be it docs or coding, add one example to the
beautiful @link[https://janetdocs.com][Janetdocs] project, be on
@link[https://gitter.im/janet-language/community][Gitter channel] for others to
help and some more.

### What is the reason?

Right now, I can tell you only that there will be another post, when Janetuary
starts, where I will shine more light on this resolution from another point
of view.

### Do you like it?

Go and help Janet development and share. There won't be any prizes, GH tags
or such things. But you can find something more.

A content/posts/why-i-am-janet.mdz => content/posts/why-i-am-janet.mdz +219 -0
@@ 0,0 1,219 @@
{:author "pepe"
 :title "Why I am Janet"
 :description "Reasons why I am using Janet"
 :date "2021-01-08"
 :template "/templates/blog"}
---

In this installment I would like to show you in six cases, why is
@link[https://janet-lang.org][Janet] my programming language of choice.

## Case 1: Immutable or not

I will start small: Janet has both mutable and immutable data structures for
all three usual suspects. So we have a buffer (mutable) and string (immutable),
also table (m) and struct (i), and indeed the array (m) and tuple (i). I
can understand the argument for immutable data, and respect it, but I love
the choice. Janet gives me that on every step, and yet guide me by its design.

## Case 2: Metal

### C

The fundamental property of the Janet language is the low-level nature of
the language implementation. C is the programming language used to implement
lots of parts; its parser, compiler, the virtual machine and a lot of the
functionality in the standard library.

This choice not only makes Janet fast and efficient, but it also brings
inspectability and transparency of the underlying mechanisms. Another benefit
is that there is the header file for the Janet C API, with which it is not
that hard to build your own C code or wrap some existing C code into your
library or embed Janet in other C program.

### Print

In the spirit of the best Unix programs printing to the stdout is the
first-class citizen in the Janet language. For example, templating language
@link[https://git.sr.ht/~bakpakin/temple][Temple] by the creator of the language
just prints. In the
@link[https://github.com/janet-lang/spork/blob/master/spork/fmt.janet][formatting part]
of the @link[https://github.com/janet-lang/spork][Spork]'s library base function
prints. The standard library has many functions for better work with the
printing, e.g. redirecting output.

### Threads

The threads are also part of the core of the language. You can say what you
want when @link[https://shouldiusethreads.com/][you should use the threads]
but sometimes it is very convenient to spin up threads for the hard
work. Especially if the threads are more similar to the erlang processes than
to the standard OS threads. Still, you have to use them safely, because of
the race conditions and locks.

## Case 3: OOP

Now you have to think I have gone crazy. OOP in the functional language,
isn't it anti-pattern? I do not think so. Once I have been to
@link[https://www.youtube.com/watch?reload=9&v=uNPdZm5oF_E][talk] which
compared all three main paradigms. I took away that every paradigm has its
place and time for usage.

### Prototypes

The OOP in Janet is the prototype-based one and backed by the table data
structure. You can easily set the prototype for the table with some properties
or behaviour, which is then inherited by your table.

### Messages

The syntax for sending messages is easy. Call the keyword with the object
you are calling the message on as the first argument. This syntax is often
confusing for the people coming from the Clojure, because they can be used to
get the value from hashmap this way.

### Abstracts

One exciting possibility emerging from this concept is that you can easily
teach messaging to your JanetAbstract objects written in the C language. Then
you have programs written in C looking just like ordinary Janet objects.

## Case 4: PEG

As you may remember from the
@link[/posts/how-i-became-janet.html][How I became Janet]
post I was avid Rubyist. One of the quotes from Matz I like a lot is:

@pre[There are only three things certain in programmers life:
taxes, death and parsing text.]

For this purpose, Janet uses
@link[https://bakpakin.com/writing/how-janets-peg-works.html][PEG]. If you are
not sure, read the article to understand the concept better. With it, you
can create a small state machines, which can scan, parse and transform the
text into another form of the data.

### Oh so core

What I love a lot about this particular implementation? That it is part of the
core of the language, again, you guessed, written in C. The PEG definition's
syntax is pure Janet code, very similar to how you write macros with all the
quoting, quasiquoting and unquoting. Its learning curve is steep, especially
if you strive for very optimal definitions, but once you get feel of it,
you will never look the same on a string of text. And you will finally
understand why you hated regex so much.

### Command and conquer

One use case, where PEG shines for my particular interest is parsing the
interactive commands user input, mostly in TUI applications. I will discuss
this more in one later post, where I will write about my projects.

## Case 5: Dynamic

### Environment

The environment is just a Janet table, that holds all loaded bindings. The
one called root is used as a base, when you want to create a new one, for
example for the new fiber, you are creating, or when you are compiling your
code by hand.

### Modules and Loaders

As is a custom in many languages, Janet has modules system to separate concerns
and divide code into smaller parts. By default, one source file maps to one
module and contains bindings and the environment. By importing a module, you
bring these to the current environment. But there are many other mechanisms,
how you can make this your own, some of them I will show in this part.

The loader is a mechanism that imports modules into the
environment. Interestingly, you can have loader not just for the Janet code,
image and native modules, but for whatever syntax. One lovely example is
the Temple library, which uses them to load your HTML (or any other) templates.

### Fibers

The concept is very similar to the coroutines in other languages with one
caveat: it is also one of the base building blocks of the language and the
virtual machine. The fact also supports this: fiber contains a mechanism
for signalling, which helps differentiate the fiber's return, called
yielding. One of the usages touted by the language creator is capturing error
in the fiber's code, returned to the calling fiber. Yes, you are always in
the fiber, when you have Janet code running.

Right now the development version of the language contains generators,
based on fibers. Generators are similar to the Python ones, but due to the
status of the fibers as the first-class citizens of the language, they are
more natural in my view.

### ev

Experimental and developing feature of the language added just in the latest
minor update, but great potential for the future. Maybe you already know what
it is: event loop in the core of the language! Just say how cool is that, and
with fibers as building blocks, it shines for anything async you throw at it
(if it does not block that is). Even as I am very excited about this feature,
I would rather wait for a little for it to mature and show all its facets.

### Compiling

I know what you think; pepe just got out of ideas. No, I do not want to talk
about the fact, that Janet compiles the source code into virtual machine
bytecode, what I want to convey is that there is absolutely nothing wrong
for you as a programmer to grab some AST (probably provided by the language
parser) compile it and run compiled code. Or use some of the higher-level
mechanisms already present in the standard library as dofile or require.

I just used my minimal knowledge of programming language design to develop
Janet @link[https://git.sr.ht/~pepe/jlnt.kak][linter] for the Kakoune editor,
which probably is not the best linter around, but works great for me.

And not only code but even PEGs you can compile for faster and more efficient
run, when their time comes.

### Macros

As any other Lisp, and many other languages Janet has macros. With all said
above, I am not afraid of writing them and even use them in a way, that will
up many brows, I fear. Yes, we can use macros! Deal with it.

## Case 6: Grab bag

### Tables

As you may understand now, tables are everywhere in the language OOP,
environment and other places, and frankly quite common in other langs. So? In
my opinion, Janet's ones are top-notch, similarly to fibers, because they
are the very basic building block of the language design.

### Repl keys

Standard Janet repl has already coded a lot of shortcut keys for navigating
and modifying input text. One of the good outcomes of this feature is that
all those are also present in standard library getline function. But for me,
there are two I use a lot and refuse to switch to remote repl from the editor:

* tab completes the binding you have started, even showing you the options,
when there are more than one.

* ctrl+g shows the documentation for binding
under the cursor! You may know that thought: is the separator first or the
last parameter to this fn?

And both are present when you use standard library getline; you provide the
table with bindings.

### Loop

In the standard library, there is a macro loop, which is similar to those
in other Lisps. It also has sister macro seq, which gathers all the results
from all runs. I do not use it very often, but when I do, I praise it.

## To be continued ...

That's all folks for this part. Next will be again little bit more
philosophical.

To understand all this better, be sure to read the
@link[/posts/how-i-became-janet.html][first installment].


M panearth/acts.janet => panearth/acts.janet +7 -1
@@ 95,7 95,13 @@
                       :dev dev}
                      (if index?
                        {:markups ms
                         :posts (filter |(not (index? $)) bfiles)}
                         :posts (as-> bfiles fs
                                     (filter |(not (index? $)) fs)
                                     (sort fs
                                       (fn [a b]
                                             (let [mad (get-in ms [a :date])
                                                   mbd (get-in ms [b :date])]
                                                (> mad mbd)))))}
                        {}))))
           (save-content file fc))
         ([e] (log "Error: " e " when rendering file: " file))))}))

M static/css/main.css => static/css/main.css +1 -1
@@ 10,7 10,7 @@ body {
}

#hero #logo {
  width: 18.16%;
  width: 8.16%;
  max-width: 30rem;
}


M templates/blog-index.temple => templates/blog-index.temple +9 -9
@@ 2,9 2,9 @@
(use spork/temple) (add-loader)
(import /templates/head) (import /templates/foot)
(defn anchor [post]
  (-&gt;&gt; post
    (string/replace &quot;content&quot; &quot;&quot;)
    (string/replace &quot;mdz&quot; &quot;html&quot;)))
  (->> post
    (string/replace "content" "")
    (string/replace "mdz" "html")))
$}
{- (head/render-dict args) -}
<div>


@@ 13,12 13,12 @@ $}
     {- (args :content) -}
  </div>
  <ul>
      {% (loop [p :in (args :posts)
                :let [pa (anchor p)
                      m (get-in args [:markups p])]] %}
    <li><strong><a href="{{ pa }}">{{ (m :title) }}</a></strong>
        by {{ (m :author) }} at {{ (m :date) }}</li>
  {% ) %}
    {% (loop [p :in (args :posts)
              :let [pa (anchor p)
                    m (get-in args [:markups p])]] %}
      <li><strong><a href="{{ pa }}">{{ (m :title) }}</a></strong>
          by {{ (m :author) }} at {{ (m :date) }}</li>
    {% ) %}
  </ul>
</div>
{- (foot/render-dict args) -}

M templates/blog.temple => templates/blog.temple +5 -4
@@ 3,8 3,9 @@
(import /templates/head) (import /templates/foot)
$}
{- (head/render-dict args) -}
  <h1>{- (args :title) -}</h1>
  <div>
    {- (args :content) -}
  </div>
<h6>Published on {{ (args :date) }} by {{  (args :author)  }}</h6>
<h1>{- (args :title) -}</h1>
<div>
  {- (args :content) -}
</div>
{- (foot/render-dict args) -}

M templates/index.temple => templates/index.temple +4 -1
@@ 3,7 3,10 @@
(import /templates/head) (import /templates/foot)
$}
{- (head/render-dict args) -}
<h1>{- (args :title) -}</h1>
<hstack align-x="center">
  <img src="logo.svg" alt="logo" id="logo"/>
  <h1>{- (args :title) -}</h1>
</hstack>
<vstack id="content" align-x="center">
  {- (args :content) -}
</vstack>