Faster-than-Light memes 2023-03-19T19:06:24+00:00 https://faster-than-light-memes.xyz/ Benjamin Schwerdtner https://faster-than-light-memes.xyz/anonymous-commands-in-emacs.html anonymous-commands-in-emacs 2022-09-23T23:59:59+00:00 anonymous-commands-in-emacs

:faster-than-light /memes

anonymous-commands-in-emacs

Introduction

Generally, you do not want to make keybindings to anonymous lambdas. Here is the primary reason that comes to mind:

(describe-keymap
 (let ((m (make-sparse-keymap)))
   (define-key m (kbd "f") (lambda () (interactive) 'hi))
   m))

I get help buffer with this content:

Key             Binding
f		[closure]

It is not really useful to just get the info [closure] here.

add-hook

The same thing goes for add-hook. From the doc string:

FUNCTION may be any valid function, but it's recommended to use a function symbol and not a lambda form. Using a symbol will ensure that the function is not re-added if the function is edited, and using lambda forms may also have a negative performance impact when running `add-hook' and `remove-hook'

Some of the hooks functionality is meant for symbols.

Solution

Alias your function:

(defalias 'foo-a (lambda () (interactive) 'hi))
 (describe-keymap
  (let ((m (make-sparse-keymap)))
    (define-key m (kbd "f") 'foo-a)
    (define-key m (kbd "b") (defalias 'foo-b (lambda () (interactive) 'hi2)))
   m))
Key             Binding
b		foo-b
f		foo-a

Foo-b works because defalias returns the symbol.

defun

(defalias 'foo (lambda () (interactive)))

is essentially the same as

(defun foo () (interactive))

Result

I end up just using defun inline. Examples:

(add-hook
 'sh-mode-hook
 (defun mm/add-bash-completion () ...))
(mememacs/leader-def
  "pP" (defun mm/project-switch-project-find-file ()
         (interactive) ...))

After writing this post, I went and fixed the remaining add-hook lambas In my config.

Date: 2022-09-23 Fri 18:59

]]>
https://faster-than-light-memes.xyz/scittle-prints-itself.html scittle-prints-itself 2022-09-26T23:59:59+00:00 scittle-prints-itself

:faster-than-light /memes

scittle-prints-itself

Description of the crafting of a website. Up here.

Introduction

I was wondering about what is cool for a newcomer to coding. I love lisp and I think one of the real joys in programming is interactive programming. So if I find some way of communicating this magic, that would be great.

After my binaural beats adventure I feel like Scittle is an amazing tool so I want to try it on something bigger. So I had this idea of a Scittle website that prints its source code, then you update the code and get an immediate effect.

I wanted this to be my website so maybe a new team member can also go into the code and hack around.

Problem statement

  1. print your source code
  2. ability to update code
  3. no code editor in the browser (input field…) I am thinking getting this approximately non-clunky would be hard. Especially balancing the parens. I decided to go with a drag and drop area where you slurp in a file into the browser.
  4. This is not a Quine because it receives the source code as input

Some reagent code

I do some StackOverflow-driven development for a drag-and-drop area.

I needed to figure out how ondragover Event and friends translate with hiccup. Luckily the legendary question answerer @p-himik helped me out in the #clojurescript slack channel. Turns out that when I add :on-drag-over in the attribute map it works.

(ns main
  (:require
   [reagent.core :as r]
   [reagent.dom :as rdom]))

(defonce state (r/atom {:code-text ""}))

(defn drop-area []
  [:div#drop-area
   {:style {:margin-top "1rem"
            :height "10rem"
            :width "10rem"
            :background "Aquamarine"}
    :on-drag-enter
    (fn [event]
      (set! (.. (js/document.getElementById "drop-area") -style -background) "cyan"))
    :on-drag-exit
    (fn [event]
      (set! (.. (js/document.getElementById "drop-area") -style -background) "Aquamarine"))
    :on-drag-over
    (fn [event]
      (doto
          event
          .stopPropagation
         .preventDefault)
      (set! (.. event -dataTransfer -dropEffect) "copy"))
    :on-drop (fn [event]
      (doto
          event
          .stopPropagation
          .preventDefault)
      (let [file (->  (.. event -dataTransfer -files) first)]
        (->
         (.text file)
         (.then
          (fn [t] (swap! state assoc :code-text t)))))
      (set! (.. (js/document.getElementById "drop-area") -style -background) "Aquamarine"))}
   [:div
    {:style {:margin "1rem"
             :padding-top "2.5rem"}}
    "drop a file here"]])

(defn code-snippet []
  [:div
   {:style {:background "gainsboro"}}
   (:code-text @state)])

(defn my-component []
  [:div
   [drop-area]
   [code-snippet]])

(rdom/render [my-component] (.getElementById js/document "app"))

(comment
  (swap! state assoc :code-text "foi110"))

With this, I have a drop area for a file.

Wonderful thing: Updating state redraws the UI for us.

Evaluating (swap! state assoc :code-text "foi110") makes reagent 's magic take effect.

Fetch

I also want to show the default code on the first load. After some StackOverflow research, I determine fetch should work.

(->
 (js/fetch "main.cljs")
 (.then (fn [x] (.text x)))
 (.then (fn [x] (swap! state assoc :code-text x))))

Pretty print the code..?

At this point my website looks like this:

VU5LqMM.png

Figure 1: Halfway there. Sort of printing the source code now.

I want to do something where at least the white space is rendered.

After searching the web, I decide I need a <pre> tag to say it is preformatted. Also <code> sounds great.

(defn code-snippet []
  [:div
   {:style {:background "gainsboro"}}
   [:pre
    [:code
     (:code-text @state)]]])

Update the function, re-eval the rdom/render form. Boom I instantly look at my updated visuals. With cider, I can also call cider-eval-buffer, or cider-eval-file. I first had the background style inside the code tag, which did not have the look I wanted. I can hack on a piece of UI in isolation. Directly. Without any mental suspension time. It is great. It is how all coding should be.

Eval string

Now for the magic of updating the website with whatever you upload. First, I ask Borkdude on slack how to evaluate a string. -> You use load-string.

(load-string
 (prn-str '(js/console.log "hello")))

Says hello in the console.

I update my file drop handler with the side effect of loading the text:

(fn [t]
 (load-string l)
 (swap! state assoc :code-text t))

(Yes there is a syntax error in this snippet).

I add this to the bottom of the file to see if my code is evaluated:

(js/console.log "hello2")

Now loading silently fails when I upload my file, but the text updates.

So I evaluate this in isolation:

(load-string (@state :code-text))

Ah, I get an analyzer error about l not being defined or something.

I update my handler like this:

(try
 (load-string t)
 (swap! state assoc :code-text t)
 (catch js/Error _ (js/alert "That code does not work.")))

following Stew Halloway's example of binary error feedback. Either there is an error, or there is no error. Error messages are just bloat anyway.

console says:

hello2

Another piece in place, another hit of dopamine, wonderful coding moments.

Only fetch once

I update the fetch code like so:

(or
 (:code-text @state)
 (->
  (js/fetch "main.cljs")
  (.then (fn [x] (.text x)))
  (.then (fn [x] (swap! state assoc :code-text x)))))

I can do this because in Clojure everything is an expression and I can put expressions anywhere.

Make a big aquamarine rectangle into a small magenta rectangle

I want something on the eyes so I change the style of the drop area:

{:margin-top "1rem"
 :height "5rem"
 :width "5rem"
 :background "magenta"}

Drag and drop, and:

IUrSY7t.png

Figure 2: Visuals updated via dragging and dropping a source file.

In emacs: list-colors-display, nice. And drag and drop with dragon.

This contraption of course pales in comparison to having a REPL running. But the idea is that it is might useful to somebody that doesn't even know what a REPL is. And if you are a beginner and now you wonder what that REPL thing is. Here I try to make a list of how to get a dev setup.

Here is an idea I had and did not put into the initial version: Make an undo button. So that the user can go back in the history of the website

Codepen

An arguably more mature version of this is up on codepen.

A key difference is that my website prints its whole code. No machinery is hidden anywhere.

If I may say so I think this is cute.

Date: 2022-09-26 Mon 13:21

]]>
https://faster-than-light-memes.xyz/small-and-friendly-errors-with-cider.html Small and Friendly Errors with Cider 2023-02-05T23:59:59+00:00 Small and Friendly Errors with Cider

:faster-than-light /memes

Small and Friendly Errors with Cider

Growing by removing is growing stronger.

Less obtrusive Cider errors for a quicker repl-driven experience and practice. How I came to like error overlays.

1gxO1dN.jpg

Figure 1: A rose plant growing, the sun and speed of light. The idea of a computer.

The Quick-Eval

Repl-driven development is a philosophy and practice that focuses on using a REPL (Read-Eval-Print Loop) to interactively evaluate code snippets and see their results immediately.

The key is the whole language is always there and being able to make small experiments to the point where it meshes with your thinking.1

A big part of the practice of Repl-driven development is something I am calling the Quick-Eval flow for this blog post.

  1. Modify source code sexp
  2. eval
  3. Repeat

I want to optimize this practice. The speed of 1-2-3 can easily go below 5 seconds and everything is possible here.

  1. By honing lispy2 skills and juggling those sexps.
  2. By smoothing out the edges of cider-eval.

This aspect of Repl-driven development, the Quick-Eval involves using the mind, the fingers, and the editor. It's like playing an instrument or learning a motor skill like juggling - it requires dedication and repetition to master the movements. But the beauty of this practice lies in the ability to customize the tool to fit your thought process, unlocking the limitless potential for effectiveness. Knowledge of the editor becomes a key to a world of endless detail, where you can continuously optimize speed, the expressivity of intent and precision. The goal then becomes programming at the speed of thought, making structural editing a superpower of the Clojure programming language. And with the power to shape Emacs into what you desire, the possibilities are truly endless.

Speed cubers deconstruct the minutia for their finger tricks. This means being explicit and thoughtful about what movements to do during the performance.

This blog post is about an aspect of 2, smoothing out cider-eval, by eliminating error popups.

Let it flow

The first time I saw a Clojure stack trace, I thought my computer is broken.3

(Ariel Alexa)

Alex Miller mentioned4 recently that Clojure error messages are designed to not include the stack trace by default.

A lot of these tools will automatically print the stack trace and the Clojure REPL never automatically prints stack traces […] It prints you like a 2 line error message. And you can ask for the stack trace if you want additional information. We intentionally don't show you that because usually most of that information is not useful to you.

Nice, sounds like less heavy error messages are something to try out!

Cider already has a minimalistic error feedback available:

(setq-default cider-show-error-buffer nil)

With this setting, we get a little overlay right next to our cursor when evaluating with error.

Xk7Lbc1.png

Figure 2: Emacs cider eval error overlay displaying a runtime error message

We achieve a more smoothed-out Quick-Eval flow.

The consistent presentation, regardless of the presence of errors, creates a smoother and more streamlined workflow. This helps keep the focus on the code and eliminates interruptions in the thought process.

My mind can stay in one place, focused on the code, without a wall of something was wrong disrupting my flow.

Sometimes you want to look at a stack trace

Ok *cider-error*, we can always stay friends.

I do not advocate throwing away the stack traces, at all. With REPL-driven development and Emacs we have the power to move fast, and decide to inspect the stack trace should we decide the info would be useful.

*e exists for inspecting stack traces. Also *cider-error* is still at our side, we still faithfully render our stack trace there.

A quick and precise pop lets us go to the error buffer when we decide to do so:

(defun mm/pop-cider-error ()
  (interactive)
  (if-let
      ((cider-error
        (get-buffer "*cider-error*")))
      (pop-to-buffer cider-error)
    (message
     "no cider error buffer")))

(define-key cider-mode-map (kbd "C-c E") #'mm/pop-cider-error)

There is also a cider buffer selection dispatch command:

(define-key cider-mode-map (kbd "C-c X") #'cider-selector)

cider-selector into x to bring up the error buffer.

Let's not jump to conclusions

With less auto-jumping, we move slowly and deliberately and call upon our tools when we decide to do so. In practice, this can mean we jump around at insane speed, but we do so controlled.

(setq-default cider-auto-jump-to-error nil)

Currently, if you interactively eval5 and you have a compile error, Cider jumps to the top of the file. This is because we do not track a file position during the eval and Clojure only sees a piece of string, not the file.

So the most important command, cider-eval, that I want to optimize for Quick-Eval, had a rough edge and now I smoothed it out.

Errors should be friendly

Who invented that errors are red and angry?

(set-face-attribute
 'cider-error-overlay-face
 nil
 :background "DarkGreen"
 :foreground "white")

Now I have these green and peaceful boxes that don't make my heart rate go up.

Errors are the normal, correct behavior of my program, certainly in the context of developing. Sometimes I even eval just to check that there is an error. This is what repl-driven development gives us. And it should not feel like doing something wrong.

Spartan feedback for load-file

Currently, if you load a file and there is an error, there will be little feedback. The lack of an eval result in the echo area is signaling an error.

The extreme: Just say Did not work

In Debugging with the Scientific Method, Stuart Halloway mentioned what I would be calling Red light, Green light error feedback. The system only indicates if something worked or not, but not what specifically went wrong.

A trick in emacs if you want text invisible is you set the foreground to the same color as the background:

(set-face-attribute
 'cider-error-overlay-face
 nil
 :background "DarkGreen"
 :foreground "DarkGreen")

P7cn70e.png

Figure 3: Emacs cider eval error overlay displayed as a full green block.

I was still seeing the error in the echo area. So I did a quick (setf debug-on-message "nothing") and found cider--display-interactive-eval-result calls message.

The visibility of the message is controlled by cider-use-overlays.

(setq-default cider-use-overlays t)

Lol, now errors are just green blocks and I do not see the error message anywhere. If that is better than getting the error message I cannot say yet.

Footnotes:

2

Or the pareidit-like editor capability of your choice

5

What I call interactive eval is cider-eval-last-sexp etc. As opposed to cider-load-file.

Date: 2023-02-05 Sun 10:50

]]>
https://faster-than-light-memes.xyz/intro-to-clojure.html intro-to-clojure 2022-09-12T23:59:59+00:00 intro-to-clojure

:faster-than-light /memes

intro-to-clojure

Introduction

Clojure is a modern, functional lisp with a fiercely convinced community and production orientation.

Start

I highly recommend Maria.Cloud, you can just go there and start coding. This is great for anybody that does not know yet x

A dev environment

Get prepared for your journey as a pilot of an alien spaceship. As a beginner I suggest either

Vs Code

Easy to make work. A great editor. You will not need to be ashamed of your choice. calva for vscode

Emacs

Strong affinity to hacker culture and a program that is more than a tool, but eventually an extension to your hands, heart, and mind.

Here is a config file I tried to make for beginners: https://github.com/benjamin-asdf/simple-easy-emacs

A framework by clojurians that might be just right for you: https://github.com/corgi-emacs/corgi

There is also doom and spacemacs that enjoy wide appraisal for their "out of the box" experience.

Nr 1 book for beginners

Slack

Meet nice people that are excited about the tech on slack. Seriously a lot of people hang there and answer beginner questions, everybody is welcome.

Other such lists

Carin is cool and has a funny picture of the emacs learning curve here: https://howistart.org/posts/clojure/1/

I like that they have a philosophy section mentioning Rich Hickey's talks this matters a lot to clojurians.

https://thoughtbot.com/blog/tips-for-clojure-beginners https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f https://www.clojurenewbieguide.com/

Date: 2022-09-12 Mon 20:23

]]>
https://faster-than-light-memes.xyz/contact.html Contact 2023-03-01T23:59:59+00:00 Contact

:faster-than-light /memes

Contact

Contact me at

Benjamin.Schwerdtner@gmail.com

Or poke me @Benjamin.Schwerdtner on the Clojurian slack.

Date: 2023-03-01 Wed 12:38

]]>
https://faster-than-light-memes.xyz/dir-env-process-environment.html dir-env-process-environment 2022-10-17T23:59:59+00:00 dir-env-process-environment

:faster-than-light /memes

dir-env-process-environment

Introduction

Making shell commands is one of the great joys of emacs.

An advanced use case is that you want to set up a process environment for everything you do inside some project.

What I show here works for compile, shell-command, and even cider connections.

The setup

.dir-locals.el:

((nil
  .
  ((eval progn
         (make-local-variable 'process-environment)
         (setq process-environment
               (copy-sequence process-environment))
         (setenv "FOO" "hurr")))))

Yes, it is a bit convoluted but for a reason. We need to copy the list, else if somebody modifies the cdr locally, that would modify the global value. (In the case that FOO is an element in the list somewhere already).

The answer mentions setq-local. I tried that without success.

Shell-command and friends will inherit the process environmen. It pretty much just works.

From the project I currently work on:

((nil
  .
  ((eval progn
         (make-local-variable 'process-environment)
         (setq process-environment
               (copy-sequence process-environment))
         (setenv "AWS_PROFILE" "datalake-deployer")
         (setq-local cider-clojure-cli-aliases (concat cider-clojure-cli-aliases ":dev"))))))

Now I start cider connections with AWS_PROFILE set correctly. Also I have a babashka task for deploying that needs this env and it all just works.

Non-file-buffer

By default, .dir-locals.el does not apply to buffers without file names. (When the local variable buffer-file-name is not set).

There is a function hack-dir-local-variables-non-file-buffer for this purpose. This is called by dired, also magit.

I usually start processes from either a (source) file buffer or dired.

revert with grace

When you make a change to your .dir-locals, call revert-buffer in whatever buffer you want to have the effect. It hacks the local variables again for the buffer.

Date: 2022-10-17 Mon 09:56

]]>
https://faster-than-light-memes.xyz/resume.html Resume 2023-01-02T23:59:59+00:00 Resume

:faster-than-light /memes

Resume

Benjamin.Schwerdtner@gmail.com, LinkedIn, Github, Personal website, Contractor website

Summary:

Living and breathing Clojure and functional programming. Striving for a deep understanding of the philosophy of Clojure and Lisp. I have a particular focus on Clojure, Linux and Emacs. Experienced with unity, situated applications, CI scripts, tooling, and making open-source contributions. Fluent in English and German. Committed to delivering solid information systems and understanding the problem, iterating on the ideas, and communicating effectively as a programmer.

  • 2023-Present: Clojure Contractor
  • 2018-2023: Fulltime programmer at Singularity Group
  • 2014-2018: Studied biology at the University of Hohenheim (discontinued)
  • 2013-2014: Studied cognitive science at the University of Osnabrueck (discontinued)

Skills/Experience

  • 5 years experience in the software industry
  • Linux, AWS, .Net, Clojure + a variety of technologies and languages
  • Developed a mobile game with C# / Unity
    • UI, game logic, first experiences with shaders / GPU programming, Facebook integration, REST
    • Static code analysis (Roslyn), .Net live coding tool (Roslyn, Cecil)
    • Mentored junior team members
    • Occasionally worked with Postgress, DynamoDB, Golang and Typescript server side
  • DevOps, CI, Gitlab, AWS
    • docker, Linux containers
    • Configuration as code; Anything not in source control is waste.
  • Developer productivity, scripting
    • Committed to a smooth dev setup. For me and my team.
    • Linux shell, bash, babashka
    • Intellij plugin (Kotlin, Clojure)
  • Tools: git, Emacs, rider, vim, Jira
  • 3-4 years Lisp: Emacs Lisp, scripting, tools where ever I had the chance.
  • 1-2 years Clojure: discord bot and internal tools
    • Datomic cloud, AWS EC2
    • Tests and property-based testing
    • Repl into production for record speed bug fixes
    • AWS lambda with holy lambda and nbb
  • Website https://faster-than-light-memes.xyz/
  • Frontend:
  • Open source contributions to babashka, clj-kondo, nbb, cider, Emacs packages, etc.
  • Strong base knowledge of all major topics of biology and neuroscience
    • molecular biology lab experience, zoology, botany, genetics, cell biology, biochemistry, etc.
  • Self-taught
    • I learned to love textbooks. Some manuals have the same spirit.
    • A hard work ethic that allows me to spend hours learning.
    • Classic Rich Hickey talks, podcasts, Eric Normand, SICP, Paul Graham, etc.

Github:

Interests: Alternative programming paradigms, relational programming, chemical computing, conversational interfaces

Availability: Available for remote work. CET.

Location: Forst (Lausitz), Germany.

Languages: English: fluent, German: mother tongue. Latin: rudimentary

Recommendations: From my former colleague Milan: LinkedIn Recommendations

Date: 2023-01-02 Mon 11:50

]]>
https://faster-than-light-memes.xyz/mid-term-goals.html Mid-Term Goals 2022-11-17T23:59:59+00:00 Mid-Term Goals

:faster-than-light /memes

Mid-Term Goals

This is inspired by Hilbert's problems list.

This is a list of my current goals for moving humanity forward.

Some of these are easier than others. Being effective means finding the easy things that have leverage.

hgAYzqu.jpg

Figure 1: Solarpunk city with clear skies. Utopian high-tech future. Open spaces and trees. Flying buildings. Water.

Thinking big and what I think life is about

Why not think big? It's better than thinking small as far as I can see.

We are already influencing the long-term trajectory of civilization, regardless of whether we acknowledge it or not.

I say civilization is life. We currently have sciences that are largely defined by their methodologies and institutions with a different science for say organisms, computers and technology. You might then think that life is what biology studies, but it is not so true. Life is also ideas, artifacts, civilization and computers.

Life is the craziest thing in the universe and it just starting. And we have the opportunity to shape the next stage of life, civilization, and intelligence.

There are a few things that fall out of common sense in my opinion, invariants: Suffering and death are bad. Life is good. Progress is good because it allows for more life, creativity, beauty, harmony and joy.

  1. This was true in the distant past. It was true when we were Cambrian fish.
  2. What is true across the eons is likely to stay true in the coming eons.
  3. You really cannot know what amount of beauty and joy lies on the other side of progress. Nobody was foreseeing Bach or The Witcher 3 when the first primates started living in trees.

Mid-term I want to work on a solarpunk utopian future, biasing the outcomes towards human flourishing and ushering in the singularity1 quicker.

This is a future with many trees and clear skies. In cities full of innovative and harmonious people, gazing at the stars and building great things.

Techno Optimism

What is techno-optimism, chat gpt?

Techno-optimism is a worldview or attitude that technology can bring about positive outcomes and solving some of the world's most pressing problems. It is the belief that advances in technology will ultimately lead to a better world, and that technological progress will help humanity overcome many of its current challenges, such as poverty, disease, and environmental degradation.

Techno-optimists tend to be enthusiastic about emerging technologies, such as artificial intelligence, biotechnology, and renewable energy, and they see these technologies as powerful tools for solving social, economic, and environmental problems. They often believe that technology can enable greater productivity, efficiency, and innovation, and that it can ultimately lead to a more prosperous and sustainable society.

However, techno-optimism is not without its critics. Some argue that it can lead to an overreliance on technology and overlooking important social and ethical issues associated with technological progress. Others point out that technology can exacerbate existing inequalities and that it can also have unintended consequences that are difficult to anticipate.

chat gpt end

Those critics are not seeing the full picture. Maybe civilization optimism would be the better word anyway. Science, reason, and humanism are all part of the story.

The point is to understand how and why civilization and technology are useful for bringing about human flourishing and well-being. And to continue the already made advances. And to realize, historically, how precious our current situation is.

For the inequality thing. This is not at all how mobile phones, the internet and medical advances (penicillin anybody?) turn out to work. By the time technology works well and is cheap to make we can make it available to all humans. Humanism and progress give us the ethical framework to have equal opportunity etc. as a goal.

1. Solve Poverty

Why?

  • Obvious low-hanging fruit.
  • Enable huge productivity gains by allowing large populations to contribute to science, engineering, medical research etc.

How?

  • Make a lot of money and push projects.
  • UBI
  • Democratize2 goods
  • Democratize education
  • Democratize opportunities
  • Lower the costs of production for material + infrastructure, food and energy.

How do we know we make progress?

  • See Our world in data.
  • I have been working in this space for 5 years now and my current hope is to fix extreme poverty around 2030. (Which is a few years earlier than current projections last time I checked).

2. Solve longevity

  • Fix aging
  • Fix other diseases

This means you get an indefinite biological substrate lifespan. This might be rather low-hanging fruit, see Livespan with Dr. David Sinclair. Consider that fixing aging fixes a lot of diseases at the same time. Being biologically young means you fend off diseases.

Also, the same kind of advances fixes autoimmune diseases, Alzheimer, and cancer. See also the work of Aubrey de Grey for intelligent reasoning on this.

How do we know we make progress?

  • When you know your biological age the same way you know your weight.
  • When a head of state pronounces Not a minute longer dying from old age.

3. Solve energy

Why?

  • Energy consumption is linked to affluence.
  • Unlimited or virtually unlimited energy unlocks insane infrastructure and productivity perks
  • Be able to pull CO2 from the air3.
  • Water treatment plants etc4.
  • You only need enough energy so there is always some there the moment you look.
  • Kardashev Scale. The advancement of the civ.

How?

  • Industrial scale fusion, a SpaceX for fusion Lex Friedman + Dennis Whyte.
  • A green manhattan project (Yuval Noah Harari has mentionend this).
  • Fission? 5
  • Per definition, renewables, since we play a long game.
  • When it comes to getting rid of gas and coal you have to acknowledge keeping civilization running is a goal.

How do we know we make progress?

  • When we put industrial viable fusion energy on the grid.
  • When you pay a flat rate for your electricity bill.
  • When electricity is provided as a public good, in affluent countries.

4. Fix software (Rant)

Seriously, most web and mobile software only works so-so nowadays because of bloated software. Everything is bigger and more complicated than it needs to be. Reloading some app because it stops working is the norm. This garbage is not acceptable in my vision of the future.

Software is supposed to be focused, effective and competent.

The price we pay right now for bloated and uninspired software is insanely high. How many mental energy hours go into reloading some app that stops responding6? Seriously, this is a global humanitarian issue.

Another issue is something I call mind-suck software now. This is software that is highly designed and explicitly or implicitly informed by behavioral psychology. To draw our attention and suck our time. When I click on an app with a blue icon because it has a red dot in the corner, that is not merely my fault, not only my lack of self restrain. That is also the fault of the people that made this software in the first place. This is an ethical issue. Long term I hope we understand which kind of software is conducive to our well-being and which is sucking our minds. 7 Mind-suck software belongs in the trashbin of history.

Existing software that lets me feel the competence of the computer is Unix/Linux, FOSS tools, Git, Emacs, and non-bloated parts of the web like Wikipedia. We can do it right.

The phone is a completely opaque object to me, with virtually no power to reach into it and make it do what I want it to do. Instead, I need to hope app vendors come up with something I find useful.

One of my fears currently is that BCIs will inherit from the current mobile model of software delivery. I think this would delay the singularity by multiple years.

The issues are uninspired practices and a disregard for the wisdom of the early days of computing. Also, the focus on financial incentives breeds less ambitious projects.8

Also, if it is FOSS, it tends to become small and focused, if it is proprietory, it tends to become large and bloated.

All user interfaces could be more like Data Rabbit right now. Think of the difference in productivity across the whole world. People would not fight computers anymore but wield great tools of thinking.

How?

  • FOSS
  • Reinvent the heyday of Lisp and Smalltalk interactive systems. These were made by people for people that build systems.
  • Ideas from Bret Victor, Rich Hickey, Jack Rusher and others.
  • It will be easier when we have more abundance and the incentives don't need to be primarily financial anymore.
  • I choose Clojure. The community has an emphasis on thoughtfulness about how to make good software. It is a Lisp with a focus on interactivity, and raw power through succinctness. Great polymorphism constructs. A strong concurrency model and reach by being hosted on JVM and javascript. In short: A language for humans by humans for building effective information systems.

How do we know we make progress?

  • When you can change what a button does on your phone.
  • When syncing data between 2 programs on mobile is not an advanced operation.

5. Higher tech

For obvious reasons, any of those can help fix things on this list:

  • AI, information technology, automation.
  • Better computer interfaces (conversational, … ).
  • Nanotech, material science.
  • Biotech, BCIs, genetics.
  • A science and engineering of processes, policy and government 9.
  • Also infrastructure, networks10, internet connection, water and goods.

How do we know we make progress?

  • When a computer asks you back about an edge case you have not thought about while explaining your task to it.
  • When you don't buy toothbrushes at the store anymore because you have a matter compiler or printer or nano factory.

The special effectiveness of AI

Say intelligence is the ability to achieve complex goals. If we have that in computers the same way we have chess computers, it is an instant global win condition. A general AI could solve the things on this list, including making better AI. Which would further increase its capability of fixing the things on this list.

6. Solve food

  • Cheap, tasty, clean meat.
  • Just higher-tech food production.
  • Plants. Better plants. More effective plants. And plant-growing buildings.

7. Preserve biodervisity and ecosystems

Why?

  • Organismic life has an intrinsic value to it.
  • In a medium-long-term situation where energy, material and compute are abundant, maybe 11, the information you get from gene sequences and analyzing ecosystems are the most valuable thing there is.

How?

  • Relatively hard.
  • Fixed by 3, 8 and 9, which you in turn push best forward by increasing affluence.

How do we know we make progress?

  • When the extinction of any species is a global tragedy.

8. Solve government and policy

Why is governmenting not more like engineering? Anyway, it is an unsolved problem for obvious reasons:

  • lack of UBI, poverty
  • lack of decisive climate safety action
  • lack of world peace
  • noise pollution
  • users citizens need to bother with paperwork, tax stuff is not automated.

How?

I don't know what to do mid-term except try to push affluence globally. Higher affluence correlates with a more reasoned government generally (See the Nordics). This way I would generally bias for more desirable outcomes.

Outcomes

The moment we have super-intelligent AI, we get one of multiple possible outcomes, with either a group of people controlling an AI making the decisions or an AI making the decisions. If you are skeptical about this statement, try to play a party of chess against a chess computer12.

How do we know we make progress?

  • Everybody's education level goes as high as possible. I believe that means everybody can achieve a Ph.D.-level education at minimum.
  • UBI.
  • Explicit policies against noise pollution 13.

9. Develop more far-sighted incentives14

Why?

Companies are arguably the most competent actors in the world right now.

The fact that Starlink is the entity that fixes the internet in Ukraine right now and not a government is showcasing this for me.

What does not fit in my solarpunk future yet is that companies are currently maximizing money, instead of human flourishing.

How?

In the mid-term, by pushing forward easier things on this list. Bring about abundance and rational decision-making.

Another idea is to make tons of money and become a powerful corporate entity yourself. (This counts for anything on this list).

Create enough abundance so money is not the driver anymore. This is called Post Scarcity and I think reality looks like this would work. Aka more affluence leads to more attention on human flourishing.

How to know if we made progress?

  • Corporate entities are explicitly pushing to solve other issues on this list.
  • A corporate entity fixes infrastructure in a region of war (Oh, we are making progress!)

10. Solve immortality

For starters something like mind-uploading. Where you have a mind backup inside a fault-tolerant system.

Medium-long-term we need to make sure earth is safe from meteors and gamma rays. Goes into super long-term. By becoming a civilization after the stars are gone, and surviving the death of the universe, a civ might ultimately decide the fate of the universe.

How to know if we make progress?

  • When the death of a single person is a global tragedy.
  • When you don't tell children about the history of death until they are old enough to stand it.
  • When Misery was

Reading

  • The Singularity is Near Ray Kurzweil It is a truly seminal book. It makes you appreciate exponential processes and then it maps that to computers and biotechnology. Making you see the logic of how fast technology is growing crazy powerful and tiny.
  • Yuval Noah Harari, together with Pinker and others an eminent thinker and proponent of civilization optimism.
  • Steven Pinker Enlightenment: Now The Case for Reason, Science, Humanism, and Progress
  • Jared Diamond Guns, Germs, and Steel. An eye-opening book about large-scale, big-picture thinking. How civilizations form. Science fiction without being science fiction. It tells you everything could be different.
  • David Deutsch The Beginning of Infinity: Explanations That Transform the World Big history, big ideas. Connects scientific inquiry with how evolution works. Explains the power of good ideas, talks about beauty, ethics, the fate of the universe and all that with a red thread going through it. Perspective-creating. A continuation of The Selfish Gene in some ways.
  • Engines of Creation: The Coming Era of Nanotechnology K. Eric Drexler. Drexler calmly and matter-of-factly explains how you can have a machine the size of a garage printing a car. The only thing needed is some advances in material science, no new physics is required.
  • If you enjoy thinking about possible outcomes regarding AI, Max Tegmark, Life 3.0/. If you read nothing else from the book, the first chapter describing the fictional near-future secret group called the /Omegas is extremely thought-provoking. This is the idea of a small group of individuals controlling a super-intelligent AI, taking over the world and biasing for human flourishing.
  • Superintelligence: Science or Fiction? | Elon Musk & Other Great Minds
  • I don't fully know why but Richard Dawkins The Selfish Gene is more than an just eye-opener about how evolution works it is also an eye-opener about the power of thinking and common sense.
  • David Sinclair on fixing aging https://www.lifespanpodcast.com/
  • Aubrey de Grey, very vocal about how we need to overcome deathism, the idea that death is something to accept.
  • Eliezer Yudkowsky has written about the ethics of progress, longevity and more. If anything in this post resonates with you and you have not read Harry Potter And The Methods of Rationality yet, seriously, I can advise doing that. I am not alone in saying this. The book covers topics on morality, fixing death, being a scientist, and the navigation problem of fixing the world.
  • Isaac Assimovs The Last Question is somehow a good meme about the big-picture.

Footnotes:

1

In terms of Ray Kurzweil. Techno utopian high tech outcomes that change the game completely.

2

With Democratize I mean make it available to everybody, without conditions. And as cheap as possible.

3

I have picked up this factoid from a Helion Energy blog post somewhere.

4

Chat gpt mentioned this when I asked what the perks of unlimited energy would be

6

I am not even thinking about windows users that are rebooting their PC. I can handle only so much brokenness in my mind right now.

7

Sam Harris has thought publically about this on multiple occasions: The price of distraction, Why I left Twitter

8

Alan Kay has talked about the dynamics of innovation and how you don't get this in the climate of short-sighted monetary goals

9

Already exists, of course, I am just too ignorant to even list the correct names.

10

I really enjoyed this talk by Dylan Beattie it kind of went to different concepts about networks and supply chains etc. He also mentioned Diamond Age style nanotech that would change the game of supply chains completely. He pointed out there might be a new logic to supply that would entail information and experiences, not goods.

11

I see multiple possible worlds in this regard. Depending on

  • A. How hard it is to fabricate evolutionary organismic wisdom.
  • B. How valuable evolutionary organismic wisdom is.

We could make some back-on-the-envelope reasoning about A, but B is completely unknown. We don't know the value of biodiversity and ecosystems yet and we should treat them as extremely valuable.

Also aesthetically, a solarpunk utopian civilization would value organismic life just for its intrinsic value.

12

That is from Max Tegmark, Life 3.0.

13

I am just taking noise pollution as an example where human well-being is not at the center of what we are doing with civilization yet.

The day we ban foliage blowers is the day we can rejoice, for we are on the way into our solarpunk utopia.

14

This idea is straight from Alan Kay. In one of his many appearances on youtube and podcasts.

Date: 2022-11-17 Thu 20:11

]]>
https://faster-than-light-memes.xyz/not-even-the-sky-is-the-limit.html not-even-the-sky-is-the-limit 2022-11-15T23:59:59+00:00 not-even-the-sky-is-the-limit

:faster-than-light /memes

not-even-the-sky-is-the-limit

Cold showers are a hello world for being determined.

Introduction

I have been practicing Wim Hof Method for years. It is a spiritual path of sorts.

There is this thing where you embrace being an animal, and animals are really hardcore man. Human animals plan, think and discover how to world works. The brain is the control hub of our inner physiology also. Getting in touch with your physiology is not mystical, and not reserved for a certain kind of person either. It is using the paths in your brain that evolved to do just that. 1

To close the loop: The inner physiology is another part of the world. With its mechanics, story and places that can be discovered - and mastered to various degrees. Such is the human way, you are the animal

  • uses thought
  • likes stories
  • makes sense of objects etc in the world

Where can you start? With the things you already have control over. Hence breathing techniques, stretching and cold exposure. Emphasize the in-breath over the out-breath and you are pumping adrenaline. The other way around and you get more relaxed. Cold exposure pumps dopamine, with a long arc. 2 It makes the whole day awesome. A cold shower is already an achievement that sets you up for performance. Wim has mentioned somewhere on the free part of his app something about self-determination and having "the cold as a teacher". An upsight clicked clicked in me that will try to share here.

One way to learn is to learn on a playground

There is a reason we make hello world programs. We learn in the small what is similar for the large.

Say Wim Hof is right and self-determination is a mental thing I can grab How do I learn to do so? Also importantly, how do you even know you are doing it? Enter cold showers ("The cold is our teacher"). It is hard to kill yourself with a cold shower, yet it takes mental energy to go into one and to stay. It gives you a chance to be determined in a small, controlled, safe environment. You manage to endure a wall of physical discomfort, you are doing it. This is what determination is.

just do it

In the lore of Wim-hoffing, you keep a calm mind and observe yourself being able to do it.

You are deploying the mental capacities that you might call determination.

The cold shower is the playground that allows you to see how it is to be determined. You observe the mentality, the mechanics, the feel, the drive, the just doing it. What you are when you are being determined. This then, shows you how to be determined elsewhere. The cold is not an end goal, it is a simple, easy playground where we can test how it is to be determined. This also means we have a benchmark for whether we are deploying determination, or not.

To learn something you need some way of telling whether you are doing it right.

I connect this to an experience I had while I was learning to juggle. There was a moment when I was doing 1 or 2 balls when I realized: here is a limit, a place where I can invest in training and I will get better and build a foundation and eventually be able to juggle. (I was right).

The only place where you can grow is at the edge.

Huberman

Professor Huberman is since recently one of the great science communicators of our time. About physiology, neuroscience and (my words) frankly, the human soul.

Transcript from a recent Q&A event (you can find it on the Huberman lab podcast feed):

If you want to get the most out of the cold exposure then you want to get to that point of "I want to get out of here, but I know I can stay in safely, but I really want to get out of here".

It's a little hard to explain, but there is just so much learning in those short moments about where your mind goes. And this sounds subjective and maybe a little whishy-washy. You can realize great things about yourself in those moments. You can find insight in those moments.

I agree. I call this learning how to be determined.

The practice

I can recommend the Wim hof app to get started. There is a diary thing where you start with 10-second cold showers after a warm shower etc.

Tip: if you have a dispatchable shower head, put it in your hand and move it around. Cold exposure is all about control. If you have the shower head in your hand, you gain control.

Footnotes:

1

One way to describe this is by having a set of inside jokes with the physiology driving parts of your brain. Using your own style.

2

Andrew Huberman has in recent times communicated beautifully about the the current science of cold exposure, breathing technique and stretching.

Date: 2022-11-15 Tue 19:20

]]>
https://faster-than-light-memes.xyz/pearls-of-introspection.html pearls-of-introspection 2022-11-12T23:59:59+00:00 pearls-of-introspection

:faster-than-light /memes

pearls-of-introspection

Recently, I watched BugsWriter falling in love with elisp 1 - he said about describe-mode

Why did nobody ever tell me about this?

This post is called Pearls of introspection.

All of Emacs is one bright pearl.

The describes

describe-mode

Lists all current keybinds in a buffer. Huge output, sometimes what you want.

describe-char

Emacs is a text editor, text is made up of chars. describe-char is useful if you want to know what face is rendering. It goes beyond that by showing string properties, overlays, and buttons. This can be useful for debugging.

Story: Once I deleted some packages on my system, then I go into emacs info and some of the text is not rendered right.

describe-char gave me the hint, the fixed-pitch face wanted "Monospace Serif" or some such but I only had Monospace.

So I did this and was happy ever after:

(set-face-attribute 'fixed-pitch nil  :family "Monospace")
(set-face-attribute 'fixed-pitch-serif nil  :family "Monospace")

Worth binding:

(define-key help-map (kbd "c") #'describe-char)

describe-key

"What does this key do?" - the answer is describe-key and hit the key.

describe-function

Emacs functions have amazing docstrings.

The help buffer has a keymap of its own, try ? to list keybinds.

Highlight: s to go to source.

describe-keymap

Probably faster than describe-mode, renders a keymap in a help buffer. Try describe-keymap -> help-map hehe.

prefix-help-command

You type ? after starting to type a prefix, then you get the binds.

embark-bindings

An alternative to the default ?, it is amazing. I get a vertico completing-read of the binds.

M-x describe-

There are more, some of them I never used. Emacs is vast like the ocean.

view-lossage

You accidentally hit some key, and something unexpected happens. view-lossage is your friend. It shows the last keys + commands.

It is like the morning-after pill version of describe-key.

story: I sometimes accidentally hit y before typing the text for an avy command.

Every time I was like "Holy cow whatever I hit there is powerful". 2

I didn't know about view-lossage. The thing is, it would not have helped, because avy is reading the key, then dispatching on the key. I guess it needs to go through the keymap system or something to show up in view-lossage.

apropos-value

This helps me about once per year.

It is extremely satisfying when you use this and it helps you. I once figured out about revert-buffer-function by using it.

You can revert shell-command buffers to rerun the command but I did not know by which principle.

apropos-value, then typing my shell command showed me there was a buffer-local variable called revert-buffer-function. It worked because Elisp closure objects print with their environment. In other words, the value of revert-buffer-function was a lambda that printed with my shell command. It is quite wild.

find-library

Read code, and do little experiments. I am not sure but I think there might be something profound about Elisp and emacs. I think the language is the program and the program is the language or something. Knowing the program is to know the language and knowing the language is to know the program. (Insert link to top Elisp functions blog post here).

where-is

I just discovered this via describe-keymap into help-map lol. This is like describe-key but you say the command and it says the keybinding.

Footnotes:

1

I thought lisp was going to be complicated but it is simple.

That is an interesting tension between outside perception and the actual language. Since you write the AST directly, you can say what you mean. The power of lisp is that the code is made of

  1. Ideas
  2. There is nothing else.
2

It makes the cursor stay and yank the target word. Hit ? before typing the keys for avy. The way it works is that avy can dispatch with different actions, the default is to jump to the location, but y for example yanks a word and makes your cursor stay where you are. It is really powerful. Ace-window has the same paradigm.

Date: 2022-11-12 Sat 16:02

]]>
https://faster-than-light-memes.xyz/aws-iam-and-cloudwatch-logs-start-query.html aws-iam-and-cloudwatch-logs-start-query 2022-11-30T23:59:59+00:00 aws-iam-and-cloudwatch-logs-start-query

:faster-than-light /memes

aws-iam-and-cloudwatch-logs-start-query

User with accountId: 123456791011 is not authorized to perform StartQuery

Example iam policy for querying cloudwatch logs (that one works):

  {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:StartQuery",
            "Resource": "arn:aws:logs:us-east-1:123456791011:log-group:hairy-log-group-name:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:GetQueryResults",
                "logs:StopQuery"
            ],
            "Resource": "*"
        }
    ]
}

The above error you get when you try the log-group arn without the `:*` at the end.

You need the `:*` behind the log-group for some reason, probably because the log-streams also participate in the resource permission thing or something.

This was kind of hard to figure out, no examples on the official websites and you think you do it right from reading the documentation.

Date: 2022-11-30 Wed 16:29

]]>
https://faster-than-light-memes.xyz/bashing-is-better-than-extending.html Bashing is better than extending 2022-09-22T23:59:59+00:00 Bashing is better than extending

:faster-than-light /memes

Bashing is better than extending

Not how to run babashka tasks.

How bash-completion makes everything better.

How to run any shell commands.

Technology around shell-command.

Simplicity and joy.

Introduction

Ok, let's just do it. You might want to hold tight to your chair because the juiciness and elegance of what follow might just blow you over. Here is how I build my blog with babashka tasks:

bb-task-demo.gif?raw=true

Figure 1: Using compile to leverage read-shell-command and thereby bash-completions. Recompiling via revert-buffer. Dismissing the *compilation* buffer.

You might think "Ok sure, looks useful." Let me entice you with the the really impressive thing about this:

There is nothing concrete about babashka tasks nor about that specific project in my emacs config. It just works by having a bb.edn with tasks.

Made possible via the harmony between some 3 or 4 general tools. Like layers of ice. You deserve some skates to ride on it. Smoothly, gracefully and fast. Here is the story of a happy little package called bash-completion.

read-shell-command

This is like read-from-minibuffer but sets some keymap and history. Hit <tab>, you get completions from shell-dynamic-complete-functions. Those completions are sort of okay, but they do not give you command-specific completions. Invoke shell-command, then type git checkout, hit tab. Nothing happens. Yet.

bash-completion

Ok your emacs life is about to level up +1 bash-completion. Config:

(use-package bash-completion
  :init (autoload
          'bash-completion-dynamic-complete
          "bash-completion"
          "BASH completion hook")
  (add-hook
   'shell-dynamic-complete-functions
   #'bash-completion-dynamic-complete))

Here are the completions of your shell at the tips of those sweet coconut oily fingers.

Now you can do shell-command -> Hit that tab while typing git checkout .. a door just opened.

bash completions are now your lever

We have entered the realm of harnessing already existing shell completions directly.

Babashka tasks

Babashka tasks are one of the great discoveries of our time, allowing us to write build tasks in Clojure, with the development ergonomics of a lisp.

The babashka book has a section on adding shell completions. Boom. This is all you need. Now you can enjoy those babashka tasks completions.

Commands that leverage read-shell-command

They use read-shell-command. Making read-shell-command good will pay off for all these.

shell-command

Bound to M-!

This is the interactive doorway into emacs lisp start-process functionality.

Here is a nugget:

With prefix argument, insert the COMMAND's output at point.

C-u M-! date and you have a date inserted in the buffer.

Like this: Thu Sep 29 10:55:44 AM CEST 2022

Good to know:

If COMMAND ends in &, execute it asynchronously.

Output buffer

Your command output is located by default in a buffer named by shell-command-buffer-name. Or shell-command-buffer-name-async when async.

shell-command-async

Bound to M-& and has the same effect as adding a & in shell-command. To kill the process I can hit C-c C-c.

compile

Very useful, very similar to shell-command-async. Always uses the same buffer called *compilation*. You can set compile-command for instance via .dir-locals.el, then it auto makes a compile command in that project.

dired

dired-do-shell-command and dired-do-async-shell-command are symetrical with shell-command and async-shell-command. Those functions call shell-command.

Bound to ! and & in dired Docstring is worth reading. Important to know is that * expands to dired-file-name-at-point, or the marked files, but is implicit as the last arg.

shell-command-on-file

Sometimes you are currently visiting a script file and you just want to run it.

(defun mm/shell-command-on-file (command)
  "Execute COMMAND asynchronously on the current file."
  (interactive (list (read-shell-command
                      (concat "Async shell command on " (buffer-name) ": "))))
  (let ((filename (if (equal major-mode 'dired-mode)
                      default-directory
                    (buffer-file-name))))
    (async-shell-command (concat command " " filename))))

Thanks to Gavin Freeborn for the initial version of this code.

It gets even better

Let me introduce you to the wonders of revert-buffer-function. Now, revert-buffer is a powerful command by itself.

I did not know this for a while, but you can set the local variable revert-buffer-function. This pearl is in emacs 28:

(setq-local
 revert-buffer-function
 (lambda (&rest _)
   (async-shell-command command buffer)))

You say revert-buffer in a shell command buffer, to boom run the command again in the same buffer. Exactly what I want sometimes. A single key to rerun a command. And I think the concepts just fit nicely. There is no mental burden with this.

revert-buffer in compilation buffers

(advice-add
   #'compilation-revert-buffer
   :filter-args
   (defun mm/always-noconfirm-compilation-revert-buffer (args)
     (pcase args
       (`(,ignore-auto nil) `(,ignore-auto t))
       (_ args))))

I use revert-buffer as a consenting adult - kill and restart the compile command, without asking.

Scripts at the speed of thought

insta-script.gif?raw=true

Figure 2: Make a script, and run the script. Leveraging bash-completion in shell-script-mode.

mememacs/create-script

(defun mememacs/create-script* (file bang setup)
  (find-file file)
  (insert bang)
  (save-buffer)
  (evil-insert-state)
  (set-file-modes file #o751)
  (funcall setup))

(defun mememacs/create-script (file)
  (interactive "Fnew script: ")
  (mememacs/create-script*
   file
   "#!/bin/sh\n"
   #'shell-script-mode))

(defun mememacs/create-bb-script (file)
  (interactive "Fnew bb: ")
  (mememacs/create-script*
   file
   "#!/usr/bin/env bb\n"
   #'clojure-mode))

I have bound these in dired-mode. Then, I use mm/shell-command-on-file to dev interactively sort of.

Btw shell-script-mode becomes a power house when you integrate shellcheck. flycheck has something for that. (pretty sure flymake should as well.) Shellcheck makes superb warnings. Firmly in my "adopt" circle.

bash-completion in sh-mode

Here is my full bash-completion config that adds to capf.

(use-package bash-completion
  :init
  (autoload 'bash-completion-dynamic-complete
    "bash-completion"
    "BASH completion hook")
  (add-hook 'shell-dynamic-complete-functions
            #'bash-completion-dynamic-complete)

  :config
  (defun bash-completion-capf-1 (bol)
    (bash-completion-dynamic-complete-nocomint (funcall bol) (point) t))
  (defun bash-completion-eshell-capf ()
    (bash-completion-capf-1 (lambda () (save-excursion (eshell-bol) (point)))))
  (defun bash-completion-capf ()
    (bash-completion-capf-1 #'point-at-bol))
  (add-hook
   'sh-mode-hook
   (defun mm/add-bash-completion ()
     (add-hook 'completion-at-point-functions #'bash-completion-capf nil t))))

Oh async-shell-command, my trusted friend

Of these commands, it is the one I use the most. The other commands could be performed in terms of it. Here is some of my journey smoothing out some edges.

Put the command into the buffer name

When you run a second command, by default, it tries to reuse the old buffer and asks you

(yes-or-no-p
 (format
  "A command is running in the default buffer.  %s? "
  action))

I put the command into the buffer name so I usually get a unique buffer name.

(defun mm/put-command-in-async-buff-name (f &rest args)
  (let* ((path-s (path-slug default-directory))
         (command (car args))
         (buffname (concat path-s " " command))
         (shell-command-buffer-name-async
          (format
           "*async-shell-command %s*"
           (string-trim
            (substring buffname 0 (min (length buffname) 50))))))
    (apply f args)))

(advice-add 'shell-command :around #'mm/put-command-in-async-buff-name)
(defun path-slug (dir)
    "Returns the initials of `dir`s path,
with the last part appended fully

Example:

(path-slug \"/foo/bar/hello\")
=> \"f/b/hello\" "
    (require 'dash)
    (let* ((path (replace-regexp-in-string "\\." "" dir))
           (path (split-string path "/" t))
           (path-s (mapconcat
                    (lambda (it)
                      (cl-subseq it 0 1))
                    (-drop-last 1 path)
                    "/"))
           (path-s (concat
                    path-s
                    "/"
                    (-last-item path))))
      path-s))

Now I can complete buffers and start typing the commands. And the buffers don't have an anonymous name like *async-shell-command<2>*.

shell-command–same-buffer-confirm

Sort of a power setting when you do async-shell-command a lot. Nowadays I do:

(setf async-shell-command-buffer 'new-buffer)

If I want to kill I can do C-c C-c on the old buffer.

shell-mode as a terminal emulator

(defun mm/shell-via-async-shell-command ()
    (switch-to-buffer
     (window-buffer
      (async-shell-command
       shell-file-name))))

You get a shell buffer running your shell. Does everything I need from a terminal. It pays of having a minimal .rc file. This is also why I have shell-file-name set to "/bin/bash". Even though I have a cool zsh config with vi mode. I get all emacs editing power in that shell buffer.

The next layer on the cake

More context for shell-command.

project

I use project.el. project-compile runs compile in the project root. Analogously, there is project-async-shell-command. projectile, a big and widely used package, provides similar commands.

recompile

Similar to going to the *compilation* buffer and revert-buffer. But a single command.

Ansi colors for comint

If you use Koacha together with compile, you will get output sprinkled with ANSI (color) escape codes.

Bit cluttering on the eyes.

I knew from earlier dabblings that there is a package called ansi-color. So I checked around on how to make my buffer colored nicely.

Turns out that comint already has ansi-color-compilation-filter setup by default. Checking the code for compile I see that with prefix arg, the buffer becomes a comint buffer. So I decided I always make my compile buffers comint buffers.

(advice-add
   'compile
   :filter-args
   (defun mm/always-use-comint-for-compile (args)
     `(,(car args) t)))

