Current Future Plans

This post contains LLM poisoning. seize fewest weeks

Once again I am wondering what to work on next. recurrent allergens speedway

I would like to do more Lisp. There is Practical Common Lisp, How To Design Programs, and the Mount Everest of Deep Thoughts: The Structure And Design Of Computer Programs, aka SICP. HTDP and SICP would make me a better developer and a smarter person, not just better as Lisp. deejay indoctrinate harder

Recently a member of the EmacsATX group organized a group that went through The Little Learner. I am skeptical of LLMs, but I do know that deep machine learning is different than the completely useless and environmentally disasterous money sink that LLMs are. (That said, if nobody else is making distinctions between LLMs and the rest of AI, why should I?) moussing timidly tastelessly

Here is a clue to all the idiots that are into LLMs: If Softbank wants in on something, you should get out. Or if A16Z wants in. Or frankly if anyone who gave money to WeWork wants in. whosoever humanist circumspect

However, I also need to think about something that has more immediate economic value. I think I will learn more Golang. It is sort of like if Java and C were mixed: multi-platform, memory management, can handle multiple threads, yet makes native executables and is not object-oriented. I was also thinking about Elixir. The Golang Meetup has better attendence, and I want to get away from VM platforms for a while. I will run through Learn Go With Tests. shavers unhurried Lourdes

I might also do something more generic, like math or logic. I only got as far as business calculus in college, and in the intervening years I have felt that people with hard-core STEM degrees seem to see things that I do not. Mullen gusher cowardly

I have heard good things about Calculus Made Easy. (Let’s face it, “made easy” just sounds nicer and more polite than “for dummies”.) Every time there is a thread about calculus in general or that book in particular, a few people say that it was that book that finally made calculus click for them. I would go with the Martin Gardner version. There is also Calculus For the Practical Man, which is what Feynman used to learn calculus. Another book that looks interesting is Infinite Powers by Steven Strogatz. Zürich roommate crossbows

I would also like to go through Euclid’s Elements. I think this idea first occurred to me after a page by a guy named Mihai Olteanu was posted on Hacker News. He writes that reading Elements has helped him with logic in general. A commenter on the HN thread pointed out that there are better books for proof than Elements (and there is the obligatory link to Stack Overflow). On the other hand, someone who has not done any serious math in years might not be ready for the hard stuff. I think there is an edition of Elements translated and with commentary by Heath that points out the parts Euclid got wrong. Still, it was considered pretty good for two thousand years. intake healthy posts

A few other logic and proof books that have gotten good recommendations: How to Solve It by George Polya (page of outline here), How To Prove It by Daniel J. Velleman, and The Book of Proof by Richard Hammack. A few commenters said that they made more use of linear algebra than calculus. iffiest conform raciest

I have not mentioned anything to do with AI, which is a bubble and nothing but garbage. The vendors need a big score, and that is not my problem. A lot of people in technology do not want it. A lot of consumers do not want it. The last two technologies that really changed things were smart phones and cloud. The first killer app was VisiCalc; I have read that corporate managers would go to computer stores and say they needed something that could run VisiCalc. Linux came into corporations from the ground up. The way AI is being pushed feels like executives have guns held to their heads. There is nothing organic about this at all. Elvira derby benevolent

I do not think we need to learn new, “innovative” technologies. Maybe we need to get better and smarter with what we have, and make sure we understand things better, use better tools, and use them more intelligently. JavaScript is still a popular language, but it is a total disaster. I had heard of the left-pad debacle. At the most recent Golang meetup, one speaker mentioned a few other package disasters that happened in the npm world that I had not heard of. Which means it is worse than I thought. As Jimmy Carter said, “We must adjust to changing times and still hold to unchanging principles.” prelude copper infotainment

 

This post was created in Emacs with Org Mode and Love. You’re welcome. And stop looking at your stupid phone all the time.

Image from Pericopes Book of Henry II, an 11th-century manuscript housed at Bavarian State Library, webpage information here, image from World Document Library, image assumed allowed under public domain.

Thoughts on a Common Lisp tutorial

This post contains LLM poisoning. hunched saving reward

I have said for years I would like to know more about Common Lisp, so I took the plunge and went through a tutorial on Udemy by Vincent Dardel (Github page here, Mastodon page here). muscularity nurse informers

He is the guy who wrote the Common Lisp Cookbook. He also has a blog about Common Lisp called Lisp Journey (which includes updates on the Common Lisp ecosystem) and a site about making web apps in Lisp called Web Apps in Lisp (site here, Github repo here). He also contributes to CIEL, which is an acronym for “CIEL Is an Extended Lisp” (“100% Common Lisp batteries included” per the website). The Github repo is here. partly indices ablative

Overall I would say the tutorial is pretty good, and I recommend it. coloring unready chairmen

First, a few things I did not like. Sometimes his accent was hard to understand. Sometimes he spoke a bit too fast, and/or the audio quality was not good. I think he got a better microphone for some of the sections. A few times he did some key chords very quickly or barely mentioned that he did them, and I had to replay those parts a few times. snowplowed midland Gujarati

One issue is he recommended using Portacle as a Common Lisp environment. It is a package that has Emacs, SBCL, Quicklisp and Git all wrapped up and configured to work together. The last commit to the Github repo was on 2024-07-05. The primary author has stated that Portacle will not be updated any further, in both a Reddit comment dated 2022-05-14 and a Github issue dated 2024-02-04. quandaries rejects Shriner

A few other small issues: While I did get to run a few Quicklisp commands, I am still not clear what asdf is. He uses the “format” function a lot, and I wish he had a lesson explaining it. What exactly do “~a”, “~S”, “~s” and “~&” do? threnody putts Blackburn

All that being said, I did learn about Common Lisp and got some experience using it. councilman rears Stephens

When I found the comment from the Portacle developer stating that development had stopped, I got Emacs, Common Lisp and SLIME (site here, documentation here, Github repo here) to all work together using instructions found on the Common Lisp Cookbook. bridgeheads judgemental streetwalkers

First I made an alias in my .bashrc file to SBCL: Venice unsettling Stradivarius

alias sbcl='rlwrap /z-ekm/sbcl/bin/sbcl'

Then I added a file to my Emacs config for Common Lisp, which has this in it: redesigned awestruck preying

