Posted on 13th of October 2023
| 356 wordsNB: I’ve since decided to quit Mastodon
In the digital landscape, social media is an indispensable tool for
communication, networking, and content sharing. Yet, the way these platforms
have been implemented and designed isn’t praiseworthy. From content
suppression algorithms to opaque data policies, it’s no secret that the
leading tech giants have cultivated a restrictive environment.
I’ve been vocal about social media and how wrong it has always felt to me,
leading me to delete most of my social media accounts apart from
LinkedIn.
However, is LinkedIn truly a
social media platform or merely a glorified job board? I also wrote a post
about social media from the perspective of digital
minimalism
some time ago.
For years, I was content without any social media accounts, and still am.
Recently, I yearned for an online community to engage in meaningful
discussions and banter, perhaps due to my move to a new country last year or
simply because of an extended hiatus from social media.
I didn’t want to return to the draconian social media platforms I once used,
like Facebook, Instagram, and Twitter. Even Reddit didn’t pique my interest.
Nevertheless, I sought something new, which led me to consider Mastodon.
I had followed Mastodon’s development from afar due to my reluctance to join,
not because Mastodon is malevolent, but because I felt I spent too much time
on computers, and joining might exacerbate that.
However, after stumbling upon intriguing threads (is there a Mastodon-specific
term for these?), I decided to join Mastodon and participate in discussions.
Intrigued by its promise of a democratic and transparent social media
experience, I took the plunge and joined the Mastodon community, finding it a
breath of fresh air.
I’m thrilled to contribute to a platform that values user autonomy, fosters
genuine human connections, and champions transparency and inclusivity.
Embracing Mastodon signifies not just a personal choice but also a deliberate
step toward fostering a more democratic and empowering social media
environment for all.
In a world rife with censorship and control, Mastodon serves as a beacon of
hope, embodying technological innovation that prioritizes user well-being and
digital freedom above all else.
Posted on 3rd of October 2023
| 1178 wordsSo, like I mentioned in a previous post
, my
hands have been quite full with Baldur’s Gate 3, so I haven’t been able to
program too much Sila. But thankfully, while I enjoyed the game through and
through, it’s nice to be back to hacking.
I started to add more parser rules for Sila, simple ones still, but crucial
nonetheless. These included stuff like parsing equality (==, !=), relational
(>, <, <=, >=) and unary nodes (-1, +2). While writing these rules, I quickly
realized that I’m repeating myself quite a bit. So as a Lisp hacker, naturally
I decided to reach for macros in this case to make my own life just a little
bit easier.
If we look at the structure on how I decided to parse equality and relational
nodes, they looked something like this:
(defun parse-equality-node (tok)
"equality-node ::== relational-node ( '==' relational-node
| '!=' relational-node ) *"
(multiple-value-bind (node rest)
(parse-relational-node tok)
(loop
(cond ((string= (token-val rest) "==")
(multiple-value-bind (node2 rest2)
(parse-relational-node (token-next rest))
(setf node (make-ast-node :kind :equal :lhs node :rhs node2))
(setf rest rest2)))
((string= (token-val rest) "!=")
(multiple-value-bind (node2 rest2)
(parse-relational-node (token-next rest))
(setf node (make-ast-node :kind :not-equal :lhs node :rhs node2))
(setf rest rest2)))
(t
(return-from parse-equality-node
(values node rest)))))))
(defun parse-relational-node (tok)
"relational-node ::== add ( '<' add
| '<=' add
| '>' add
| '>=' add ) *"
(multiple-value-bind (node rest)
(parse-add-node tok)
(loop
(cond ((string= (token-val rest) "<")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node (make-ast-node :kind :lesser-than :lhs node :rhs node2))
(setf rest rest2)))
((string= (token-val rest) "<=")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node (make-ast-node :kind :lesser-or-equal :lhs node :rhs node2))
(setf rest rest2)))
((string= (token-val rest) ">")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node (make-ast-node :kind :greater-than :lhs node :rhs node2))
(setf rest rest2)))
((string= (token-val rest) ">=")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node (make-ast-node :kind :greater-or-equal :lhs node :rhs node2))
(setf rest rest2)))
(t
(return-from parse-relational-node
(values node rest)))))))
So the structure between these are pretty much identical. First, I bind the
values that I get from the next parser rule, e.g. parse-relational-node
or
parse-add-node
, and I run infinite loop and check the next tokens and create
nodes based on that.
Macro Definition
Function definition can be broken down to a following macro:
(defmacro define-parser (name &key descent-parser
comparison-symbols
bnf)
"Macro for generating new parser rules."
(let ((parser-name (intern (format nil "PARSE-~a-NODE" name)))
(descent-parser-name (intern (format nil "PARSE-~a-NODE" descent-parser))))
`(defun ,parser-name (tok)
,bnf
(multiple-value-bind (node rest)
(,descent-parser-name tok)
(loop
(cond
,@(loop :for symbol in comparison-symbols
:collect `((string= (token-val rest) ,(car symbol))
(multiple-value-bind (node2 rest2)
(,descent-parser-name (token-next rest))
(setf node (make-ast-node :kind ,(cdr symbol)
:lhs node
:rhs node2))
(setf rest rest2))))
(t
(return-from ,parser-name
(values node rest)))))))))
So what is happening here:
First I define new symbols to the package that I will use inside the macro.
This is done with the intern
function
.
When defining macros in Lisp, you often see code that is inside a backquote
(`), this signals that every expression inside that is not preceded by a
comma is to be quoted. So above you can see some places where there is comma
in front of some expressions, those will be evaluated when the macro is run.
- For example, if
parser-name
equals to parse-example-node
then `(defun ,parser-name ())
would evaluate to (defun parse-example-node ())
.
Last crucial piece in the macro is the way I build the conditional for the
parsing itself.
Essentially how I do this is that I build a list of backquoted
expressions like:
((string= (token-val rest) "<")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node (make-ast-node :kind :lesser-than :lhs node :rhs node2))
(setf rest rest2)))
Based on all the comparison symbols are given in to macro.
The collected list is inside ,@
which basically means that evaluate the
following expression (,) and splat the containing list (@). So if
some-list
equals to (1 2 3)
, then `(fn ,@some-list)
would equal to
(fn 1 2 3)
.
Now when the macro is defined, I can just define the parser rules in a
following manner:
(define-parser equality
:descent-parser relational
:comparison-symbols (("==" . :equal)
("!=" . :not-equal))
:bnf "equality-node ::== relational-node ( '==' relational-node | '!=' relational-node ) *")
(define-parser relational
:descent-parser add
:comparison-symbols (("<" . :lesser-than)
("<=" . :lesser-or-equal)
(">" . :greater-than)
(">=" . :greater-or-equal))
:bnf "relational-node ::== add ( '<' add | '<=' add | '>' add | '>=' add ) *")
(define-parser add
:descent-parser multiplicative
:comparison-symbols (("+" . :add)
("-" . :sub))
:bnf "add-node ::== multiplicative-node ( '+' multiplicative-node | '-' multiplicative-node ) *")
(define-parser multiplicative
:descent-parser unary
:comparison-symbols (("*" . :mul)
("/" . :div))
:bnf "multiplicative-node ::== unary-node ( '*' unary-node | '/' unary-node ) *")
To see what those macros expand to you can just run macroexpand
on them, for
example:
(define-parser relational
:descent-parser add
:comparison-symbols (("<" . :lesser-than)
("<=" . :lesser-or-equal)
(">" . :greater-than)
(">=" . :greater-or-equal))
:bnf "relational-node ::== add ( '<' add | '<=' add | '>' add | '>=' add ) *")
Expands to:
(defun parse-relational-node (tok)
"relational-node ::== add ( '<' add | '<=' add | '>' add | '>=' add ) *"
(multiple-value-bind (node rest)
(parse-add-node tok)
(loop
(cond
((string= (token-val rest) "<")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node (make-ast-node :kind :lesser-than :lhs node :rhs node2))
(setf rest rest2)))
((string= (token-val rest) "<=")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node
(make-ast-node :kind :lesser-or-equal :lhs node :rhs node2))
(setf rest rest2)))
((string= (token-val rest) ">")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node (make-ast-node :kind :greater-than :lhs node :rhs node2))
(setf rest rest2)))
((string= (token-val rest) ">=")
(multiple-value-bind (node2 rest2)
(parse-add-node (token-next rest))
(setf node
(make-ast-node :kind :greater-or-equal :lhs node :rhs node2))
(setf rest rest2)))
(t (return-from parse-relational-node (values node rest)))))))
Cool, seems to be identical to the earlier definition that I had. So now when
I need to add new parser rules, I can just utilize this macro to do them,
saving me of writing unnecessary boilerplate. I probably am not able to use
this macro for all the definitions. For example currently the topmost parser
rule is defined in a following manner:
(defun parse-expression-node (tok)
"expression-node ::== equality"
(parse-equality-node tok))
So it doesn’t really make sense to use that macro for defining something like
that. Similarly, unary and primary nodes are defined in a slightly different
manner currently:
(defun parse-unary-node (tok)
"unary-node ::== ( '+' | '-' ) unary | primary-node"
(cond ((string= (token-val tok) "+")
(parse-unary-node (token-next tok)))
((string= (token-val tok) "-")
(multiple-value-bind (node rest)
(parse-unary-node (token-next tok))
(values (make-ast-node :kind :neg :lhs node)
rest)))
(t
(parse-primary-node tok))))
(defun parse-primary-node (tok)
"primary-node ::== '(' expression-node ')' | number"
(cond ((eq (token-kind tok) :num)
(values (make-ast-node :kind :number :val (token-val tok))
(token-next tok)))
((string= (token-val tok) "(")
(multiple-value-bind (node rest)
(parse-expression-node (token-next tok))
(values node (token-next (skip-to-token ")" rest)))))
(t (error 'parser-error))))
Which I could make it so that the macro above would define these kind of
parser rules if e.g. some special key is given in, but for now, I’m completely
fine by defining these by hand.
Posted on 1st of October 2023
| 369 wordsDuring September I seemed to spend quite a bit of time by reading books about
addiction due to personal reasons.
Judtih Grisel: Never Enough
Grisel’s book focused mainly on how different substances work and how they
cause addictions offering wonderful knowledge about the drug use and the
development of human brain. Great book!
Gabor Maté: In the Realm of Hungry Ghost
Maté’s book approached addiction from the point of view of trying to answer
why people become addicts. One of the most common factors between hard
addicts seems to be, according to Maté, some form of trauma that causes them
to seek chemical satisfaction from various substances. Book also raises a
great point that addiction is really a spectrum. Everyone of us lies in some
place in this spectrum.
Dr. Tom O. Bryan: You Can Fix Your Brain
While fixing somebody’s brain is definitely a hard task, it is not
impossible. Bryan raises a point in this book that there is no silver-bullet
for fixing your brain, but it is possible with small wins in multiple small
areas. He calls these four faces of brain health pyramid, which are
structure, mindset, biochemistry and electromagnetism, with what you can
design a protocol for yourself.
Herman Hesse: Siddhartha (reread, but this time in German)
I’ve been tremendously interested in Buddhism ever since I was a teenager
and I would consider myself being a practicing Buddhist. I have decided to
start taking this practice more and more serious to try to fix somethings in
my life. Siddhartha Gautama’s story is obviously a crucial part of the whole
thing and Hesse’s book is a great novel for painting a picture of this. I’ve
read this book earlier but in Finnish and English. Since last year I moved
to Germany, I’ve been practicing my German and, at the same time, I’ve never
been a huge fan of translations in books since I always feel that something
always gets lost during the translation. So to improve my German I decided
to read this book in its original language, German! While I’m very familiar
with the story, from reading this book earlier but also from stuff like Pali
canon, it’s still one of my favorite books!
Posted on 24th of September 2023
| 274 wordsSoo… Baldur’s Gate 3 was finally released after many years in open beta, and
I have to be honest, it really made me forget pretty much any other project I
had going on and just focus on playing it. Yesterday, I was finally able to
finish the game after over 100 hours, and all I can say is that it truly was a
great experience!
At one point in time, I played quite a bit of video games, but then I lost
interest in playing them. Well, losing interest is maybe the wrong word, since
I was still interested in what was happening in the gaming world, but I just
followed it from afar without spending countless hours in those games.
Baldur’s Gate 3 really sparked this old fire again since it had many things
going on in it. I loved the old Baldur’s Gates, and at the same time, many
Dungeons and Dragons campaigns with friends hold a dear place in my heart, and
naturally, Baldur’s Gate 3 combined those two in a truly remarkable fashion.
So I just wanted to write this small appreciation post to Larian Studios. Yes,
the game had some minor bugs here and there, but nothing game-breaking (at
least in my experience), but it was an absolutely amazing sequel to one of my
favorite gaming series while respecting the legacy of D&D. I doubt that I will
start consuming other video games endlessly like I used to, but nonetheless,
Baldur’s Gate 3 was an amazing experience, and I’m glad I spent many, many
hours in it.
Now, when the game is finished, I can finally return to hacking.
Posted on 5th of September 2023
| 661 wordsSummer months went by fast when you had lot on your hands. Didn’t feel like
keeping the reading log up to date during these months, so I’ll just do one
big post-summer update here.
Aldous Huxley: Brave New World (reread)
On May, I seemed to be rereading bunch of classics especially with the
common theme of dystopian future. Why you might ask? That I don’t know,
maybe something inside me just thinks that future depicted in these classics
is inevitable. Brave New World is probably one of my favorite books ever
written. Wonderful vision of advanced utopia, but at what cost? Masterful
critique of the dehumanizing effects of a highly controlled and
pleasure-driven society challenges readers to reflect on the consequences of
sacrificing personal freedom for comfort and conformity.
George Orwell: 1984 (reread)
Continuing on the series of dystopia and nightmarish tales of possible
future. Tale about the dangers of totalitarianism and government
surveillance. Serves as a stark reminder of the importance of safeguarding
individual freedoms, critical thinking, and truth itself.
William Golding: Lord of the Flies (reread)
More classics! Compelling exploration of human nature and the thin veneer of
civilization that separates order from chaos.
J.D. Sallinger: The Catcher in the Rye
The Catcher in the Rye was, one of many, classics that I hadn’t read before
and to be honest, wasn’t a huge fan of it. Maybe since I read this as a
little bit older. Don’t know. Topics in this book was really interesting,
considering teenager alienation, identity etc. While Holden’s struggles in
his adolescent were definitely unique, I just felt more annoyed about him
that anything else.
Jacques Ellul: The Technological Society
Jacques Ellul: Propaganda: The Formation of Men’s Attitudes
Ted Kaczynski: Industrial Society and Its Future
Ted Kaczynski: Anti-Tech Revolution: Why and How
Every once in a while my inner luddite wakes up and I start hating
everything about technology. Reading Jacques Ellul was definitely part of
this, but this time it was mainly the death of Unabomber, Ted Kaczynski,
that brought me to him. While I don’t agree/support on what Ted Kaczynski
did, he had some great points about how technology affects us. Ellul was
many ways inspiration for him in these sort of anti-technology philosophies
and it affection on humans. But Kaczynski and Ellul had one big difference
between them, Ellul was a pacifist were as Kaczynski was a domestic
terrorist.
Nonetheless, all of these books make some great points about technology so
despite your opinion about it, these are definitely worth a read.
Cormac McCarthy: The Road
Cormac McCarthy: No Country for Old Men
During the summer unfortunately we had a couple of passings of great
authors, one of which were Cormac McCarthy. I had never read his books
before, but I was familiar with as a movie from (No Country for Old Men by
Coen Brothers) and I had heard great things about his writing. So I grabbed
a copy of The Road and No Country for Old Men, since those were quite highly
recommended. And the recommendations were definitely true.
The Road offers a haunting depiction of post-apocalyptic America and the
struggles of father and son in this world. Immersing in bleak landscape
where hope and love endure against all odds. No Country for Old Men delves
into the realms of crime, fate, and the inexorable consequences of one’s
choices.
Both of these works showcase McCarthy’s masterful storytelling, unique
narrative styles, and philosophical depth, making them essential reads for
those interested in literature that explores the human condition in its most
challenging and thought-provoking forms.
Richard P. Gabriel: Patterns of Software
Richard P. Gabriel is a pretty known name in the software world and
especially in the Lisp world. One of the famous writings of Richard P.
Gabriel is the concept of “Worse Is
Better”
.
Patterns of Software gives a great look into software design, programming
and business around it. Definitely a must read for everyone working in this
industry.