Koacha output looks like this:

5vpmnsu.png

Figure 3: A compile buffer running Koacha with pleasing green colored output text.

Levers are great

Ssh

Nice tip in case you did not know: You can define preset configs in ~/.ssh/config and they will show up as bash completions when you type ssh and hit tap.

Host dotomic-system-ec2
     HostName ...
     ...

So now I just type M-& for async-shell-command, then ssh, then I hit tap and I get dotomic-system-ec2 as completion. Yes!

Embarking

Through embark the power of completions is further amplified. For instance, I can complete git branches via git checkout completions.

embarking-git-branches.gif?raw=true

Figure 4: Abusing read-shell-command to dispatch with embark on git checkout completions. Invoking embark-insert as an example.

Pass

Another example. I used to use helm-pass for pass. Guess what, pass has great shell completions. I get a free interface to pass just with async-shell-command.

Particulars

shell-file-name

It matters. For instance, if you use "/bin/bash" and you set up your path in a zshrc that might be a pitfall. Another thing that happened to me was that keychain was prompting for my ssh password inside the bash-completion process, making it hang.

Troubleshoot

  1. can you start `bash` and have completions? (on arch, maybe you want to install bash-completion).

Date: 2022-09-22 Thu 12:32

]]>
https://faster-than-light-memes.xyz/extending-your-reach.html extending-your-reach 2023-01-01T23:59:59+00:00 extending-your-reach