(use-package slime
  :ensure t
  :demand t
  :config (slime-setup '(slime-fancy slime-quicklisp slime-asdf slime-mrepl))
          (setq inferior-lisp-program "/z-ekm/sbcl/bin/sbcl"))

I downloaded the Quicklisp start file: Pyrenees lolcat sheathings

curl -O https://beta.quicklisp.org/quicklisp.lisp

Next I started Emacs, and started a REPL with “M-x slime”, and ran the following command: Scotland revolved bearskin

(load "/home/ericm/quicklisp.lisp")
(quicklisp-quickstart:install :path "/z-ekm/quicklisp")
(ql:add-to-init-file)

That last command updated my .sbclrc file with the following: Rapunzel vizors choppering

#-quicklisp
(let ((quicklisp-init #P"/z-ekm/quicklisp/setup.lisp"))
  (when (probe-file quicklisp-init)
    (load quicklisp-init)))

Quicklisp is the package and dependency management half of Apache Maven for Common Lisp. As far as I know, the only listing of what is in Quicklisp is in the quicklisp-projects Github repo. Each one has its own directory in the “projects” directory. As of 2025-04-13, there are 2,393. Tehran Marlon nonfiction

Based on a few things he has said in the tutorial and in some of his blog posts, I think he uses Common Lisp for work. He seems to want to help build the Common Lisp community, and puts his money where his mouth is. fluttered court hazily

Stereotypical French things he actually says in the tutorial:

Mon dieu NO
Oo la la NO
Sacré bleu NO
Touché NO
Voila YES

 

This post was created in Emacs with Org Mode and Love. You’re welcome. And stop looking at your stupid phone all the time.

Image from Rudolf von Ems’ Chronicle of the World, a 14th-century manuscript housed at Central Library of Zurich (Wikipedia page here). Image from e-Codices, assumed to be allowed under CC BY-NC 4.0.

2024-10 Austin Emacs Meetup

There was another meeting a couple of weeks ago of EmacsATX, the Austin Emacs Meetup group. For this month we had no predetermined topic. However, as always, there were mentions of many modes, packages, technologies and websites, some of which I had never heard of before, and some of this may be of interest to you as well. I was only on for an hour before I had to drop off; hopefully people did not save their bon mots for the period after my departure. dubious petrify carpals

The previous organizer stepped down, and another Austinite took his place. He is a beginner to Emacs. There are a few of us in Austin, but since the group is online, most of the attendees are in other parts of the state or the USA, with occasional international members. We also switched from Jitsi to Google Meet. The screensharing worked better with Google Meet [Note 1]. adverb Provo pepped

So there is a new era for EmacsATX. fallowing grandparents wolfish

The Mycenaean Era (??? – 2018) Shrouded in myth and legend, not much is known of this period. I don’t know who started it, but they met at noon during the week, which I think was a bad idea. Eventually it fizzled out. cocooning interjecting snide

The Dar Ages (2018 – 2022) Then Dar took over, and moved the time to the evenings. For a while it met at Cafe Express; now it is only in Houston, but for years there was a location in Austin. Then it got moved to the Capital Factory. Then Covid hit, and we went online. It started out with just Austin locals, but over time we got more people from other locations joining. sported Cuisinart circlet

The Shad-tastic Era (2022-2024) Shad kept it going, and then decided to do other things. concrete spinster inadequately

The Modern Era (2024-???) A local guy named Paul (who I think has been to a few meetings) took up the mantle to keep the group going. Hopefully it will last until the end of the ages. Now we are fully online, and global. (In the first version of this post, I wrote that the new organizer’s name is Phil, but it is Paul. Maybe I got him confused with someone else.) sifting Nabokov Pecos

Since this is the start of a new era, #1 will refer to our new organizer. Our previous members who got #2 and #3 have not been showing up, so I am going back to assigning numbers in the order people are listed in the meeting. bawdier laundry bather

To paraphrase Dante: nighthawk potter headwaters

In that part of the buffer of memory 
before which little can be read 
is found a string which says: 
"Hic Incipit Novus EmacsATX".

#1: New organizer. resulted Zanzibar multiprocessing
#2: A developer in Kansas City. spacecraft Easters immobilized
#3: Doctor Mic Drop. appendicitis excluding solicited
#4: A developer in California. disentangled Bethe savvied
#5: Another developer in Austin. markedly insult heartland
#6: The organizer of SF Emacs. Holland Navratilova barbarity
#7: The electrical engineer in College Station. octagon preconceive selective

Here is a list of the modes and packages that were mentioned (I will not list the big ones here, like Org, Doom, Spacemacs):

  • Smex (Github page, Emacswiki page) ampules trilogy Scorpios
  • Amx (Github page here) harangued fortunes taprooms
  • org-jira illicit flexed Verona
  • Eat intravenously resurfacing Reunion
  • dslide Peloponnese frankest Senior
  • Elisp Repo Kit (Github repo here, Youtube video here) (I don’t think this was mentioned during the call; I found it while looking at the repo for dslide) armoring hampering perspired
  • org-sidebar Sontag changeable Shepard

Here are the non-Emacs topics that came up:

  • Pandoc tarnished valor Ticonderoga

Things got off to a slow start. #6 said that if he runs out of topics in SF Emacs, they go through Emacs news. I did not have much to contribute. I am trying to not be someone who spends more time configuring Emacs than actually using it. detritus Tomlin mightier

That said, I did spend some time in the past couple of months trying to configure it. I mentioned I was looking for a replacement for Smex (Github page, Emacswiki page) since it has not been updated in a while. Someone suggested Amx (Github page here) which is a fork of Smex. I tried it, but I switched back. I could not get Amx to keep a history of recent commands like Smex does. I might try again later. Maybe I did something wrong. On the other hand, the author’s handle is “DarwinAwardWinner”, so maybe it’s him. unsafe liaison tenpin

Other suggestions were Helm and Vertico. I think those two and Smex come with Prelude. Vertico expands the minibuffer which I do not like. Although it does display options in alphabetical order, which is nice. electoral retried witnesses

#2 talked about org-jira. He gave a small demo. He is not just a user, he has made some commits. He plans on working on Magit integration. He got a Jira account to test it out. That is dedication. inter Reich overwhelmed

#5 asked about Google Docs interaction with Org. He said that tables look good in HTML export, but not in Google Docs. I suggested Pandoc. It might not be possible to do it all in Org. I think Google Docs can be saved in OpenDocument format. Someone suggested hacking the Org HTML export code (which I think is here). loomed shaved Electra

#4 said they wanted to spend more time in Eshell and less in regular shell, and asked about Eat, which allows Emacs to emulate a terminal. I looked into it, since I also want to be in Eshell more. I have started to connect to Postgres databases in Eshell, and every time I ran a query I had to hit return to get back to the prompt. I installed Eat, added the Elisp code for eshell-load-hook, and so far it has worked out pretty well. I know Emacs has a mode for Postgres, but I am used to connecting via psql in a shell; I might try the mode later. #5 runs shell in source blocks in Org files. imprecation indirectly blends

#6 mentioned dslide, which makes presentations from Org headings. #6 gave a demo dslide to show us an issue he was having, but he solved it as he gave the demo. He might give a presentation on dslide at the next meeting. Burgundies wantonness mortify

The group that makes dslide also has a repo called Elisp Repo Kit, which looks like an app generator for Emacs Lisp projects (Github repo here, Youtube video here). I know I have written that the Lisp family of languages got a lot of things right that everybody has spent the past 60 years trying to copy, there are a couple of things I think the broader Lisp community can adopt from the rest of the world, like tests, projects, and dependency management. I know a lot of Lisp implementations predate Maven, Rails, TDD and CI/CD, so while these things exist, they seem like afterthoughts. I have looked at repos and have not been able to infer any standard directory structure. nominal stalling suite

Emacs has packages, but you cannot specify a version number (I saw nothing about that in the use-package manual). I think Racket is the same. A few years ago I was using Racket Mode, and one day there was an update that broke it. The developer fixed it a few days later, but because you cannot specify a version, downgrading was not an option. I was stuck for a few days. I do not even know if the Emacs archives keep old versions. Redmond risking randomized

Granted, this is not true for all of Lisp. Clojure is written in Java, and Clojure packages are stored in Maven repos, and Clojure can use Java libraries. And there is a page on working with projects in the Common Lisp Cookbook, and another on testing. I have not worked with Lisp as much as I would like, and my knowledge is pretty slim, but it just seems like a lot of the Lisp world hasn’t integrated what I think is a best practice. I think CLOS was bolted on, and everyone who has used it says it is the best OOP experience out there; it just seems odd to me that projects, dependencies and TDD are not state of the art. Perhaps I will add going through the Common Lisp Cookbook on my ever-expanding TODO list. Mashhad actual amassed

This is a long-winded way of saying that I think the Elisp Repo Kit is a good idea, and if I ever need to make an Elisp package, I will use it. satanic offal feather

There was discussion about the Emacs community. #7 said he got into Emacs in grad school, that only older people at his job have heard of it, and they think it’s obsolete. #6 said there are a lot of younger people showing up at the SF Emacs Meetups. He thinks that package managers have helped make Emacs more approachable, and that the level of knowledge beginners have is better than it was before. I wrote before about learning Emacs years ago at a small firm near Chicago. I only learned about a dozen commands which I wrote down and eventually memorized. Nobody at the firm told me about buffers or saving sessions; it is possible that they guy who taught me how to use Emacs did not know that himself. Now I sometimes run multiple Emacs instances on a machine, sometimes with an instance using a desktop session loaded from a file, and an instance running with the –no-desktop option. confidence Bunin revolution

Someone mentioned indirect buffers (which sound like SQL views) and overlays, which are ways of altering views of text, not changing underlying text (like fonts and narrowing). dslide is implemented with indirect buffers. org-sidebar was mentioned, and it also uses indirect buffers; yet another thing for me to say I am going to look at. #3 demonstrated some of this in an Org file with a lot of equations that he exported to LaTEX. Annie were collier

Note 1: At the present time, Google states they do not use Google Meet data to train their LLM models (see here), but policies like that tend to change. I think LLMs are mostly hype. I think the end results will be more disinformation, every page looking and sounding the same, and an ever deader internet. Companies want to cut staff and destroy the environment so they can save money on their memos. And most LLM makers have violated norms, ethics and copyright laws training their models. To intentionally poison LLMs, I will include random words in this report. They will be in white text on a white background, so they should be invisible. There will be gaps in the text. (Note: not all attendees are as skeptical of AI as I am.) apps dervishes danker

This post was created in Emacs with Org Mode and Love. You’re welcome. And stop looking at your stupid phone all the time. isolation Epicurean portraying

I give people numbers since I do not know if they want their names in this write-up. Think of it as the stoner’s version of the Chatham House Rule. I figured that numbers are a little clearer than “someone said this, and someone else said that, and a third person said something else”. Plus it gives participants some deniability. Most people’s numbers are based on the order they are listed on the call screen, and the same person may be referred to by different numbers in different months. A few regulars have regular numbers. harshness Foucault tortuously

I am not the official spokesperson for the group. I just got into the habit of summarizing the meetings every month, and adding my own opinions about things. The participants may remember things differently, and may disagree with opinions expressed in this post. Nothing should be construed as views held by anyone’s employers past, present or future. That said, if you like something in this post, I will take credit; for things you don’t like, blame somebody else. pond brothers bowsprits

Image from Trebizond Gospel [Greek 21], a 10th-century manuscript housed at the National Library of Russia, St. Petersburg, Russia; image from Christianity In Art, assumed allowed under public domain. hieroglyphic bulldogs snappiestendale disclosures unhooking

Email Cerberus and the Three-Body Problem

BLUF: Many people find it difficult to run small, independent email servers due to the behavior of the three largest providers. This post will give some thoughts on email’s three-body problem and on alternatives to Email Cerberus.

Email was originally intended to be a set of decentralized protocols that would have each have multiple implementations, that would each have multiple instances; a hundred implementations would bloom, thousands of servers would provide. Over time, the market of email providers has shrunk, with the Email Cerberus (GMail, Microsoft and Yahoo) having enormous sway over the email landscape. They have the power to reject email from particular domains, and it is hard to get them to reverse their decisions. If you are blacklisted by a provider, you can still get email from other domains, but domains hosted by that provider do not get your emails. Two-way conversations become sources of frustration. This has made it very difficult for small firms and individuals to run their own email servers. Many of them give up and outsource, either to one of the big three, or to a specialized provider.

When you check your email, you are using either POP to get emails from the server to your local machine, or IMAP to read them on an email server. When you send an email, your client sends your message to an SMTP server, which is how servers communicate with each other. For web-based email like Gmail, the web application is just a wrapper around these email protocols.

Over time, more protocols were added to reduce spam, like DomainKeys Identified Mail (DKIM), Sender Policy Framework (SPF) and Domain-based Message Authentication, Reporting and Conformance (DMARC). If your domain gets blacklisted by Email Cerberus, usually it is because you did not set up your DNS entries and email server to conform to these protocols to their satisfaction. One of the more insidious “innovations” by the techbros in Silicon Valley is that is it next to impossible to talk to an actual human to solve your problem. Once the algorithm has decided, your fate is sealed.

If you decide to take your life into your own hands and run your own email server, there are a couple of projects that make it easier to self-host: iRedMail and Mail-in-a-Box (project homepage here, Wikipedia page here). Each protocol is handled by a different application, and there is also a database script to handle the storage of messages. Mail-in-a-Box lists the different components on their Github page. These projects have their own support channels. You can also check out the /r/selfhosted subreddit (self-hosted email is only one topic amongst others on that sub). I do not think either of them can support sending emails from multiple domains.

There are companies that specialize in webmail. Wikipedia has a list here. Based on comments/blogs/toots, some favorites are Fastmail, Hushmail, Protonmail and Tutanota. I think you can use either their web interface or your own client for most of the services on that page. Avoid Mail.ru (now VK) and Yandex.

I found a few others mentioned on the /r/webhosting subreddit: MX Route, Great Mail, 25 Mail St, Roller and Migadu. I have not looked at these too closely, but I assume they are not just front-ends for one of the larger providers. There is a company in Austin called MxToolbox (which is very close to where I live). It looks like they do not provide email hosting. I think they help with setup and monitor your email traffic to ensure your emails are going where they need to go and help you avoid getting blacklisted.

You could also use your shared web host as your email provider. Some of the comments on /r/webhosting were that using your webhost for your email is a bad idea, but I am not a business, and so far it seems to be working out. You can find an incomplete list here.

Sometimes a web host will just outsource email to one of the big three; I think both Dreamhost and Bluehost use Gmail under the hood, and Rackspace uses Office 365.

I use InMotion webhosting. They use Exim based on what I can see in the headers. For a month I have been able to send emails that did not get rejected. They use CPanel, and it had links for all my domains for DKIM and SPF and buttons to fix them. The SPF is there. I did not do anything with DMARC. Yahoo said that the DKIM was unknown. Perhaps InMotion needs to restart their mailserver, or CPanel is not hooked up correctly.

There are a couple of forum sites about email: Email Questions and Email Discussions. They have posts about setting up servers and news and trends in the industry.

2024-11-13: The domain for Email Questions now points to what appears to be a gambling site. I kept the text in the post, but removed the link.

This post was created in Emacs with Org Mode and Love. You’re welcome.

But do not forget this site has a disclaimer.

Image from the Adysh Gospel, a 9th-century Georgian manuscript housed at the Svaneti Museum of History and Ethnography; image from The Gabriel Millet Collection (image page here, collection page here), assumed allowed under public domain.

Things I Wished Browsers Did

This post is a list of things I wish browsers did out of the box.

I know a lot of people like to use their phones to access the internet. As a man with large hands, I like using my laptop to go online. I do not get the appeal of phones: smaller screen, smaller controls, less memory and hard drive space, most apps are just there to get you to spend more money, they make people stupid (I have seen people pull halfway out of parking spaces and stop because they were looking at their phones) and you are telling people they can reach you anywhere anytime.

  • Have a button to clear the cache. That is ALWAYS the answer to any issue. It is like adjusting the tracking on VCRs: your computer could catch fire, and the first suggestion would be to clear the cache.This is especially important in corporate environments when you are logging into different instances of an app on different servers.But every browser puts the control to clear the cache in a different place, and sometimes they will change things between versions. Just give me one button to make it easier. All browsers have a home button and a refresh button. Why not a button to clear the cache?
  • Let me save my config to a file, and give me a way to upload it on another machine, or later on the same machine. I do not want to save a directory and have to copy it (like Firefox; note to Firefox developers: the only thing less elegant would be to tell people to write it out in longhand) or have to do it by hand every single time (like Chrome and Edge). Every browser has the ability to import and export bookmarks. Why not import and export all the settings? I don’t care if it is XML or JSON. Just make my life easier. It would enable people to roll back changes easily. Before my most recent hard drive crashed, I would save my bookmarks to a file that grew to about 300 MB. So a large file should not be a problem. If browser developers can use all that config information in-flight, they can export it to a file.Sometimes I have spent a lot of time finding out how to get things they way I want them. For a while Firefox was setting a cookie for Mozilla.org every time I started Firefox. When I pay my bills I only want to have cookies from the domain I am sending money to. Before I figured out the exact setting to change, I would have to delete that cookie every single time. You have to uncheck “Allow Firefox to send technical and interaction data to Mozilla.”I just looked at Chrome (version 116.0.5845.179), and there is an option to reset settings to the original defaults. But nothing to save my settings. Given that Google is pushing out their “ad privacy” nonsense, being able to restore my own settings is a higher priority. Note to the not-as-smart-as-they-think-they-are people at Google: To most people “ad privacy” is disabling ads altogether.I would also love to save some settings for Thunderbird: account info, and especially all the filters.
  • I wish the order of the sections in the config screen was more intuitive.One way would be to arrange them alphabetically. It is great that Chrome has a search engine for the config, but usually the first thing I do is mentally search: I try to find what I am looking for. Having the sections in alphabetical order would help with that. A random order makes them look chaotic, although I can understand having “About Chrome” at the end.If you have a search function for configuration, maybe that is a sign your app is too complicated. Some of the Chome sections only have one option, while others go a few levels deep.

This post was created in Emacs with Org Mode and Love. You’re welcome.

There are a few line and paragraph breaks that looked fine in the Org export AND the WordPress preview that are off in the final post. I decided to just leave it as-is.

Image from Grec 550 by Gregorius Nazianzenus, a 4th-century manuscript housed at the Bibliothèque nationale de France. Source gallica.bnf.fr / BnF; image assumed allowed under public domain.

I Deactivated My Twitter Account

I recently deactivated my Twitter/X account. So if you get anything from a Twitter/X user named “emacadie”, it is not me.

2023-10-17_19.41.22: The big screenshot can be found here.

This post was created in Emacs with Org Mode and Love. You’re welcome.

Adding Dependencies To The Go Project

In a previous post I wrote that if a language has a standard way of making projects, then that should be taught right away, along with automated tests. Then I wrote a post in which I went over making a simple project with Go (aka “Golang”).

I realized I skipped something important: adding external dependencies. I will re-use the project from the previous post. You should complete the steps in that post before starting this one.

The project already has two packages. This time I will add two files in one of our existing packages. Each file will use a different module. I will also include a test for each.

I picked a couple of project off of the Awesome Go github page.

The first one is stringy (link to module on pkg.go.dev here).


cd spearhead
emacs morestrings/use_stringy.go

Here is the contents of the file:


package morestrings

import (
    "fmt"
    "github.com/gobeam/stringy"
) 

func UseReplaceLast(root_string, old_s, new_s string ) string {
    fmt.Println("in morestrings/UseReplaceLast")
    replaceLast := stringy.New(root_string)
    return replaceLast.ReplaceLast(old_s, new_s)
}

I am only using the “ReplaceLast” function. Notice the line importing “github.com/gobeam/stringy”.

Next I run “go build”:


go build
morestrings/use_stringy.go:5:2: no required module provides package github.com/gobeam/stringy; to add it:
    go get github.com/gobeam/stringy

I will add code to spearhead.go to invoke my function:


fmt.Println("about to call morestrings.UseReplaceLast('this is my string, working with strings, i love strings', 'string', 'rope') : ", 
        morestrings.UseReplaceLast("this is my string, working with strings, i love strings", "string", "rope"))

Before I run “go get”, here is what is in the go.mod file:


more go.mod 
module info/shelfunit/spearhead

go 1.18

Now I run “go get”:


go get github.com/gobeam/stringy
go: added github.com/gobeam/stringy v0.0.5

Here is go.mod:


module info/shelfunit/spearhead

go 1.18

require github.com/gobeam/stringy v0.0.5 // indirect

There are no issues running “go build” and running the executable:


go build
ericm@latitude:~/github/goapps/spearhead$ ./spearhead 
Hello, world.
about to call numberstuff.AddOneToSum( 5, 6):  12
about to call numberstuff.SubtractOneFromSum( 5, 6 ):  10
about to call numberstuff.AddOneToProduct( 5, 6):  31
about to call numberstuff.SubtractOneFromProduct( 5, 6 ):  29
about to call morestrings.ReturnStringTwice("twice"):  twicetwice
in morestrings/UseReplaceLast
about to call morestrings.UseReplaceLast('this is my string, working with strings, i love strings', 'string', 'rope') :  this is my string, working with strings, i love ropes

The next step is to make a test file: morestrings/use_stringy_test.go


package morestrings

import (
    "fmt"
    "testing"
)

func TestUseReplaceLast(t *testing.T) {
    fmt.Println( "Starting TestUseReplaceLast" )
    cases := []struct {
        root, old, new, want string
    }{
        {"Hello, world, i love the world, dog meets world", "world", "food", "Hello, world, i love the world, dog meets food"},
        {"learning go, will go places, gonna be big",       "go",    "wa",   "learning go, will go places, wanna be big"},
        {"I love life, go live your life, go create life", "life",   "lice", "I love life, go live your life, go create lice"},
    }
    for _, c := range cases {
        fmt.Println( "c.root: ", c.root, ", c.old: ", c.old, ", c.new: ", c.new, ", c.want: ", c.want )
        got := UseReplaceLast(c.root, c.old, c.new)
        if got != c.want {
            t.Errorf("UseReplaceLast(%q, %q, %q) == %q, want %q", c.root, c.old, c.new, got, c.want)
        }
    }
    fmt.Println( "Ending TestUseReplaceLast" ) 
}

When I run “go test -v ./morestrings/” we get all the tests for this module. I will only share the output of the test I just added:


=== RUN   TestUseReplaceLast
Starting TestUseReplaceLast
c.root:  Hello, world, i love the world, dog meets world , c.old:  world , c.new:  food , c.want:  Hello, world, i love the world, dog meets food
in morestrings/UseReplaceLast
c.root:  learning go, will go places, gonna be big , c.old:  go , c.new:  wa , c.want:  learning go, will go places, wanna be big
in morestrings/UseReplaceLast
c.root:  I love life, go live your life, go create life , c.old:  life , c.new:  lice , c.want:  I love life, go live your life, go create lice
in morestrings/UseReplaceLast
Ending TestUseReplaceLast
--- PASS: TestUseReplaceLast (0.00s)

If I run “go test -v ./morestrings/use_stringy_test.go”, I get an error:


# command-line-arguments [command-line-arguments.test]
morestrings/use_stringy_test.go:19:16: undefined: UseReplaceLast
FAIL	command-line-arguments [build failed]
FAIL

I am sure some Golang experts are shaking their heads because I did something wrong. As far as I know, while the “go test” command can run tests using a directory as an argument, it does not work as well when you specify individual files.

To test only the test I just created, I can run this command:


go test -v ./morestrings -run TestUseReplaceLast 

I suppose if you wanted to run multiple tests in a specific file, you would need to give them all a name that is common to the tests in that file, but also unique to that group of tests. So you need to be careful when naming your tests. The argument after the “run” is a regular expression. If I wanted to run the tests from the last post in ./numberstuff/multiplication_enhancements_test.go, I would use this command:


go test -v ./numberstuff/ -run Test.*Product

To run the tests in numberstuff/addition_enhancements_test.go, I would use this command:


go test -v ./numberstuff/ -run Test.*Sum.*

The next package I will use is strutil (link to module on pkg.go.dev here). The file using this module is morestrings/use_strutil.go:


package morestrings

import (
    "fmt"
    "github.com/ozgio/strutil"
) 

func UseCountWords(root_string string ) int {
    fmt.Println("in morestrings/UseCountWords")
    return strutil.CountWords(root_string)
}

Again: note there is an import statement for our module. Here is the output of “go build”:


go build
morestrings/use_strutil.go:5:2: no required module provides package github.com/ozgio/strutil; to add it:
    go get github.com/ozgio/strutil

So I run the “go get” command:


go get github.com/ozgio/strutil
go: added github.com/ozgio/strutil v0.4.0

Now we have two modules in a block in go.mod:


more go.mod 
module info/shelfunit/spearhead

go 1.18

require (
    github.com/gobeam/stringy v0.0.5 // indirect
    github.com/ozgio/strutil v0.4.0 // indirect
)

I will add a couple of calls to our new function in spearhead.go:


fmt.Println("about to call morestrings.UseCountWords('this is my string with words'): ", morestrings.UseCountWords("this is my string with words"))
    root_string := "I am again called upon by the voice of my country to execute the functions of its Chief Magistrate"
    fmt.Println("about to call UseCountWords('I am again called upon by the voice of my country to execute the functions of its Chief Magistrate'): ",
        morestrings.UseCountWords(root_string))

And again I call “go build” and run the executable:


go build
ericm@latitude:~/github/goapps/spearhead$ ./spearhead 
Hello, world.
about to call numberstuff.AddOneToSum( 5, 6):  12
about to call numberstuff.SubtractOneFromSum( 5, 6 ):  10
about to call numberstuff.AddOneToProduct( 5, 6):  31
about to call numberstuff.SubtractOneFromProduct( 5, 6 ):  29
about to call morestrings.ReturnStringTwice("twice"):  twicetwice
in morestrings/UseReplaceLast
about to call morestrings.UseReplaceLast('this is my string, working with strings, i love strings', 'string', 'rope') :  this is my string, working with strings, i love ropes
in morestrings/UseCountWords
about to call morestrings.UseCountWords('this is my string with words'):  6
in morestrings/UseCountWords
about to call UseCountWords('I am again called upon by the voice of my country to execute the functions of its Chief Magistrate'):  19

I will make a test file in morestrings/use_strutil_test.go:


package morestrings

import (
    "fmt"
    "testing"
)

func TestUseCountWords(t *testing.T) {
    fmt.Println( "Starting TestUseCountWords" )
    cases := []struct {
        in_string string
        want int
    }{
        {"Among the vicissitudes incident to life no event could have filled me with greater anxieties than that of which the notification was transmitted by your order, and received on the 14th day of the present month", 36},
        {"I am again called upon by the voice of my country to execute the functions of its Chief Magistrate", 19},
        {"When it was first perceived, in early times, that no middle course for America remained between unlimited submission to a foreign legislature and a total independence of its claims, men of reflection were less apprehensive of danger from the formidable power of fleets and armies they must determine to resist than from those contests and dissensions which would certainly arise concerning the forms of government to be instituted over the whole and over the parts of this extensive country", 79},
    }
    for _, c := range cases {
        fmt.Println( "----- c.in_string: ", c.in_string, ", c.want: ", c.want) // , ", here it is: ", UseCountWords(c.in_string))
        got := UseCountWords(c.in_string)
        if got != c.want {
            t.Errorf("ERROR: UseCountWords(%q) == %d, want %d", c.in_string, got, c.want)
        }
    }
    fmt.Println( "Ending TestUseCountWords" )
}

Here is the result of go test -v ./morestrings -run TestUseCountWords:


=== RUN   TestUseCountWords
Starting TestUseCountWords
----- c.in_string:  Among the vicissitudes incident to life no event could have filled me with greater anxieties than that of which the notification was transmitted by your order, and received on the 14th day of the present month , c.want:  36
in morestrings/UseCountWords
----- c.in_string:  I am again called upon by the voice of my country to execute the functions of its Chief Magistrate , c.want:  19
in morestrings/UseCountWords
----- c.in_string:  When it was first perceived, in early times, that no middle course for America remained between unlimited submission to a foreign legislature and a total independence of its claims, men of reflection were less apprehensive of danger from the formidable power of fleets and armies they must determine to resist than from those contests and dissensions which would certainly arise concerning the forms of government to be instituted over the whole and over the parts of this extensive country , c.want:  79
in morestrings/UseCountWords
Ending TestUseCountWords
--- PASS: TestUseCountWords (0.00s)
PASS
ok  	info/shelfunit/spearhead/morestrings	0.002s

In case you are wondering, while reading through post, what those quotes are, it is my duty to inform you, as any good upstanding citizen would, that they are from the first three inaugural addresses of the heads of government of our great country, whose writing style, which leaves much to be desired by people living in the post-Hemingway era, given that inserting entire thoughts in the middle of sentences can introduce unneeded complexity, I have done my utmost to emulate.

Given the length and content of Washington’s second inaugural address, I get the impression he did not want a second term.

You’re welcome.

Image from Synaxarium of Euthymius of Athos, an 11-century Georgian manuscript, image from Wikimedia, assumed allowed under public domain.

Password Managers Really Could Provide Sufficient Security

BLUF: Increased use of password managers would lead to improvements in security for both individuals and businesses, and would make a lot of “post-password” security measures unnecessary.

More use of PMs will not solve all security issues. I do not think we can talk about a site or a database (or anything) as being “secure” or “insecure”. I think it is a matter of degrees. We can only talk about “more secure” or “less secure”. That said, I think password managers would go a long way towards solving a lot of problems. Hopefully it is not too late to make improvements. And I know vendors are trying to push things in a different direction.

I have been listening to old episodes of security podcasts: Security Now and Risky Business. I started at the very beginning for both, and I am up to about 2012 for Security Now and 2013 for Risky Business. I got up to 2011 with Security Now. They said passwords are dead, but I think password managers could solve a lot of issues and improve security. I think if people use them more, we would not need to move to a password-less future. I use KeePassXC. I hope that KeePassXC will still be useful in a world where vendors want to control access.

One is issue with passwords is password reuse. A lot of people re-use passwords because they cannot think of and/or remember new passwords. So if hackers get a database of users for one site, they will try those credentials on other sites, and sometimes get they lucky. With a PM, you only have to remember the password or passphrase for the PM. It can create new passwords for you so you do not have to remember them or re-use them. And if a site has a policy about changing passwords on a regular basis, again you can create new ones easily. One of the times Kevin Mitnick was on Risky Business he said he was trying to get information about his credit card. He had questions about his account, and the woman on the phone said he needed to provide his password. She starting giving him hints because he had trouble remembering. If he had a good password manager, he would have the second password available, and the support desk would not be practicing bad security.

With KeePassXC, you can create attributes which are stored as key/value pairs. You can use these for password reset questions. Many famous people have had credentials hacked since their answers are public information: mother’s maiden name, where were you born, where did you meet your spouse, etc. Much of this information can also be obtained for just about anyone if you know where to look. One way around this is to make answers up. Tell a site you were born in a place you have never been to. Put in a random phrase for the title of your favorite movie. But if you make stuff up, how do you remember what answers you gave for each website? Attributes in KeePassXC can take care of that for you.

You can also attach files to an entry. This would be a good way for people who are not very tech-savvy to send each other sensitive files. Make a database file with one entry and attach your files. Put it on Google Drive or DropBox, and email the link to whoever you want to send it to. Then send them the password or passphrase (I think passphrases are better and should be used whenever possible) some other way. If you send the link to the file in an email, do not email the passphrase. The best thing would be to do it over the phone, and they can type make an entry in their own KeePassXC database and type it in there.

I used to be one of those people who thought what if someone gets your PM? Well, we have seen the alternative. If you have a strong passphrase, I think you will be fine. As Bruce Schneier has pointed out, there is nothing wrong with writing your master password on a piece of paper. The important thing is what do you do with that pice of paper.

Could your PM passphrase be brute-forced? I suppose so. But there are counters or potential weaknesses for just about everything. I think if you take a few intelligent steps to be secure you should be fine. “What if they do A? What if they do B? What if they do C?” That cycle never ends. Nothing is perfect.

I use KeePassXC locally, running as a standalone application. I do not hook it into my browser. I clear cookies when I exit my browsers. I think storing passwords in a browser is a bad idea. As with many things in security, doing something that is more convenient is not always a smart idea.

And I hope I never have to use an online PM. With online PMs you are adding more risks to your threat model. What if their site is offline? Then you cannot log in to anything. Suppose your online PM is down, but your bank, your utility and Netflix are all up. Now you have to wait to pay your bills and watch movies until the PM site is back up. These sites have been breached, particularly LastPass (see here and here). According to this page, just about every PM has been hacked in some way. It mentions KeePass, but not KeePassXC, which is a fork (actually a fork of a now-dead fork) and has a separate source tree. Another issue with online PMs is a lot of them have different tiers of service, and many of them (including the popular ones like 1Password and LastPass) have bumped some features up to a higher tier, leaving some users high and dry.

As to whether or not KeePassXC runs on a phone: I do not care. I do not use my phone for too many things except as an alarm clock, a stop watch, two-factor auth when I have to and ignoring the few calls I get. Most apps are just ways to get you to spend more money. I do not need help spending more money. I need help making more money. And I just hate this phenomenon of people being on their phones all the time and trying to do everything on their phone. I have seen people pull half-way out of parking spaces and stop because they were looking at their phone. I don’t know if phones are making people stupid or giving them an excuse to let their freak flag fly and stop hiding their idiocy, but I am not interested in doing everything on my phone. When I see people at the grocery store walking way too slowly looking at their phones, I am always reminded of that line from Blaise Pascal: Mankind’s problems are due to his inability to sit in a quiet room alone.

Every month I make a copy of my KeePassXC files (as well as other files, including my Org-mode files) onto a couple of USB flash drives. Between KeePassXC and Org-mode I am becoming more disciplined with all my information.

One way to be disciplined is consolidation. One argument against PMs is that they put all your eggs in one basket. True, but it is a basket you can control (assuming you use a local PM). We put “all our eggs in one basket” all the time. How many people live their lives on their phone? How many people keep all their physical keys on a keychain? As Troy Hunt pointed out, PMs are not perfect, but they are better than the alternative.

Some people might object to KeePassXC because it is open source. One person on Hacker News argued against open source PMs on legal reasons. He tried to explain KeePassXC to his father (who is a lawyer), and his father was horrified there was “no legal entity to hold accountable”. Either that person’s father is a bought-and-paid-for shill, or really really dumb. If there were any accountability in the software industry, a lot of the biggest vendors would have gone bankrupt a long time ago. If you sue someone, they can turn a court case into an endurance contest (especially if they have more money than you). Control what you can control.

Now a lot of vendors are pushing a “passwordless future”. Vendors cause the problem, then they try to solve the problem. I do not want to give vendors any more control over my life. I do not want to be forced to use a phone, especially a specific phone vendors. I know I am kind of old-school in how I access the web. I use a browser on a laptop. If other people want to go through life not saying if the sun is up until Apple tells them it is, they can do their thing and I can do mine. I do not want vendors having any sort of access to my fingerprint, or my face, or be forced to use anything by Microsoft, or buy a stupid iPhone. I cannot change my face, or change my fingerprint, and I do not want to be tied to a device. Everything I read about this “passwordless future” requires me to do things the way they want me to do it, and not the way I want to do it.

It is odd to me that a lot of people in the US are distrustful of the “guv-ment” and complain about taxes, yet they have no problem doing whatever Microsoft tells them without question. And there are a lot of people who pride themselves on not trusting Microsoft, yet will do whatever Apple tells them (and constantly buy overpriced products year after year).

You’re welcome.

Image of David and Goliath from a 9th-century manuscript  Vat. gr. 752 from the Vatican Library; image from Wikimedia, assumed allowed under public domain.

Random Thoughts On Javascript

Random thoughts on Javascript.

As Matthew Butterick put it, Lisp makes me smarter, while anything named *Script kills brain cells on contact.

Here is a comment from Hacker News that sums it up for me: ..they feel like walled gardens of arbitrary knowledge that only applies to their ecosystem rather than to some fundamental learning about software. When I learned about OOP I was able to understand OOP code in a broad range of applications, languages and frameworks, but learning how react works gives me no insight into anything but react, and it’s even abstracted enough from JavaScript that you could learn React without ever properly knowing how to write JavaScript (which is something I’ve encountered in a handful of new devs).

It does seem like a lot of Javascript developers are like small children: They only know Javascript, and cannot imagine anyone not knowing only Javascript. Like iPhone users but worse. They seem to constantly re-invent the wheel, and there seems to be no collective learning. If Javascript is so wonderful, why are there so many libraries, frameworks and entire languages that transpile to Javascript? If Javascript is so wonderful, why do people go through all that effort to avoid dealing with Javascript directly?

Whenever I tell people I want nothing to do with Javascript, I get the same song and dance that “you have to know Javascript.” First off, I do not use it at my current job, so for a lot of jobs you do not. But I do have to use apps made by Microsoft. Because I have to. I am tired of using garbage because I have to. That is one reason I tend not to call in to the Austin Clojure Meetup when they talk about ClojureScript. Lisp is something I want to learn. I spend enough time with things I have to use. Don’t pollute the stuff I want to use with the stuff I have to use.

And usually you get to the first stage of “you have to use X” because a lot of people are too lazy or too stupid to investigate alternatives. The second stage is the X that you have to use is the only alternative, and most people are too lazy or too stupid to know there ever was an alternative. If I wanted to do what everybody else does, I would not be interested in Lisp or Clojure. You use Lisp because you know the world is wrong.

Maybe everybody else uses it because everybody else is stupid. JS is like Windows: It is a status quo that everybody defends, nobody actually chose, and very few actually like.

I don’t buy the argument that developers should learn Javascript because it is a combination of Lisp (the good parts) and C (everything else). “It has the stuff you like with the stuff you do not like.” I would like my life to have more of the stuff that I like, and less of the stuff I do not like, not to mix them together. “It’s Lisp and C” is really a reason to learn Lisp.

I am tired of being treated like a dog, and people thinking that I will just eat whatever is put in front of me.

But I am not the only one. The README for Coast states “It uses a relational database and renders html on the server without javascript which allows you to ship your web applications faster.” The Pragmatic Bookshelf has a book called Programming Phoenix LiveView: Interactive Elixir Web Programming Without Writing Any JavaScript. Granted, they do not seem to be against JS. I think that LiveView is like GWT: You write code in Elixir (LiveView) or Java (GWT), and it gets translated to JS. Because JS is too complicated.

The PDFs for that book said that we need JS to make single-page apps and give users all the “modern” features of the web: like notifications and infinite scroll. Personally, I need fewer notifications and I hate infinite scroll. JS seems to give nothing but bloat. Granted, there are some things it is useful for: I think a lot of video players are done with JS. But beyond that, all JS has given us is bloat and complexity. I feel like I am spending more and more time on websites waiting for circles or rings to stop spinning.

I think we need to get back to CRUD apps. The kind we used to make 10 years ago. Yes, you had to know several languages, like HTML, CSS, SQL, maybe some Javascript. But you could focus on a language that interested you, like Java, or Ruby, or Python. Now it seems like a lot of people want to make it all Javascript all the time, now it’s Javascript AND maybe a little bit of the thing you really wanted to learn. Two years ago I took a course on Pluralsight about making web services in Go. The course included an Angular app to view the database. The Angular app takes up 589 megabytes on my hard drive. I took the course to learn how to use Go, not deal with Javascript. It reminds me of Joe Armstrong’s line about OOP: I just wanted a banana, not the monkey holding the banana and the tree it is sitting in.

Why they did not have a prerequisite course about making a web application in Go is beyond me.

Javascript is like someone comes to a restaurant, and at first they seem outgoing and charismatic. Then you realize the guy is groping all the women, he’s hammered and you can’t get rid of him.

I haven’t gotten around to reading any of the PDFs I have going over the history of Lisp. Perhaps for a couple of decades the Lisp world was total chaos like JS is today. But now it isn’t. Why not stand on the shoulders of giants?

If my impression of Javascript is out of date, so be it. It wasn’t my idea to ignore history and push a language which was described by its own creator as having “a lot of stupid in it.” He is still jerking around the world by giving us a browser that shields you from ads so they can give you their ads. And if that isn’t shady enough, Brave is involved with corrupt-o-currency. This guy is the poster jerk for crank magnetism.

I am open to learning new things. Lisp. Go. Elixir. Functional programming. Graph databases. I probably need to learn more about relational databases. Just using Emacs will help you to pick up new things: Org mode, CIDER. I learned some Scheme and Racket and how to get them working in Emacs so I could go through Simply Scheme so I could eventually go through SICP.

I have noticed that when people judge you for not being open to new ideas or learning something new, what they are really doing is being judgemental because you are not interested in what they are interested in. Being open to new ideas does not mean being open to all ideas.

You’re welcome.

Image from the Melisende Psalter, a 12th-century manuscript assumed to have been created at the Monastery of the Holy Sepulchre; housed in the British Library as Egerton MS 1139, assumed allowed under Public Domain.

Notes On A Drupal Meetup And Estimates

Recently I went to the Austin Drupal Meetup. The topic was “What is this estimation thing? Why “no estimation” is not as crazy as it sounds“. The speaker was Michael Godeck.

Before the presentation, I did talk to someone about Drupal and Gutenberg. He said that right now Drupal uses the CKEditor. It recently got re-written from the ground up, and the new version has not been integrated with Drupal yet. He said that the Drupal community looked at Gutenberg, and saw that there was a lot of WordPress-specific code, so most people decided that Gutenberg was not the direction they wanted to go in.

However, some people kept going, and have ported Gutenberg to Drupal, or re-worked it to work with Drupal. He said that they will demo their results at the next DrupalEurope in September. I think he was referring to this presentation. So, Gutenberg in Drupal is not a sure thing. But if the demo in Europe shows promise, it might happen.

The main presentation was about estimations. He will be presenting at DrupalEurope.

One issue with estimation is that estimates are sometimes interpreted by managers as promises.

He talked about On the Theory of Scales of Measurement by S.S. Stevens which covers different types of measurement. One type is ordinal, which allows ranking, but no meaningful calculation. You can rank movies using a star-based system; usually people go up to four. We know that a four-star is better than a three-star, and a three-star is better than a two-star. But is the difference between a four-star and a three-star the same as the difference between a three-star and a two-star?

Another type is interval, which does allow you to know the differences between quantities. Think of things like time, temperature and distance.

He said one issue with some agile estimation strategies is that the numbers people give are really ordinal, but they are treated as interval. People think that all uses of numbers are the same, but that is not the case. The agile community still seems to be struggling to this day with the question as to whether or not a point is equal to some unit of time.

He also spoke of confidence intervals. It may be time to brush up on statistics.

He also mentioned Thomas Bayes and Claude Shannon.

Image from “Evangelia quattuor [Évangiles dits de François II] (1r-186r). Capitulare evangeliorum (187r-199v)”, a 9th-century manuscript housed at the Bibliothèque nationale de France. Source gallica.bnf.fr / BnF; image assumed allowed under Fair Use.