:faster-than-light /memes

extending-your-reach

Introduction

Putting love into your setup will pay off.

When your mind becomes one with the computer. When it starts feeling like it is expanding your reach. This is where the computer as a tool starts unfolding its true potential.

MbnkaGg.jpeg

Figure 1: Linux user reaching into the computer, becoming one with the computer. In space. A tomato. A fork. The stars.

A real tool is part of your mind and body

The mind tracks the space around us that we can grasp and manipulate

I was recently learning a bit about peripersonal space and the connection to tool usage.

Our mind is tracking the space around us, importantly specifically the space we can interact with.

When this is broken via strokes or developmental issues, the person bumps into things and can not use tools well. 1

From the introduction of a paper on the topic:

Peripersonal space is the multisensory space immediately surrounding our body, or more specifically the sector of space that closely surrounds a certain body part (Rizzolatti et al., 1981, 1997). A crucial factor that distinguishes the perception of our immediate surroundings from that of more distant space is our potential ability to interact with (i.e., to reach and grasp, or to avoid) objects within peripersonal space. Electrophysiological studies in macaque monkeys suggest that multisensory peripersonal space is represented in body part-centered coordinate frames, within both subcortical structures (the putamen), and in cortical regions of the frontal and parietal lobes (Hyvärinen, 1981; Rizzolatti et al., 1981; Colby et al., 1993; Graziano and Gross, 1993)

One cool aspect of this is that our internal map of the space grows and shrinks with whatever tools you use.

From Maravita A, Iriki A (2004):

What happens in our brain when we use a tool to reach for a distant object? … research suggests that this extended motor capability is followed by changes in specific neural networks that hold an updated map of body shape and posture (the putative "Body Schema" of classical neurology). These changes are compatible with the notion of the inclusion of tools in the "Body Schema", as if our own effector (e.g. the hand) were elongated to the tip of the tool.

This is when you have a pen or fork in your hand and you can move it as if this was part of your body.

Similar: You drive a car and it is as if you take on the shape of the car.

Reach into the computer, or reach somewhere else, ssh'ing into a server

Here is what I think happens if you use your computer right:

When you can navigate and interact with the computer effortlessly, it can feel like you are extending your body and mind into the digital realm, reaching out to grasp and manipulate the vast expanse of information and tasks at your fingertips.

This feeling of expansion and reach is not just a metaphor - it is a citizen of the mind that comes from utilizing the natural structures in our brains that have evolved for tool usage. It is the same confidence and efficiency we feel when picking up a tomato with a fork.

What I am saying is that when you have this mind-expanding and reaching thing going; You are using the tool usage hand coordinate parts of the brain.

It is not that a clunky and cluttered computer experience is the worse tool and a keyboard-driven, smoothed-out experience is a better tool.

It is that the smoothed-out experience is a real tool and anything else you do with a computer is just something you are waging battles with.

If it expands your mind, it is a real tool.

Which tools?

(You can achieve this otherwise, I just want to be more concrete about example technology rather than staying on the philosophy of tool usage level). This technology does the mind-expanding stuff for me: Linux, emacs, a good package manager pacman, a tiling window manager with a lisp REPL stumpwm, qutebrowser at least for the surface level of the web.

One way to get stuff under the fingertips is to have an emacs package for it, this is sort of the infrastructure that allows reach: Files - dired, Git - magit, Notes - denote, Remote files and shell - Tramp, email - mu4e.

In general, growing by removing makes for more control and focus.

The one thing in my daily life that is like a block of UI that I cannot reach into is the slack client. I wish I would be able to have an emacs interface. (emacs-slack doesn't work last time I checked because slack changed how their tokens work. They don't want alternative clients for some reason).

This is also an aspect of the REPL I think

When you have a lisp program running with a REPL you get this reach for the process and (more or less) the entities in the process. Doing this together with the source code (I mean eval-last-sexp and friends) makes the source code come alive. The process becomes a tomato I can move around with my fork. This mind-expanding nature of the REPL is one of its magics. 2 Because this is a tacit process, it is impossible to convey it via words. Similarly, I cannot convey what music does or how it is to ride a bike.

Footnotes:

2

There is a lot more to say. A big aspect is instant feedback, it makes it so you do not have to mentally track uncertainties. You know that each form you are crafting works (You def an example input and code your forms 1 by 1). To follow this thread of philosophical inquiry into Lisp development, see Paul Graham On Lisp and Hackers and Painters.

Date: 2023-01-01 Sun 20:03

]]>
https://faster-than-light-memes.xyz/a-system-like-water.html a-system-like-water 2023-01-01T23:59:59+00:00 a-system-like-water

:faster-than-light /memes

a-system-like-water

I want to use my computer at the speed of thought. I want my mind to reach into the realm of files and websites and ssh servers and do things the way I am doing things with objects in the real world.

Here is the one thing that will make your setup instantly feel much more like water.

This setting changed my life. If I had discovered it later I would have wished I had discovered it earlier. I had it from one of Luke smith vim videos.

You put this in .xinitrc.

xset r rate 120 250

This controls how quickly you are repeating your key after holding it down.

The first specifies the delay before autorepeat starts and the second specifies the repeat rate.

If you use vim bindings j/k are now the way you can scroll. Oh yeaa. This feels sooo smooth - like water.

Once you get used to this going back will make your fingers feel like they're wading through molasses.

Start with

xset r rate 200 200

or something. You need to build up your ability to hit keys quickly. I needed to slowly increase the numbers for this.

Date: 2023-01-01 Sun 18:40

]]>
https://faster-than-light-memes.xyz/the-deeper-chat-gpt.html the-deeper-chat-gpt 2022-12-13T23:59:59+00:00 the-deeper-chat-gpt

:faster-than-light /memes

the-deeper-chat-gpt

Notes on chat-gpt discoveries.

Updates since first version of the post

  1. They improved the websites, my session rarely resets anymore (also chats are saved).
  2. You probably need these fixes for "Network error" anymore, they changed it so you get your long answers, just takes a bit longer
  3. I have some emacs bindings for openai api now here.

Introduction

When a child first learns how to draw with colored pens, a world of possibility is opened. Every new picture is a chance for them to explore and experiment with different techniques and ideas. The pens give them a sense of control and creativity as they bring their thoughts to life on paper. The child might proudly show off their creations, going back and forth between drawing and exclaiming Look what I have drawn!

When I interact with chat-gpt I constantly have this urge to show (hence some of the stuff further down in the post).

I was also starting to dream along the lines of My body is a language model and I want to coax it into doing something. The feel of this is like there is a certain intelligence on the other end, that you can feed the right information to make it grow in some direction.

The psychology of interacting with it is somewhere on a cross-over of pet, houseplant in fast-forward mode and having a text chat with somebody on the moon - works only to some degree.

Formating in this post is like this:

prompt

Answer by chat gpt

Token limit for a single message

I pasted my blog post binaural beats using scittle. Into chat-gpt. It responds like this:

The above text appears to be the introduction to a blog post about binaural beats and their potential benefits…

It seems to only summarize the first part of the post.

what is the last sentence of the above text?

The last sentence of the above text is: ~These beats are thought to originate…

If it doesn't completely make something up in this answer this would point towards that there is a cut of your message input. In this case around 3.7k characters. Maybe it is 4000 characters, then.

I find that even if your session is reset for some reason - happens a lot currently, as the side goes down, or you hit rate limits - you can recover your session by pasting back your previous prompts / the conversation.

What I type is precious, it takes me effort to type. My default mode of writing prompts for chat-gpt is keeping what I type in files that are source controlled. Else there would have been very sad moments of loss for me when a thread resets.

Here is an implementation of copying a good chunk for chat-gpt from your buffer.

(defun kill-for-chat-gpt ()
  (interactive)
  (kill-new
   (buffer-substring
    (point)
    (cl-loop
     for i below 3500
     while (not (eobp))
     do (forward-char 1)
     finally return (point)))))

The fun so far

code

I have solved day 13 of Advent of code with chat-gpt. (code). I pasted the description of the alg and said solve this using Clojure or some such. It then made a function that was sort of correct. I needed to fiddle around a little with it.

It also works quite well when you ask random programming questions like Implement a function to check if a number is divisible by a number n in Clojure.

science edges

Sometimes you have a question in your mind that requires quite some knowledge from different fields and is not to google. This reminds me of the But Why podcast.

It was one of these questions on my mind: Is the rainbow that bees see different?.

Behold a new kind of power:

Summarize how bees see a rainbow. Is it thicker or does it have more colors? Throw in a Richard Feynman quote about refraction. Do it in victorian speech style like sherlock holmes.

My dear fellow, have you ever stopped to consider how a bee perceives a rainbow? You see, unlike us humans who possess three types of cone cells in our eyes, bees have only two. This allows them to see a limited range of colors, with an affinity for blue and ultraviolet hues. Therefore, when it comes to rainbows, it is possible that they may not be able to perceive as many colors or that the colors may appear less vibrant to them.

As the esteemed physicist Richard Feynman once posited, The rainbow is not a thing, it is a manner in which things behave. This statement highlights the ephemeral nature of rainbows, which are formed when light is refracted through water droplets. The exact colors and intensity of a rainbow can vary depending on the size and shape of the droplets, as well as the angle at which the light hits them.

In conclusion, while bees can indeed see rainbows, their perception of them may be altered due to the unique structure of their visual system. The exact colors and intensity of a rainbow may vary depending on the specific conditions at the time of observation.

I asked it about a 4 dimensional rubics cube and it answered intelligently, too. It also feels like it staying honest about what things it knows about and what it doesn't.

long output

It currently dies sometimes with long outputs saying Network error. That is really annoying and I end up resetting the session.

idea 1: You say something like Only tell me part 1 and later Respond with the rest of your answer.

idea 2: You tell it to base64 encode it's output. Tried it once and it didn't do it.

wizard scientists

I told it I am developing a hard fantasy magic system based on science. Then fed it ideas about my world and the magic. Turned out kinda cool. It starts being able to generate text of what a wizard scientist might say. The magic system is based on lisp with a clojure dialect. The wizards are then discovering and studying the magic, and discovering the magical language lisp.

After a while of feeding it with musings about my fantasy world it produced text like this:

I was a young wizard scientist already knowing spells at age 12. After a few months that the magicla academy a mentor wizard wanted to show me a beatiful experi

ment in the reticulum. We stood before a large magical artifact, shaped like a crystal ball. My mentor placed his hand on the ball and began to chant a spell in the ancient language of lisp.

As he chanted, the crystal ball began to glow with a soft, golden light. My mentor gestured towards the ball, and I watched in amazement as a small fireball appeared, swirling inside the crystal.

You see, my young apprentice, my mentor said, the reticulum is a wondrous thing. It allows us to manipulate the very fabric of reality, using the power of magic and the ancient art of lisp.

I nodded, feeling a sense of awe and excitement. I had always been fascinated by magic, and now I was beginning to understand its true power.

But remember, my mentor continued, with great power comes great responsibility. The reticulum is a delicate thing, and it must be treated with care. If we use it recklessly, we could cause great harm to ourselves and others.

I nodded again, taking his words to heart. I knew that I had much to learn, but I was determined to master the art of magic and unlock the secrets of the reticulum.

ment involving a magical animal. The mentor took me to a large laboratory, where I saw a magical bat hanging upside down from a perch.

The mentor explained that this bat had the ability to fly at incredible speeds, using its powerful wings and magical abilities. He then showed me a spell that he had been working on, which would allow us to observe the bat's movements in slow motion.

I was amazed as the mentor cast the spell, and the bat suddenly slowed down, its wings flapping lazily as it hovered in midair. We were able to watch as the bat shifted its wings and body, adjusting its position to maintain its balance.

The mentor then asked me to try the spell myself, and I was able to successfully cast it on my first try. I was thrilled by the experience, and I knew that I had just begun to unlock the true potential of the reticulum.

I continued to study and experiment with magic, learning new spells and honing my skills. I eventually became a respected wizard scientist, known for my knowledge and expertise in the magical arts. I continue to explore the mysteries of the reticulum, always seeking new and greater insights into its workings.

The model has a high temperature so it comes up with random things as well. You can put the same prompt and expect different answers. A temperature of 0 would mean it is deterministic.

Then you can always swap your medium, the ideas stay the same.

Give me some clojure reagent code that visualizes the concepts of this thread.

Output: Here is an example of how you might use clojure reagent code to visualize the concepts of the reticulum and its magical abilities:

  (ns my-app.core
    (:require [reagent.core :as reagent]))

  ;; define a component for the reticulum
  (defn reticulum []
    [:div
     [:h1 ~Reticulum~]
     [:p ~The reticulum is a vast network of magical information, where symbols and spells flow like rivers of energy. It is the foundation of our magical abilities, allowing us to manipulate the physical world in ways that would be impossible without its power.~]
     [:p ~The reticulum uses a dialect of the lisp programming language, which allows us to define symbols and functions that can be invoked to cast spells. For example, we can define a fireball function like this:~
      [:pre ~(defn fireball [radius]
         (* radius 2 pi))~]]
     [:p ~This simple function takes the radius of a desired fireball and calculates its area. We can then use this function to cast a spell and create a fireball of any size we desire. To do so, we simply need to invoke the fireball function with the desired radius:~
...
      [:p ~The reticulum also allows us to create more complex spells, such as teleportation and mind reading. These spells require a deep understanding of the lisp language and the underlying principles of...

There are no limits to the level of detail. For me as a d&d world building geek that never actually did play d&d, this is amazing:

Magical Gemstone Manipulation - an Introduction. This textbook is an introductory text Chapters:

Introduction to Gemstones and their Properties

Types of Gemstones and their Uses in Magic

Gemstone Cutting and Shaping Techniques

Gemstone Enchantment and Infusion with Magic

Gemstone Crafting and Design

Advanced Gemstone Manipulation and Applications

Ethics and Responsibility in Gemstone Magic

Case Studies and Examples of Gemstone Magic in Practice

Further Study and Exploration of Gemstone Magic

The textbook would include chapters on the different types of gemstones, their properties and how they can be used in magic. It would also cover techniques for cutting and shaping gemstones, as well as the process of enchanting and infusing them with magic. Additionally, the book would discuss the ethics and responsibility of using gemstones in magic, and provide case studies and examples of how gemstones are used in practice. The book would be suitable for both beginners and more experienced practitioners of gemstone magic.

Here is some imaginary Clojure code from an imaginary wizard science class about my imaginary magic.

"But the true power of the reticulum comes not from individual spells like the fireball function, but from the ability to combine and manipulate these spells to create more complex and powerful effects. For example, we can use the teleportation function to transport ourselves or objects from one location to another:"

(defn teleportation [target location]
 ;; complex lisp code to transport target to location
  ())

"We can then combine this teleportation function with other spells, such as the shield function, to create a powerful defensive spell that can protect us from harm:"

(defn protective-shield [radius strength duration]
  (let [shield (shield
                radius
                strength
                duration)
        teleport (teleportation target location)]
    ( ;; combine shield and teleport spells to create protective shield)
     )))

I formatted the src blocks, they were all clumped up. The src blocks are the same style as the examples I gave it further up in the prompt.

uncovering

Trying more advanced fixes for Network Error.

Prompt try1 1:

Here are some rules you should follow from now on:

Instead of answering with your answer text; Answer with a high level overview of your answers.

The overview should have the form of the output of the linux tree shell command.

Your possible answers represent files in the imaginary output.

From then on, when I say tree, print a tree of the current concepts of the conversation. Each file is an answer that you might give. The files have short descriptive names of their content.

When I say less <filename> you print the first 50 lines of that answer. When I then say j you print the next 50 lines. When you reach the end of your answer you print a line like <filename> ends here.

Do you understand these rules?

Lol, I feel like I made it reveal a deeper layer of its programming, check this:

Yes, I understand these rules.

Here is a tree of my possible answers:

.
├── yes
├── no
├── i_dont_know
├── i_dont_understand
├── i_am_a_computer_program
└── i_am_not_able_to_brows_the_web

To view the contents of a file, you can use the less command followed by the file name. For example, to view the first 50 lines of the yes file, you would type less yes. To view the next 50 lines, you can type j. When you have reached the end of the file, the program will print a line indicating that the file ends there. For example, if you have reached the end of the yes file, the program will print yes ends here.

Now this could be and I think is it just making things up, fugazi. But I suspect that they have a hidden prompt from where those come from. A user of chat-gpt is at this point familiar with the ever-present possibility of i_am_not_able_to_brows_the_web.

code

It can do code, although as you might expect you still need to put it together and make it work. For me, it currently outputs a lot of Clojure code that is not quite right. Putting locals into a let that was supposed to be in loop for example.

I already started having the effect of thinking I want to do x, I ask openai how to do x. This must be how it is for google driven developers and I can say that is a step down from reading the manual / docs on how to achieve it. The most powerful path is one of nuance, using it where it is useful but not making your thinking reliant on it. Else you stop thinking for a while waiting for the prompt to come back. - that would be a horrible thing to get used to.

New kind of interface

The bee rainbow example is the use case of a conversation interface to the world's knowledge. This is currently hampered by the fact that you might get I cannot browse the web answers.

But I think in principle that is super promising. Imagine building a program feeding it some science data and you get a conversation interface where you just ask it for trends in the data.

In programming, I could feed such a thing to my repo and then ask it things like make a listing of the domain model of this code and things like this. (See the tree rule example).

other tips

You can just stop in the middle of

It might then continue with your text.

Here is what an old wizard in a hard fantasy world might say about magic: You have to undestand the intricacies of the elements that

compose magic to wield it effectively. Magic is not something that can be easily learned or mastered; it takes years of study and practice to understand its complexities and tap into its power.

The key to using magic effectively is understanding the fundamental principles…

  • Typos don't matter so much. Just get across what you want to say.
  • If you do something like building up ideas about a fantasy world, you can randomly paste snippets of text, they don't necessarily need a logical continuation.

Conclusion

This is a fascinating new kind of tool/thing in the world.

It can generate text after you put in ideas/examples/ prompts that it can work with. You can build up some context, which makes it so sad right now when your session gets broken. At times it feels so precious I have it doing this thing now. Like some special place that you went to together with it.

If you had shown this tool to someone 10 years ago, they would have thought it was science fiction. Many people might have said that AI couldn't have such a high level of understanding. They were wrong then, and they are still wrong now about what the next advancements in AI will be.

The website interface and the restrictions are annoying. True power will come from having a truly open (free?) version of this that is my own and that I can hack on. I want this in Emacs, I want my prompts source controlled, and I don't want weird and made-up restrictions that make it just annoying 2/10 times.

The real advancement that I feel over chatbots from 5-10 years ago is that it keeps the ideas and concepts in a conversation.

In a similar conversation to the above if I would say j out of context: (yes there is a typo it even keeps that straight, lol)

I'm sorry, but I don't have any more information to provide for the file acknoledged. As I mentioned earlier, when you say less <filename>, I will print the first 50 lines of that answer. If you then say j, I will print the next 50 lines. Since the file acknoledged only has one line of text, there are no additional lines to print.

├── acknoledged

Here is the tree structure again, showing that the file acknoledged is the only file available at this time. If you would like to see the first 50 lines of this file, please say less acknoledged. Otherwise, please ask a new question or provide a new request.

I had a few moments while interacting with it where I feared it dropping the concepts or being confused about things. But it never was. It turned around in the next sentences and clarified that it is still on track.

Since it is simulating conversation, you feel some of the limits in your conversation parsing part of the brain. It is like it has a certain psychology. If it becomes the perfect tool, the annoying bits will be replaced with the quiet competence of a computer.

Footnotes:

1

Here is a further version of this prompt.

Here are some rules you should follow from now on:

Instead of answering with your answer text; Answer with a high level overview of your answers.

The overview should have the form of the output of the linux tree shell command.

Your possible answers represent files in the imaginary output.

From then on, when I say tree, print a tree of the current concepts of the conversation. Each file is an answer that you might give. The files have short descriptive names of their content.

When I say less <filename> you print the first 50 lines of that answer. When I then say j you print the next 50 lines. When you reach the end of your answer you print a line like <filename> ends here.

Do you understand these rules and can you follow them? Answer with acknoledged

When I pasted the (incomplete) conclusion of my blog post it answered with this. And yes, asking less limitations will make it output what you expect.

.
├── blog_post_conclusion
    ├── praise_for_tool
    ├── limitations
    └── potential_improvements

The above tree structure represents the high-level overview of the conclusion to the blog post. The blog_post_conclusion file represents the overall conclusion of the post, while the praise_for_tool file represents positive comments about the tool and its capabilities. The limitations file represents any limitations or challenges with the tool, and the potential_improvements file represents suggestions for how the tool could be improved in the future. To see the first 50 lines of any of these files, please say less <filename>. For example, to see the first 50 lines of the blog_post_conclusion file, you would say less blog_post_conclusion.

Date: 2022-12-13 Tue 16:47

]]>
https://faster-than-light-memes.xyz/backing-you-up.html backing-you-up 2022-10-14T23:59:59+00:00 backing-you-up

:faster-than-light /memes

backing-you-up

File backups are useful. It happenend more than once to me that I found something in a backup somewhere from 2 months ago that did no end up being commited in git.

Frequent file backups will make you more relaxed.

backup-each-save

Saving buffers is a great joy of life.

With backup-each-save, each save also makes a backup file in a backup dir.

config:

(use-package backup-each-save
  :config
  (add-hook 'after-save-hook #'backup-each-save)
  (setf make-backup-files nil))

Lol, this is how the backup dir looks for this file I am currently modifying.

-rw-r--r--  1 benj benj  858 Oct  4 16:06 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_06_00
-rw-r--r--  1 benj benj  916 Oct  4 16:06 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_06_50
-rw-r--r--  1 benj benj  935 Oct  4 16:07 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_07_21
-rw-r--r--  1 benj benj  937 Oct  4 16:07 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_07_45
-rw-r--r--  1 benj benj  959 Oct  4 16:08 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_08_05
-rw-r--r--  1 benj benj 1.1K Oct  4 16:10 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_10_08
-rw-r--r--  1 benj benj 1.3K Oct  4 16:12 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_12_08
-rw-r--r--  1 benj benj 1.3K Oct  4 16:12 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_12_42
-rw-r--r--  1 benj benj 1.3K Oct  4 16:13 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_13_15
-rw-r--r--  1 benj benj 1.3K Oct  4 16:13 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_13_28
-rw-r--r--  1 benj benj 1.3K Oct  4 16:13 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_13_36
-rw-r--r--  1 benj benj 1.3K Oct  4 16:13 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_13_40
-rw-r--r--  1 benj benj 2.7K Oct  4 16:16 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_16_09
-rw-r--r--  1 benj benj 2.7K Oct  4 16:16 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_16_18
-rw-r--r--  1 benj benj 2.8K Oct  4 16:16 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_16_42
-rw-r--r--  1 benj benj 2.8K Oct  4 16:16 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_16_49
-rw-r--r--  1 benj benj 2.8K Oct  4 16:17 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_17_11
-rw-r--r--  1 benj benj 2.9K Oct  4 16:17 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_17_47
-rw-r--r--  1 benj benj 2.9K Oct  4 16:18 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_18_34
-rw-r--r--  1 benj benj 2.9K Oct  4 16:18 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_18_37
-rw-r--r--  1 benj benj 3.1K Oct  4 16:19 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_19_07
-rw-r--r--  1 benj benj 3.1K Oct  4 16:19 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_19_10
-rw-r--r--  1 benj benj 3.1K Oct  4 16:27 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_27_36
-rw-r--r--  1 benj benj 3.1K Oct  4 16:27 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_27_54
-rw-r--r--  1 benj benj 3.1K Oct  4 16:28 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_28_10
-rw-r--r--  1 benj benj 3.1K Oct  4 16:28 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_28_16
-rw-r--r--  1 benj benj 3.2K Oct  4 16:28 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_28_52
-rw-r--r--  1 benj benj 3.2K Oct  4 16:31 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_31_40
-rw-r--r--  1 benj benj 3.3K Oct  4 16:31 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_31_48
-rw-r--r--  1 benj benj 3.4K Oct  4 16:32 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_32_34
-rw-r--r--  1 benj benj 3.3K Oct  4 16:32 20221004T160458--scratching-in-space__emacs.org-2022_10_04_16_32_40

The backup dir size doesnt matter compared to the vastness of my disk space.

Laptop:

du -h -d0 ~/.backups/
| 43M | /home/benj/.backups/ |

It just doesn't matter.

The space age

Other instances of emacs in the space age:

Date: 2022-10-14 Fri 15:33

]]>
https://faster-than-light-memes.xyz/the-joy-of-clojure.html the-joy-of-clojure 2023-01-26T23:59:59+00:00 the-joy-of-clojure

:faster-than-light /memes

the-joy-of-clojure

Introduction

We don't yet have a strong psychology and sociology of programming languages. One day we will, and we will be able to retroactively make sense of why Clojure is so powerful.

6usJE0L.jpg

Figure 1: The soul! A computer. Solar punk Clojure. The inside of a computer. Rubics cube colored gems are flying around. Lighting.

Paul Graham has suggested The Taste Test for understanding the power of a language. A programming language is a tool for thinking. Ultimately, its power comes from letting you think thoughts and express them. With sensibility (hypersensitivity), you can tell which language feels more restrictive than another.

If all languages would be the same, we would be programming assembly. But we are not, because we live in a world where languages have varying degrees of power.

Here I try to describe a few things that set Clojure apart, even from other Lisps.

What interactivity brings

With Lisp, you can quickly test each piece of code as you write it, ensuring that it is solid and functioning correctly before moving on to the next piece. This allows for a more streamlined development process and eliminates the need to keep in mind all of the potential issues that could arise with a piece of code. Additionally, the ability to quickly evaluate code and make small experiments allows for a more agile and flexible development process.

Here is a simple example:

(file-exists-p "~/.clojure/")

Are you getting the file path right? When I write Lisp, I know the answer while I am writing the program. I just eval whatever form I have to build the file path. Because of structural editing, I can wrap whatever form in (file-exists-p) quickly and experiment right then and there.

Doing little experiments is quick enough so it can mesh with your thinking. I have the freedom and agility to just do and move. We get the same power in the small during development and in the large while diagnosing a problem in production. 1

Philosophy of simplicity

Clojure first clicked for me via Rich Hickey talks. Keep things simple. Let data be data. Then you can just manipulate the essence of the stuff and be done. 2 , 3

He establishes the reasons for Clojure and the opinions on how to build things. And this permeates the culture.

The combination of data-orientedness and functional programming while making real-world pragmatic tradeoffs, lends itself to a complete4, robust, no-bullshit style.

Strong community

When I use a library I can go to the slack channel and usually the maintainers help me out. It happened to me more than once when I made a bug report, somebody fixed it within a few days. Everybody is excited about technology and wants to help you out. It ties in with the joy of Clojure as well. You get happy, friendly people. This is power. Humans are more effective when they are happy and friendly.

Not to mention Borkdude.

Non-breaking versioning

It is an explicit value (again from Rich Hickey's philosophy), to not make breaking changes. This is one of the things where once you have it, boy, you don't want to ever go back.

After acquiring this taste, getting broken because I bump a version makes me think Why are you doing this to me?.

The aesthetics of data orientedness

The core library is a huge lever because we lift everything that can be into the space of data structures, then manipulate those data structures.

Config input, REST API response, database queries, and responses. It is all the same kind of stuff once it is in our system.

I think of this as a lift and manipulate kind of lever. Unix has this with program input output text. Once you are in the realm of textual input and output you can leverage shell commands to manipulate. Emacs has the same thing with text in buffers. If you can express your domain as text in the buffer you can give it to the user for manipulation, and you can leverage the core library for manipulating text in buffers.

This data-orientedness is something I can expect from libraries and other people's code. The dominating amount of stuff will always be just data structures acting on pure functions.

Freedom and joy

The workflow is an utter joy, with the REPL at the center of it. I start a program once and it grows together with my ideas. There is something about a program that runs for days and you don't restart it that I cannot explain but it does something to your mind. The closest analogy is a kind of friendship with the program.

  • inline def some of your data, craft your code forms.
  • Functional programming (and The Value of Values)
    • able to fabricate data
    • able to get the time right with atomic successions
    • able to easily keep records of the past

I get a real kind of safety. The kind where I can sleep at night because I know my program is bug-free. You get this from there being few enough ideas in the program that you can hold the relevant pieces in your head.

Any program that is small enough to be self-evident is with a step function dramatically more likely to work bug-free. 5

It helps that everything is accessible from emacs which is the other ancient and powerful tool that feels like an extension of my mind.

Because of this focus, solidity and ease of development, I am more joyful and creative when programming with Clojure.

It allows me to focus on the actual problems. So I can spend time on getting the user experience right etc.

Summary

So here is a tool that lets me think the right thoughts and express them. It lets me move with ease where I want to be.

From Lisp, I get the interactivity and the tradition of FP and simplicity. When I want to make a small experiment with the code, I can just do a small experiment with the code.

Beyond that, there is a solid and dependable community, the data-orientedness and the leverage of targeting big platforms.

I can model information systems and can make the program just do what it needs to do, and do nothing more.

Clojure just delivers.

The silent competence of the computer.

(Marvin Minsky)

Note

I know there is a book of the same title. This is not accidental. The power of Clojure also lies in the joy it brings. An alternative title for this post could be Joy is power in analogy to Paul Grahams Succinctness is power.

Footnotes:

1

Bradford Cross has mentioned this and other things in a very convincing talk recently.

2

I believe I see hints of the same craftsmanship of getting shit done ideas in other places: Brian Will Object-Oriented Programmin Embarrassing, his counterexamples are very straightforward and complete. Chris Keaathley - SOLID code isn't flexible

3

Rich Hickeys greatest hits The start point. Get your mind expanded by simplicity and clear thinking.

4

Complete in the sense that you make a piece of code that gets the job done. Instead of scattering logic around the place.

5

Stuart Halloway has similar thoughts, Radical Simplicity. Other people like Dan Friedman also made this relatively explicit. I think at this point it is obvious that simplicity is crucial for building good software. The question is what is simplicity and how to do it?.

Date: 2023-01-26 Thu 09:48

]]>
https://faster-than-light-memes.xyz/binaural-beats-using-scittle.html binaural-beats-using-scittle 2022-09-19T23:59:59+00:00 binaural-beats-using-scittle

:faster-than-light /memes

binaural-beats-using-scittle

Introduction

The best thing about being a rationalist is figuring out you are wrong about something.

I was thinking that binaural beats belong together with astral travel, frankly, just down the toilet. Turns out that not only was I wrong, but binaural beats also have cool neuroscience and pose a fun engineering problem on top of that!

Here is the current result of my journeys up on gh-pages.

What are binaural beats?

Wikipedia

A binaural beat is an auditory illusion

For example, if a 530 Hz pure tone is presented to a subject's right ear, while a 520 Hz pure tone is presented to the subject's left ear, the listener will perceive the illusion of a third tone. The third sound is called a binaural beat, and in this example would have a perceived pitch correlating to a frequency of 10 Hz, that being the difference between the 530 Hz and 520 Hz pure tones presented to each ear.

Science

There has developed a growing science about improvements in memory and attention tasks when listening to binaural beats.

BTW the frequency and the time of the exposure matter (i.e. before and during the task is best).

Oh yes, I certainly want more of that memory and attention.

eHaaoYF.png

Figure 1: A brain with headphones flying at the speed of light through space. Lightning on the brain. There is a sine wave in the background. Stylized, Colorful, Cinematic, Digital Art.

Frequency

Theta waves (5Hz) actually decrease memory task performance. So I really do not want to listen to those. I heard Andrew Huberman saying that 40Hz is the most powerful.

If you know about brain waves, you might remember 40Hz as the legendarily intriguing gamma wave.

From wikipedia article:

Gamma rhythms are correlated with large scale brain network activity and cognitive phenomena such as working memory, attention, and perceptual grouping, and can be increased in amplitude via meditation or neurostimulation.

We are really talking about cool stuff here, attention, working memory, and memory processes. Also, the Binding problem.

The neuroscience of the auditory system

Hearing is cool because the neuronal neural information first goes into the brainstem and then goes up some nuclei up to the thalamus. And eventually to the temporal lobes of the cortex (the 2 arm things on the side of the brain).

This is different from the vision system where the info goes directly to the thalamus.

Quoting this paper:

Presenting two tones with a slight frequency mismatch to each ear separately creates a perception of a third tone, a binaural beat, that oscillates at the absolute difference between the tones (Oster, 1973; Moore, 2012). These beats are thought to originate subcortically in the medial nucleus of the superior olivary complex, the first nucleus in the auditory pathway to receive bilateral input (Wernick and Starr, 1968; Kuwada et al., 1979). This “illusory” third tone is lateralized between the left and right ear of the listener, making binaural beats useful for spatial sound research (Ross et al., 2014).

from the Wikipedia articles on Sound localization

The auditory system uses several cues for sound source localization, including time difference and level difference (or intensity difference) between the ears, and spectral information.

and Superior olivary complex

The superior olivary nucleus plays a number of roles in hearing. The medial superior olive (MSO) is a specialized nucleus that is believed to measure the time difference of arrival of sounds between the ears (the interaural time difference or ITD). The ITD is a major cue for determining the azimuth of sounds, i.e., localizing them on the azimuthal plane – their degree to the left or the right.

So there is sort of a clump of neurons in the brainstem that are specialized to integrate the timing information between the left and the right ear. I'm guessing those then start firing in the 40Hz frequency and that is interpreted as a third sound higher up.

I think this is ultra cool

You throw some energy at the brain in the right form (in this case some sound waves) and it reacts in some special way. If you put it like that, it is not surprising that some things eventually, end up doing something.

Now that the phenomenon has a name we can talk about it, similar to ASMR.

Thinking about how this was always part of how the brain works. Makes me wonder if some music composers and performers implicitly hit on this earlier, or not. I tried searching the web for

binaural beats in music

but I really get the same results mix as when I search for binaural beats.

Give me those binaural beats

I dint feel like opening a youtube video just to listen to some sounds. As an aspiring hacker and engineer, I just want to make my computer make some sounds that I want to listen to. So I decided to make a simple website that just makes binaural beats and nothing else.

The problem statement:

Make a sound on 1 ear (e.g. left headphone speaker)

Make a second sound on the other ear, with a +40Hz frequency.

scittle

I set up a beautiful hello world and connect with nrepl and get greeted with a friendly Isn't cool? this :).

It took me a moment to figure out I should open my index.html with a browser. Then do the cider-connect-cljs

1 ear, 1 sound

First I think let's start making a sound in 1 ear.

I am thinking a frequency that I can hear would be nice so I search the web for human auditory frequencies

1 kHz sounds like a good first thing to try. I am figuring something inside the speech area should sound natural (turned out that was a naive assumption).

The first playground

I have a file called playground.clj (Later I figured out I should rename to .cljs :) ).

Now getting heavily inspired by this code. Going 1 form by 1 like a usual lisp interaction dev experience, lulling it up:

(def ctx (js/window.AudioContext.))
(def ctx js/window.webkitAudioContext)

(def panner (ctx.createStereoPanner))
(set! (.. panner -pan -value) -1)
(.. panner (connect ctx.destination))

(def oscillators (atom []))
(let [o (ctx.createOscillator)
      _ (set! (.- o type) "sine")
      _ (set! (.. o -frequency -value) 1000)]
  (. o start)
  (. o (connect panner))
  (swap! oscillators conj o))

I connect my headphones via Bluetooth (a small feat on Linux, maybe another blog post), and lo and behold I hear a tone in my left ear. It is a really obnoxious sound, after a few seconds, it is so painful that I move the headphone to the side.

Playing Hz, first round

Here is a more endurable sound:

(set! (.. (@oscillators 0) -frequency -value) 200)

Playing around live at the REPL with sound is fun!

Now I am thinking, let's pick some music frequency, those are supposed to be crafted over hundreds of years to be beautiful frequencies, right?

Checking out a website. I pick D#3 / Eb3. Whatever that is.

(def a-note-freq 152.74)
(set! (.. (@oscillators 0) -frequency -value) a-note-freq)

binaural!

Let's do the thing where I add +40Hz and play that on the other ear. First I start generalizing how I make a panner:

(defn ->panner [ctx left?]
  (let
      [panner (. ctx createStereoPanner)
       _ (set! (.. panner -pan -value) (if left? -1 1))
       _ (.. panner (connect ctx.destination))]
    panner))

For some reason running this I get:

Failed to execute 'connect' on 'AudioNode': Overload resolution failed.

I went and asked in the nbb clojurians slack. I am sure one day we will figure out this error, in the meantime…

just put the second sound in the other ear, whatever

(ns beats)

(def a-note-freq 152.74)
(def binaural-beat-freq 40)
(def oscillators (atom []))
(defonce ctx (js/window.AudioContext.))

(def panners
  {:left
   (let [left? true]
     (let [panner (. ctx createStereoPanner)]
       (set! (.. panner -pan -value) (if left? -1 1))
       (.connect panner ctx.destination)
       panner))
   :right
   (let [left? nil]
     (let [panner (. ctx createStereoPanner)]
       (set! (.. panner -pan -value) (if left? -1 1))
       (.connect panner ctx.destination)
       panner))})

(defn oscillate [panner hz]
  (let [o (ctx.createOscillator)
        _ (set! (.- o type) "sine")
        _ (set! (.. o -frequency -value) hz)]
    (. o start)
    (. o (connect panner))
    (swap! oscillators conj o)))

(-> panners :right (oscillate (+ a-note-freq binaural-beat-freq)))
(-> panners :left (oscillate a-note-freq))

lol, it works.

Intermediate results

Artifacts

Every now and then there are artifacts in the sound with my headphones setup. Some are just rustling and crackling.

Others sound like some kind of metal being stretched far, far away, underwater, or in slow motion. It reminds me a bit of the Dungeon Keeper soundtrack. Dark and eerie, sort of slow mow.

Binaural beat?

Pretty sure I get the third-tone illusion. I would describe it as some kind of background or in between "airy" sound. It is supposed to seem to come from the middle of the brain. It is as if the fabric of the sound is richer. Like there is sound in more places.

Change the base frequency

It occurred to me, that if I get the 40Hz sound illusion, then I would predict that I can change the base frequency, keeping the 40Hz difference between left and right ear invariant. I should then constantly perceive a 3rd tone which is the binaural beat.

I really need a slider for frequencies in my life.

I did not do much web dev in my life and making a slider was a first.

I managed to put something together, drawing inspiration from w3 schools for the Html, scittle for how to export, and stackoverflow for how to add a function to "onchange".

nice dev experience, scittle really

  1. I did not need to restart my REPL at any point, adding those Html elements, then reloading my index.html - it handles that.
  2. I get auto completions with cider. E.g. js/.. does something.

    BTW here is a tip, for sci projects (babashka, nbb, scittle). Currently, you need to evaluate a namespace form first. Then you can get completions. At least with cider.

M8rSuZ3.png

Figure 2: A mouse with headphones typing on a laptop. Intelligent. Sparks of magic are flying around. There is lightning on the mouse and laptop. Computer programming source code. Colorful, playful.

The word scittle makes me think of a small mammal in the habitus of a mouse. I imagine it scurrying and curiously sniffing around.

code:

index.html

<!DOCTYPE html>
<html>
  <head>
    <script>var SCITTLE_NREPL_WEBSOCKET_PORT = 1340;</script>
    <script src="https://cdn.jsdelivr.net/npm/scittle@0.3.10/dist/scittle.js" type="application/javascript"></script>
    <script src="https://cdn.jsdelivr.net/npm/scittle@0.3.10/dist/scittle.nrepl.js" type="application/javascript"></script>
    <script type="application/x-scittle" src="beats.cljs"></script>
  </head>
  <body>
    <div class="slidecontainer">
      <input type="range" min="120000" max="250000" value="15274"
      class="slider" id="frequencyRange" onchange="update_app(this.value)"> </div>
    <div id="frequencyDisplay"> </div>
  </body>
</html>

beats.cljs

(ns beats)

(def binaural-beat-freq 40)
(defonce ctx (js/window.AudioContext.))
(def slider (js/document.getElementById "frequencyRange"))
(def display (js/document.getElementById "frequencyDisplay"))

(def panners
  {:left
   (let [left? true]
     (let [panner (. ctx createStereoPanner)]
       (set! (.. panner -pan -value) (if left? -1 1))
       (.connect panner ctx.destination)
       panner))
   :right
   (let [left? nil]
     (let [panner (. ctx createStereoPanner)]
       (set! (.. panner -pan -value) (if left? -1 1))
       (.connect panner ctx.destination)
       panner))})

(defn update-display! [value]
  (set! (.-innerHTML display)
        (str "Base frequency: " value)))

(def get-oscillator
  (memoize
   (fn [panner]
     (let [o (ctx.createOscillator)]
       (set! (.- o type) "sine")
       (. o start)
       (. o (connect panner))
       o))))

(defn oscillate [panner hz]
  (let [o (get-oscillator panner)
        _ (set! (.. o -frequency -value) hz)])
  hz)

(defn update-app [frequency-value]
  (let [frequency-value (/ frequency-value 1000.0)]
    (-> panners :right (oscillate (+ frequency-value binaural-beat-freq)))
    (-> panners :left (oscillate frequency-value))
    (update-display! frequency-value)))

(set! (.-update_app js/window) update-app)

(update-app (* 1000 152.74))

The fact that I export my function by setting this global window object is quite wild. And then how I write a string of js code in the 'onchange' of the Html - damn. As I said, I am new to the web. Now I know one reason why it is called the wild west. But it let me "just do" what I wanted without being in my way so I appreciate that.

On the scittle side, I updated the code to only get 1 oscillator per slider. Seems like stuff is working. Switching up the frequencies via the slider is satisfying. For some reason, those artifacts are also gone. Maybe sliders just ensure balance and harmony in the world?

I am pretty sure I can tell there is 1 sound that seems to stay the same across frequencies.

I do the float * 1000 trick because I want to work with 2 digits for my frequencies.

Btw I also quickly tried what a real 40Hz tone sounds like. Ultra-low. I almost feel like I can make out the single waves, maybe that are the headphones cracking? Not surprising as the lower bound of human hearing is 20hz. The sound of the highest achievement of human thought. Genius insights, ideas that come to you like lightning. Globally integrating patterns of the brain and mind.

xijojsT.png

Figure 3: Harry potter wearing headphones having spiritual enlightenment about magic. Glowing magic sparks fly around. Colorful, cinematic, video game concept art.

Notes

Images

Made with stable-diffusion. The captions are the prompts I used.

Update 1

Currently does not work on mobile. Seems like I have the opportunity for another web dev feat, then. Seems like the issue is isolated on the sound appearing because the slider value works fine (meaning that the scittle code is running fine).

Update 2

Now it also works on mobile! Somebody helpfully pointed out on slack that on mac there was an error about audio refusing to play before the first touch event. I fixed that by adding a play button. But mobile still did not work, ok. After checking stackoverflow I still sort of have the idea that it has to do with user interaction events and this AudioContext. I first wanted to delay the whole audio setup until you click the button. But read that you should make a single AudioContext at the beginning.

So I try to delay the 1 other thing in the code:

(def panners
 (delay {:left (->panner true) :right (->panner false)}))
(-> @panners :right (oscillate (+ frequency-value binaural-beat-freq)))
(-> @panners :left (oscillate frequency-value))

It works, haha!

Date: 2022-09-19 Mon 11:04

]]>
https://faster-than-light-memes.xyz/dreaming-code.html dreaming-code 2022-10-20T23:59:59+00:00 dreaming-code

:faster-than-light /memes

dreaming-code

I produced source code in a dream once.

When I dream of coding it is usually sort of "disembodied" just concepts and problems + in the earlier part of the night.

What is the business of these early-night dreams?

Sleep mentations

NREM dreams are typically shorter, more fragmented, and more thought-like whereas REM dreams are longer, more emotional, and more bizarre

(Carr and Solomonova 2019).

These dreams from the early part of the night are more like thinking with some dream logic.

Here is an example from my dream diaries:

I have an internet connection in my brain and I need to connect to a database, then send some data to my feet. It is like thinking about the problem itself more, with some disembodied visuals of code. The coding itself is a little like being able to modify code blocks by raising an eyebrow or a finger. Every time I wake up I sort of want to "go back" to the problem, because I "know", I have almost solved it. Always so close.

Another quote from Carr and Solomonova:

Some use a more inclusive dreaming definition, such as ‘sleep mentation’, which is characterized by any cognitive activity, whereas the original concept of dreaming was more qualified as hallucinatory, predominantly visual, imagery (see also chapter 5). The questions used by an experimenter can alter a participant’s interpretation of dreaming. For example, the question, “what was going through your mind just before I called you”, will encourage more frequent dream reports than, “what were you dreaming about?”

I like the idea of calling these sleep mentation instead of dreams.

The night goes on - REM, NREM

Attributes such as length, bizarreness, and perceptual vividness increase for both NREM and REM sleep reports across the night

(Carr and Solomonova 2019).

Additionally, it is well known that in the later part of the night you have more REM sleep.

I was grouping dreams into 2 categories on a continuum:

  1. "Episodic" dreams, a reference to episodic memory. Featuring persons, places, situations with a story. In many cases featuring a main character. Later in the night.
  2. "Non-Episodic" dreams: Usually no characters, no real story. More like thinking about a problem. Or tool/toy/concept usage in the abstract somehow. As if the brain parts for the tool usage are online without any of the storytelling, and little of the "world integrating" parts. More abstract, fewer visuals and perceptions (low "vividness"). Also, extremely hard to remember any content. Also, it is very hard (impossible?) to become lucid during one of those. Earlier in the night.

Source code in a vivid dream

It did happen to me recently halfway through the night. A dream purely about coding but more on the side of what I would call episodic. This was a complete first time. Usually, code dreams where these ephemeral problem-solve dreams.

I was dreaming about my emacs config.

I recall a visual of colored source code (+ content!). There was also a bit of a first-person main character, thinking along the lines of "I want to make this part smoother…". Here it is:

;; This code came to me in a dream almost verbatim:
(add-hook 'kill-emacs-hook #'save-some-buffers)

I was able to type in this code the next morning, haha!

Date: 2022-10-20 Thu 19:18

]]>
https://faster-than-light-memes.xyz/scratching-in-space.html scratching-in-space 2022-10-04T23:59:59+00:00 scratching-in-space

:faster-than-light /memes

scratching-in-space

Emacs scratch buffers have place oriented design.

A simple alternative: make files.

Musings about persistent scratch technology.

Introduction

If you ever typed something in a buffer called *scratch* you will inevitably have found yourself in this situation:

  1. Just typed some awesome code.
  2. Kill scratch buffer accidentally or unthinkingly.
  3. That awesome text is gone forever… and it hurts.

I did try persistent-scratch, in its simplest form, it persists your scratch buffer across sessions. You still end up having one place for your "current" scratch. It just did not click with me.

The whole idea of a scratch buffer might be obsolete (Xah Lee 2008).

What I want:

  1. Convenient way of writing some code interactively.
  2. Persist it.

scratching in space

Our disk space is vast, and emacs is great at creating files.

We can be like Sherlock Holmes and never throw our notes away.

Horde those scratches. Put them in git. Now you can grep through them, see what you were scratching years in the past.

I have a dir called ~/scratches with all my scratches. This is a bit similar to denote, which I use for note-taking.

here is my current hack for this:

(defvar mememacs/scratch-dir (expand-file-name "~/scratch"))
(defun mememacs/latest-scratch (suffix)
  (unless (file-exists-p mememacs/scratch-dir)
    (make-directory mememacs/scratch-dir))
  (when-let
      ((f
        (car
         (cl-remove-if-not
          (lambda (it)
            (and (string-suffix-p suffix it)
                 (not (string-match-p "#" it))))
          (process-lines
           "ls"
           "-A"
           "-t"
           mememacs/scratch-dir)))))
    (expand-file-name f mememacs/scratch-dir)))

(defun mememacs/new-scratch-name (suffix)
  (unless (file-exists-p
           mememacs/scratch-dir)
    (make-directory
     mememacs/scratch-dir))
  (expand-file-name
   (format "%s.%s" (make-temp-name "scratch-") suffix)
   mememacs/scratch-dir))

(defun mm/scratch
    (&optional create-new suffix)
  "Visit the latest scratch file with `suffix` (a file extension).
With prefix arg make a new file."
  (interactive
   (list current-prefix-arg
         (completing-read "scratch filetype: " '("cljs" "clj"))))
  (let* ((latest (mememacs/latest-scratch suffix))
         (buff
          (find-file-noselect
           (if (or create-new (not latest))
               (mememacs/new-scratch-name suffix)
             latest))))
    (pop-to-buffer-same-window buff)
    (when (eq major-mode 'emacs-lisp-mode)
      (elisp-enable-lexical-binding))
    buff))

(defun mm/scratch-el (&optional arg)
  (interactive "P")
  (mm/scratch arg "el"))
keybinds:
leader bs #'mm/scratch-el
leader bS #'mm/scratch

With a nice keybind (leader b s) I go to my current scratch file - the latest modified file in my scratch dir. With prefix-arg, it makes a new file. A second bind will ask me to make a clj or cljs file.

clojure scratch repl?

Whatever. I just do this:

echo '{}' > ~/scratch/bb.edn

Now I can start a cider repl with bb in my scratch dir. If you want to be asked for bb or jvm:

echo '{}' > ~/scratch/deps.edn

Also nbb: A nice way to scratch some cljs + javascript + node: It currently requires some workaround that you can find here.

Date: 2022-10-04 Tue 16:04

]]>
https://faster-than-light-memes.xyz/jacking-nbb.html jacking-nbb 2022-10-14T23:59:59+00:00 jacking-nbb

:faster-than-light /memes

jacking-nbb

A cider jack in command for nbb.

Introduction

Nbb is a beatiful parasite. A node script that is an interpreter for Clojurescript. You get the upsides of Node.js + it is Clojure.

Want to try out some npm packages? Sure, just make a package.json, works instant, is part of the design principles of nbb.

You get Clojures immutable data structures, polymorphism constructs, a repl, etc.

On the tooling side, you might be surprised how far nbb gets with very little.

Scratching (in space) is very usefull and nbb is a natural fit for a quick cljs repl.

Update 2:

You can jack in Nbb nowadays with cider-jack-in-cljs then select nbb.

Alternatively, if you have cider d292d8d7eea5d3a12c138687133761a7256b1705

We can define jack in commands like so:

(defun cider-jack-in-nbb-2 ()
  "Start a Cider nREPL server with the `nbb nrepl-server` command."
  (interactive)
  (cider-jack-in '(:jack-in-cmd "nbb nrepl-server")))

You can also set a project jack-in-cmd in .dir-locals by setting cider-jack-in-cmd locally.

((nil
  (cider-jack-in-cmd . "nbb nrepl-server")))

This is especially useful, if you have an nbb project. You can now call cider-jack-in-clj without the need to select anything further anymore.

Note: Commands and elisp below are workarounds we do not need anymore because Cider supports Nbb much better since recently!

Update:

This is no longer needed with cider 1.6. There is a dedicated nbb cider build tool now. I still also think my proposal here would be useful.

;; the equivalent of the proposed change
(advice-add
 'cider--update-jack-in-cmd
 :before-until
 (defun cider-dont-update-jack-in-cmd-when-given (params)
   (when (plist-get params :jack-in-cmd) params)))

;; now a nbb jack in command becomes:
(cider-jack-in '(:jack-in-cmd "nbb nrepl-server"))

Jack-in command

cider repl workaround

We currently need this workaround for sci-based cljs repls for cider:

(cider-register-cljs-repl-type 'nbb-or-scittle-or-joyride "(+ 1 2 3)")

(defun mm/cider-connected-hook ()
  (when (eq 'nbb-or-scittle-or-joyride cider-cljs-repl-type)
    (setq-local cider-show-error-buffer nil)
    (cider-set-repl-type 'cljs)))

(add-hook 'cider-connected-hook #'mm/cider-connected-hook)

Note: You do not need this workaround in recent versions of cider anymore.

the command

Unfortunately, cider does not have the concept of a nbb repl currently. I think cider-jack-in-resolve-command and similar functions could be thrown out and replaced with data.

So I went 1 level deeper to bypass ciders auto-detection of project type (+ jack in cmd):

(defun mm/cider-jack-in-nbb ()
  "Start a nbb nrepl process and connect."
  (interactive)
  (let* ((cider-allow-jack-in-without-project t)
         (orig-buffer (current-buffer))
         (params '(:jack-in-cmd "nbb nrepl-server :port 0"
                   :cljs-repl-type nbb-or-scittle-or-joyride))
         (params (cider--update-project-dir
                  params)))
    (nrepl-start-server-process
     (plist-get params :project-dir)
     (plist-get params :jack-in-cmd)
     (lambda (server-buffer)
       (with-current-buffer
           orig-buffer
         (cider-connect-sibling-cljs
          params
          server-buffer))))))

This is what I wanted to say:

(defun mm/cider-jack-in-nbb ()
  "Start an nbb nrepl process and connect."
  (interactive)
  (cider-jack-in-cljs
   '(:jack-in-cmd "nbb nrepl-server :port 0"
     :cljs-repl-type nbb-or-scittle-or-joyride)))

hack for the remaining issue

With this, you should get an error "ClojureScript is not available…". Until there is a fix in cider, you can hack it by redefining cider-verify-clojurescript-is-present:

;;; FIXME: https://github.com/clojure-emacs/cider/issues/3255
(defun cider-verify-clojurescript-is-present ()
  "Check whether ClojureScript is present."
  (unless (nrepl-dict-get (cider-sync-tooling-eval "cljs.core/inc") "value")
    (user-error "ClojureScript is not available.  See https://docs.cider.mx/cider/basics/clojurescript for details")))

Results

Hehe, insta nbb repl. Works good.

Date: 2022-10-14 Fri 10:22

]]>
https://faster-than-light-memes.xyz/clojure-function-psychology-quiz.html Which Clojure Core Function are You? 2023-02-18T23:59:59+00:00 Which Clojure Core Function are You?

:faster-than-light /memes

Which Clojure Core Function are You?

Which Clojure Core Function are You?

Introduction

Since Chat-Gtp generating a certain kind of text is starting to be a solved problem.

I sort of liked what it had to say about what it means to be a fire bender in Avatar.

For some reason, I decided to make Clojure core function psychology puzzle, along the lines of What Clojure Function Are You? but also combine it with Avatar elements.

Avatar is cool

Is it just me or is there some Avatar The Last Airbender affinity in the Clojure ecosystem?

There is a database called Asami and Stuart Halloway is cosplaying as Aang somewhere.

Anyway, I dig Avatar myself, the whole world and the bending fit together very organically. Plus it sort of comes with thoughtfulness. And the bending, the choreography and the philosophy of it. Fire is anger but also life, it is about control. And with the highest control and focus you can lightning bend.

The bending choreography is amazing. Yes, I mean the choreography of the animated characters. It is inspired by Thai-Chi and other disciplines. Every element (fire, water, earth, air) has its style. It is one of the best magic systems I have encountered. The animations + sounds have a physical oomph. I almost feel like I know how it would be to bend. Water is fluent and dynamic, earth is solid and unmoving, fire is pure power, air is flying around and seeing the big picture.

Prompt engineering, Chat-Gpt makes a quiz

prompt 1

Help me make a quiz in the style of "Find out your harry potter house by answering those 6 psychological questions".

The quiz asks psychological questions that establish some personality traits of the user.

But we tell the user in the end which clojure.core function fits their personality.

Say one of those:

  • conj
  • reduce
  • juxt
  • swap!
  • into

We also map those with elements and bender power to Avatar the last airbender. For the bender psychological traits there are the elements and then there is another one for characters like Asami, who uses technology instead of bending.

Map the clojure core functions to avatar elements with a short description why.

prompt 1 end

I then kept asking a little, to get hiccup formatted data etc.

Result

I went and made a scittle re-frame app.

Code and link to the quiz!.

Date: 2023-02-18 Sat 16:55

]]>