<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://hemann.pl/feed.xml" rel="self" type="application/atom+xml" /><link href="https://hemann.pl/" rel="alternate" type="text/html" /><updated>2026-04-08T19:50:48+00:00</updated><id>https://hemann.pl/feed.xml</id><title type="html">Jason Hemann</title><subtitle>Personal Site.</subtitle><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><entry><title type="html">Letter of recommendation (from a professor whose class you took)</title><link href="https://hemann.pl/dwic/" rel="alternate" type="text/html" title="Letter of recommendation (from a professor whose class you took)" /><published>2023-08-11T00:00:00+00:00</published><updated>2023-08-11T00:00:00+00:00</updated><id>https://hemann.pl/dwic</id><content type="html" xml:base="https://hemann.pl/dwic/"><![CDATA[<p>Let’s say you did well in an upper-division class with a professor. You enjoyed the class and also enjoyed learning the material. That might seem like it would make the professor a shoo-in as a good recommender for you for your graduate school application. Here’s why that might not be so! It’s important that someone gives you the full scoop on all this. For instance, if I wrote a student such a letter, I might even be doing them a disservice by taking the slot of someone whose word would go farther.</p>

<p>If you have heard the term “DWIC” before, then you’ll know what I’m about to say. Either way, please do make sure you see <a href="https://koronkevi.ch/posts/applying-to-grad-school.html#:~:text=A%20%22Did%20Well%20In%20Class,ability%20in%20classes%2C%20not%20research">Paulette’s thoughts</a>.The point is that “did well in my class” letters don’t count for much because everyone who submits an application did well in the class that they would have had with their letter writer. Anyone should be able to muster that kind of a letter, and so it doesn’t help distinguish the so-so candidates from the great ones. It’s basically table stakes.</p>

<p>Graduate schools typically want comprehensive letters of recommendation that give detailed, nuanced evaluations of your strengths and potential as a student. A letter that simply states that you did well in class doesn’t give much insight into your intellectual ability, research skills, leadership qualities, or any other relevant attributes that graduate schools are looking for in applicants. Good letters generally come from people who’ve seen you work on more long term projects, in either a small-group reading class, or an independent study or a research project. Sometimes this could be a co-op/internship supervisor, depending upon where you did your co-op/internship. A one-off professor can’t offer that kind of perspective, because they didn’t get a chance to work with you in that manner.</p>

<p>If you already have all that other stuff covered, and just need like a third letter to fill out your set, then that’s probably a better fit! Another important caveat: an un-tenured professor probably has less credibility than a tenured one. When could a non-research letter go further than an ordinary DWIC? When I’ve seen an individualized project or two that you’ve worked on, and we’ve talked together several times about that project. When I’ve reaching out for help in a new course. If I can speak to you as a TA or tutor as well as a student. If I’m writing a letter for a masters program vs a phd, or a local scholarship vs a national one.</p>

<p>Be sure and let me know (1) what specifically you’re hoping for me to speak to, (2) how I can best help fit into your overall letters and application, and (3) tell me what kind of a program is this for. MS CS ? PhD CS? MFA, DDS, or MBA? A scholarship? It helps to know what I’m aiming for.</p>

<p>It will also help if you can provide:</p>

<ul>
  <li>A transcript</li>
  <li>A résumé/vita, with all of your pertinent info in it</li>
  <li>Anything in particular you’d like me to try and emphasize.</li>
  <li>A(nother) link to the scholarship/program information (and if they have multiple, <em>which</em> one you’re applying to!)</li>
  <li>And also tell me about your other letter writers.</li>
</ul>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[Let’s say you did well in an upper-division class with a professor. You enjoyed the class and also enjoyed learning the material. That might seem like it would make the professor a shoo-in as a good recommender for you for your graduate school application. Here’s why that might not be so! It’s important that someone gives you the full scoop on all this. For instance, if I wrote a student such a letter, I might even be doing them a disservice by taking the slot of someone whose word would go farther.]]></summary></entry><entry><title type="html">Is your shell what you think?</title><link href="https://hemann.pl/shells/" rel="alternate" type="text/html" title="Is your shell what you think?" /><published>2023-03-17T00:00:00+00:00</published><updated>2023-03-17T00:00:00+00:00</updated><id>https://hemann.pl/shells</id><content type="html" xml:base="https://hemann.pl/shells/"><![CDATA[<p>Depending how you installed a new version of <code class="language-plaintext highlighter-rouge">bash</code> on your mac, it
might surprise you to learn which version of bash you’re using. For
instance, if ask for the version of bash at the prompt. Here’s a
reasonable example.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>bash <span class="nt">--version</span> 
GNU bash, version 5.2.15<span class="o">(</span>1<span class="o">)</span><span class="nt">-release</span> <span class="o">(</span>aarch64-apple-darwin21.6.0<span class="o">)</span>
</code></pre></div></div>

<p>Looks good. If, however, we then go and check the BASH_VERSION …</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">echo</span> <span class="nv">$BASH_VERSION</span>
3.2.57<span class="o">(</span>1<span class="o">)</span><span class="nt">-release</span>
</code></pre></div></div>

<p>We get a very different and worse number. What gives? Well, your login
shell is using a different version of bash than is currently front on
your path.</p>

<p><a href="login-shell">This SO thread</a> helpfully describes the problem and the
issue. If you are using the new version of homebrew, then you might
have had to move where you keep the programs brew installs: the new
location is <code class="language-plaintext highlighter-rouge">/opt/homebrew/bin</code>. If that’s the one you want to set as
your login shell, then you’ll have to first add it to the
<code class="language-plaintext highlighter-rouge">/etc/shells</code> file, and then use the following to set it.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chsh -s /opt/homebrew/bin/bash
sudo chsh -s /opt/homebrew/bin/bash
</code></pre></div></div>

<p>(If you failed to add that to your <code class="language-plaintext highlighter-rouge">/etc/shells</code> file, then <code class="language-plaintext highlighter-rouge">chsh</code> will
squawk that this is a non-standard shell.)</p>

<p>But after this, you should be good to go with an up-to-date login shell.</p>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[Depending how you installed a new version of bash on your mac, it might surprise you to learn which version of bash you’re using. For instance, if ask for the version of bash at the prompt. Here’s a reasonable example.]]></summary></entry><entry><title type="html">Job hunting advice.</title><link href="https://hemann.pl/jobs/" rel="alternate" type="text/html" title="Job hunting advice." /><published>2023-02-21T00:00:00+00:00</published><updated>2023-02-21T00:00:00+00:00</updated><id>https://hemann.pl/jobs</id><content type="html" xml:base="https://hemann.pl/jobs/"><![CDATA[<p>I recently had cause to think about some advice for recent graduates
hunting for jobs. This is probably applicable too if you’re laid off
and need to find a new job. Caveats that this worked for me a dozen
years ago, and it’s tailored to students looking for programmer jobs.</p>

<ol>
  <li>Get a second email address that doesn’t obviously look like a
backup email address. You don’t want job mail spam in your inbox
for the rest of eternity.</li>
  <li>Make job hunting your full-time job until you have one. It’s a
9-5 process. There’s a lead time before you’re going to start
seeing results, and you don’t know how long that is, but don’t
sit and wait for that one org of your dreams to get back to you.</li>
  <li>Start with the “usual suspects” job recruiting sites—Monster,
indeed, etc. Fill out profiles and filters and set yourself up
with a feed for job leads.</li>
  <li>Any place that has an RSS feed, find yourself an RSS reader and
subscribe to them. This can be your work list, and mean there’s
a whole bunch of sites you don’t have to check.</li>
  <li>Work backwards in time, from most recent to more distant
postings.</li>
  <li>Niche technology where you have experience can be a good place
to start, because they probably have trouble recruiting for
that.</li>
  <li>When you find a job you want to apply for, do it from the
company’s intranet if you can.</li>
  <li>Google itself also has job search listings now, and you can use
that too.</li>
  <li>Often times when you’re looking up a job listing, you’ll find
another <em>site</em> on which that job is posted that you hadn’t
looked before. This is how you build breadth to your job search.
Let the job listings lead you to more sites, and the job hunt
sites lead you to more jobs listings.</li>
  <li>Recruiters/headhunters can be useful, get in touch w/them too.</li>
  <li>If you’ve graduated recently enough, the school might still
offer advice on your resume. Some schools have an alumni
network that to tap. The other thing I’ve seen is to update
your LinkedIn profile, see where your colleagues and contacts
are working, and then go to those companies’ websites for
listings.</li>
  <li>In fact, you can also start picking out companies that you’ve
heard of that you wouldn’t mind working for, and apply directly
with them. That’s another way to increase your pool of job
sites.</li>
  <li>Use several common search strings for positions on the search
sites. You know that “software engineer” “programmer” “computer
scientist” “software developer” “platform engineer” can bleed
across one another, but the sites don’t and HR might not
either. If a site only lets you have one active search, then
get another email address and another login to that site, and
have your second search set up that way.</li>
  <li>Make sure your resume is AI/search friendly. Use the key words
and phrases that will get you past the automatic filters and
into the hands of a human being.</li>
  <li>Borrow the address of a friend’s couch. If you’re willing to
relocate, and you have someone in the area, then you can put
that person’s address on the resume making you look like a
local hire. “I’ve been staying with a friend out there while I
.. I just recently moved back to my place…” yadda. IME, by the
time you’re far enough along that you seem like a candidate
worth interviewing in person, then that won’t matter. If it
does.</li>
  <li>As I understand it, in person commuting-to-work jobs are going
to be less competitive than the remote jobs, because a) people
place a premium on the work from home and b) you are already
excluding all the people who aren’t in or willing to be in a
commute distance of that job.</li>
  <li>You can and probably should have multiple versions of your
resume tailored to different kinds of positions. Depending on
what technology they want you to work with and what the role
requires, you’ll emphasize different things in your background.
If you can, make it look like you’re already an expert at doing
the job they want to hire you for.</li>
  <li>Double, triple check your emails and spelling and that you’re
addressing the right company with the right job. If you can,
build yourself a little program that will automate portions of
your cover letter. If you’re building it with PDF, then using
TeX macros <code class="language-plaintext highlighter-rouge">\longname</code> <code class="language-plaintext highlighter-rouge">\shortname</code> <code class="language-plaintext highlighter-rouge">\mediumname</code>
<code class="language-plaintext highlighter-rouge">\specialreason</code> to fill in a cover letter could both save you
time and frustration</li>
  <li>Likewise, before you send something, have a tool read it to
you, out loud. You can listen for mistakes that sound obvious
but are difficult to pick out. You can do this on 2x speed if
you’re quick enough. This isn’t a place to be lazy.</li>
  <li>If you have time, especially if you think you’ll be off for a
while, pull out that side project you’d been working on, and
spend some nights and weekends on that. It’s something new you
can show off, looks good on your GitHub commit history, and
gives you something to talk about at an interview.</li>
  <li>This may be less applicable, but <em>if</em> you’re going to be off
work for a <em>while</em> having a volunteer position doing something
related could be helpful just to keep a blank off your resume.
OSS and side projects are nice too, but that doesn’t fit in a
spot on a resume. Maybe start thinking about this in your
second month off, so that you can <em>have</em> something in hand. A
position that you’ve had for 6 months working one day a week
looks better than 5 months off and then a whole month straight
of volunteering.</li>
</ol>

<p>I know <a href="https://youtu.be/KT4vhl8slbE">it’s tough out there</a>. Most of
that is probably common sense to readers, but I hope there’s something
in there that’s worthwhile.</p>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[I recently had cause to think about some advice for recent graduates hunting for jobs. This is probably applicable too if you’re laid off and need to find a new job. Caveats that this worked for me a dozen years ago, and it’s tailored to students looking for programmer jobs.]]></summary></entry><entry><title type="html">Easy SFTPeasy</title><link href="https://hemann.pl/self-signed-certificate/" rel="alternate" type="text/html" title="Easy SFTPeasy" /><published>2022-11-10T00:00:00+00:00</published><updated>2022-11-10T00:00:00+00:00</updated><id>https://hemann.pl/self-signed-certificate</id><content type="html" xml:base="https://hemann.pl/self-signed-certificate/"><![CDATA[<p>The powers that be here at SHU make some webspace available to faculty
and staff here for course-related materials. This is a nice convenient
alternative to the LMS system for webhosting, and I wanted to explore
what else we could do with it. My contact at the Teaching Learning
Center on campus set me up with some space and an account. That I can
use as soon as I can log in and get to it. All technology and know-how
around campus seems geared toward a pointy-clicky Windows based mode
of operation.</p>

<p>Easy command line access requires a little bit of study and
configuration.</p>

<p>Firstly, the right tool for the job.</p>

<h2 id="btw-sftp--ftps">BTW, <code class="language-plaintext highlighter-rouge">SFTP</code> =/= <code class="language-plaintext highlighter-rouge">FTPS</code></h2>

<p>If you don’t know, <code class="language-plaintext highlighter-rouge">SFTP</code> and <code class="language-plaintext highlighter-rouge">FTPS</code> are not the same thing. If a
person talks to you about “secure FTP”, stop that person immediately
and make them clarify to you which they mean. It’s possible that they
don’t know either: trust, but verify.</p>

<p>I found the easy way to connect to our server
(<code class="language-plaintext highlighter-rouge">tltc-web1h-prod.shu.edu</code>) was to simply <code class="language-plaintext highlighter-rouge">brew install lftp</code>. Scads
of dependencies I needed to download and update all handled for me;
man alive package managers are great!</p>

<p>But I run into a problem when I actually try to use this to get to my
space now. I can connect, but when I actually try and move around, you
run into the following error.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ lftp -u hemannja,"$PASSWD" ftp://tltc-web1h-prod.shu.edu/hemannja/
cd: Fatal error: Certificate verification: self-signed certificate ...
</code></pre></div></div>

<h2 id="certificates-and-verification">Certificates and verification</h2>

<p>This error message is saying that the server has a self-signed
certificate authority, and so my system rightly doesn’t trust it. If
this were a nefarious actor, well, it wouldn’t make any sense to take
his own word that he’s an honest fella. But I happen to know that I’m
really dealing with the machine I think I am, so I want to, for this
guy only, accept the certificate that it’s providing me.</p>

<p>So I need to <em>get</em> the certificate that this server is presenting me</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ openssl s_client -connect tltc-web1h-prod.shu.edu:21 -starttls ftp
...
---
Server certificate
-----BEGIN CERTIFICATE-----
123...
...
...456789abcdefgihijklm==
-----END CERTIFICATE-----
subject=...
issuer=...
---
</code></pre></div></div>

<p>I needed to save that certificate itself as a certificate file. Just
the certificate, mind you.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat &gt; ~/tltc_web1h_prod_AES-256.crt
...
</code></pre></div></div>

<p>Once I had that, I needed to add it so that <code class="language-plaintext highlighter-rouge">lftp</code> knew about it.</p>

<p>Luckily this was a <a href="https://stackoverflow.com/a/65760327/4355474">solved
problem</a>. If you want to
add it to your MacOS Keychain, <a href="https://support.apple.com/en-my/guide/keychain-access/kyca2431/mac">they also have a help page for
this</a>.</p>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[The powers that be here at SHU make some webspace available to faculty and staff here for course-related materials. This is a nice convenient alternative to the LMS system for webhosting, and I wanted to explore what else we could do with it. My contact at the Teaching Learning Center on campus set me up with some space and an account. That I can use as soon as I can log in and get to it. All technology and know-how around campus seems geared toward a pointy-clicky Windows based mode of operation.]]></summary></entry><entry><title type="html">Living off the land.</title><link href="https://hemann.pl/living-off-the-land/" rel="alternate" type="text/html" title="Living off the land." /><published>2022-09-08T00:00:00+00:00</published><updated>2022-09-08T00:00:00+00:00</updated><id>https://hemann.pl/living-off-the-land</id><content type="html" xml:base="https://hemann.pl/living-off-the-land/"><![CDATA[<p>We’re mostly cloud computing infrastructure here at SHU, but we do
have a department server. On which I’m not an admin (and shouldn’t
be!)</p>

<p>For my software engineering class however, students (and I) will just
need access to some software sometimes that isn’t installed. For
instance, the default version of <code class="language-plaintext highlighter-rouge">python</code> is 2.7.</p>

<p>However! <code class="language-plaintext highlighter-rouge">python3</code> is already installed! As <code class="language-plaintext highlighter-rouge">python3</code>. As you’d
expect. To be more specific, version 3.6. So that’ll probably suffice.</p>

<p>However, suppose not. Or, just that we wanted to build python3.10.7
from source.</p>

<h1 id="how-to-install-python-310-on-red-hat-enterprise-linux-server">How to install python 3.10 on Red Hat Enterprise Linux Server</h1>
<p>release 7.9 (Maipo) without root</p>

<p>There were several missing modules that were not installed but
optional, one that the output of a failed <code class="language-plaintext highlighter-rouge">make</code> lists as mandatory,
and one that same failure lists as optional but seemed actually
necessary.</p>

<p>The configuration script says it’ll require a more recent version of
openssl than the one we have installed.</p>

<p>So we go <code class="language-plaintext highlighter-rouge">wget</code> ourselves a tarball of the most recent version of
openssl, and then try and configure <em>it</em>.</p>

<p>Well, the version of perl that we have on our system seems broken or
malconfigured, because perl can’t find some basic comes-out-of-the-box
install packages, e.g. <code class="language-plaintext highlighter-rouge">ExtUtils::MakeMaker</code> and <code class="language-plaintext highlighter-rouge">Test::Harness</code>. And
we don’t have CPAN installed either.</p>

<p>Those modules are supposedly core—but I cannot seem to find them
even though I have the standard perl5 installed.</p>

<p>So, the suggestion was to use something like
<a href="https://perlbrew.pl/">perlbrew</a> to just manage, a la homebrew, to
install a local fresh installation of perl5. <code class="language-plaintext highlighter-rouge">perlbrew</code> is pretty
cool!</p>

<p>Out of the box, that failed. But the instructions suggested running
perlpatch, from the same download, to try and fix perl up before doing
the perlbrew of perl.</p>

<p>However, in order to run <em>that</em> command, we need GNU patch which, you
guessed it, isn’t installed on our machine.</p>

<p>I had to download patch <a href="https://ftp.gnu.org/gnu/patch/">from the GNU site</a></p>

<h1 id="installing-in-userspace">Installing in userspace</h1>

<p>Since we’re having to install all of these in userspace, we’ll need to
have a directory convention for the download and install of all this
software. One of the keys is that most of these packages in their
configure script tell you about either a <code class="language-plaintext highlighter-rouge">PREFIX=</code> or <code class="language-plaintext highlighter-rouge">--prefix=</code>
configuration setting to let you install the software wherever you
want (in your own space ofc).</p>

<p>From there, I had to then perlbrew install-patchperl</p>

<p>From there, I had to install (some) right version of perl 5.16.3 in my case.</p>

<p>From there I could finish installing openssl 1.1 and add that on my
path.</p>

<p>Once I had that I was one step closer to installing python3, because
the next issue was that I do not have libffi installed.</p>

<p>The correct way to solve this problem is to download the release of
libffi, which has the installation script built in, and run that
script.</p>

<p>Okay, now these prerequisites are seemingly installed. Why isn’t the
install script running?</p>

<h1 id="flags-to-the-configure-script">Flags to the configure script</h1>

<p>One of the keys was to read the configuration options for the
configure script. These are also <a href="https://docs.python.org/3/using/configure.html#linker-options">reproduced
online:</a></p>

<p><a href="https://bugs.python.org/msg381577">This</a> gave me the flags and
information for how to solve the missing libssl information.</p>

<p>These both describe the problem with the SSL installation, that may
have been a bug in the install script expecting a different directory
structure for openssl.
<a href="https://github.com/pyenv/pyenv/issues/1183">And</a>
<a href="https://github.com/pyenv/pyenv/issues/1183#issuecomment-605018391">also</a>
<a href="https://bugs.python.org/msg321096">these</a>.</p>

<h2 id="ld_library_path"><code class="language-plaintext highlighter-rouge">LD_LIBRARY_PATH</code></h2>

<p>A little bit of cli-fu is just enough to hang yourself. <a href="http://xahlee.info/UnixResource_dir/_/ldpath.html">Xah
Lee</a> gives a nice
history lesson on some of the ways this can bite you. I may or may not
have needed some settings for this install. But I did avail myself.</p>

<h1 id="scripting-it">Scripting it!</h1>

<p>Now that we have a way to build this, we’d sure like to not have to do
it all over again by hand. The right thing to do here is to script the
install. The expedient thing is diligent notes. We won’t expose <em>all</em>
of it here, but certainly this could be useful to the diligent student
reader.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./configure --prefix=$HOME/python \
  LDFLAGS="-L$SPOT/libffi/lib64/ -L$SPOT/openssl/lib/"
  CPPFLAGS="-I$SPOT/openssl/include/openssl/ -I$SPOT/libffi/include/"
  --with-openssl=$SPOT/openssl/
</code></pre></div></div>

<h1 id="takeaways">Takeaways</h1>

<ol>
  <li>
    <p>Be kind to your sysadmin. Buy that person chocolates and Christmas
cards.</p>
  </li>
  <li>
    <p>Read The Friendly Manual. The information you want is sitting
<em>right</em> there. You can of course</p>
  </li>
  <li>
    <p>Your browser is your friend. There was a time when you had mailing
lists and man pages and you felt good that you did. Now, you also have
the ol’ googler.</p>
  </li>
</ol>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[We’re mostly cloud computing infrastructure here at SHU, but we do have a department server. On which I’m not an admin (and shouldn’t be!)]]></summary></entry><entry><title type="html">Maybe? Definitely.</title><link href="https://hemann.pl/monads/" rel="alternate" type="text/html" title="Maybe? Definitely." /><published>2022-06-20T00:00:00+00:00</published><updated>2022-06-20T00:00:00+00:00</updated><id>https://hemann.pl/monads</id><content type="html" xml:base="https://hemann.pl/monads/"><![CDATA[<p>Here is a use of Scheme’s findf operator.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (findf number? '(1 #f 2 dog))
1
</code></pre></div></div>

<p>Findf takes a predicate and a list, and returns the first element of
the list for which that predicate holds true, returning #f in the case
that the predicate holds for no member of the list.</p>

<p>So if we change 1 to one, then we will now get a different answer.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (findf number? '(one #f 2 dog))
2
</code></pre></div></div>

<p>And if we change 2 to two, we get #f, as now no elements of the list
are numbers.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (findf number? '(one #f two dog))
#f
</code></pre></div></div>

<p>Lets instead ask a different question of this list: boolean?</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (findf boolean? '(one #f two dog))
#f
</code></pre></div></div>

<p>Whoa ho ho. What’ve we got /here/?</p>

<p>findf returns the first element of the list for which that predicate
holds. #f is a boolean, so that’s what’s returned. Lo, the confusion
that can result.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (findf boolean? '(one two dog))
#f
</code></pre></div></div>

<p>Let’s look at the issue a bit more abstractly. The meat of the problem
is that the value we’re using to denote
an “error” (“failure”, “exception”, what have you) is /in/ the set of
things that we could possibly return as /actual/ answers. Some
languages use -1 as an error condition instead. Obviously, that’s no
good as an error value here, either.</p>

<p>There’s not a safe value we can pick, because for whatever value we
pick, it might be someone wants to hunt for precisely that value in
their list. For instance, we might try to patch the problem above,
saying to ourselves “Well, #f is useful. Comes up all the time. I’ll
write my own findf, and pick a different thing.” Heck, we’ll choose
this-obscure-symbol-means-failure-Qx29t7.</p>

<p>And that works great until some dingbat comes along and does the
following</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (my-findf (lambda (y) (eqv? 'this-obscure-symbol-means-failure-Qx29t7 y))
           '(a b c this-obscure-symbol-means-failure-Qx29t7))
this-obscure-symbol-means-failure-Qx29t7
</code></pre></div></div>

<p>But as it turns out, that might not be such a dingbat thing to do,
after all. All the time, we write code that generates code. Someone
who’s generating Scheme code might very well have reason to hunt for
that symbol in a list.</p>

<p>Anyhow. What’s clear is that the above suggestion is just sort of a
patch. These sorts of things come up all the time. We report #f, -1,
Error 404, etc., etc. It seems like there ought to be a unified
approach to handling this sort of problem, and one in which we don’t
have to kludge together some sort of an error code for each distinct
case.</p>

<p>The maybe monad gives us the power to do both of those. It provides a
generic way to handle and propogate failure, and, by virtue of being
general, it means there’s no ad-hoc solution to the value that denotes
an error.</p>

<p>We’ve got return and maybe, those new relatives of eta and * that we
introduced. And we’ve also got fail, which is our way of signaling a
failure.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define return-maybe
  (lambda (a) `(Just ,a)))
 
(define bind-maybe
  (lambda (ma f)
    (cond
      [(eq? (car ma) 'Just) (f (cadr ma))]
      [(eq? (car ma) 'Nothing) '(Nothing)])))
 
(define fail
  (lambda ()
    '(Nothing)))
</code></pre></div></div>

<p>return is just another name for eta (or unit). More on that in a sec, but a quick
reminder.</p>

<p>There’s lots of monads, and they all have the same type signatures for
the return and bind, and they all have to obey those monadic
laws. We’re gonna walk though, at a type level, what return and bind
/are/, how those things relate to eta and *, why their essence and
behavior makes sense, and then look at how the actual implementations
of return-maybe and bind-maybe make sense.</p>

<p>Whew. That’s a tall order. Well, let’s get to it.</p>

<p>As we were. return is just another name for eta.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>return : alpha -&gt; Malpha
</code></pre></div></div>

<p>The job of return/eta is to take a “pure” value – that is, a value
from the regular land of computation, and wrap it up in the
monad (burrito) (or like Just above.)</p>

<p>For our maybe monad, there are two classes of things that are monadic values.</p>

<p>1 : (Just <x>), where <x> is any old thing you choose. (Must it be a pure value?)
2 : (Nothing)</x></x></p>

<p>This second one is the value provided by invoking fail. Notice that
because all the pure values are wrapped up in a list with Just at the
front, then this (Nothing) doesn’t have the same problem as we had
before with -1 or #f.</p>

<p>If I want to return #f out of my findf-maybe (which we’ll write in a
second), it’ll come out as (Just #f). If I want to signal something’s
not in there, it’ll come out as (Nothing).  (Of course, that could be #f).</p>

<p>And now, let’s consider that same dingbat from before, trying to be
cute again.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (findf-maybe (lambda (v) (equal v `(Nothing))) '(-1 #f (Nothing) 404))
(Just (Nothing))
</code></pre></div></div>

<p>Ah-HA! Lookie there. Unlike before with Scheme’s findf, now we can tell
when the failure value is exactly that thing looked up in the list,
vs. when it’s actually returned as a failure value. We’ve got the
problem licked. Well, as soon as we figure out bind, relate it to *,
explain why bind-maybe makes sense as a bind, and use this to
implement findf-maybe.</p>

<ul>
  <li>
    <p>was typed as follows.</p>
  </li>
  <li>
    <p>: (alpha -&gt; Mbeta) -&gt; (Malpha -&gt; Mbeta)</p>
  </li>
</ul>

<p>That is, it takes a function and returns a function. A few months ago
that in and of itself might’ve been mind-blowing, but it’s pretty
old-hat now. BTW, if you need a mundane example, integral is the sort
of thing that takes a function and returns a function.</p>

<p>In the biz, we always associate curried functions to the left. If I
have something that looks like</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>f : int -&gt; (bool -&gt; (string -&gt; (bool -&gt; (string -&gt; int))))
</code></pre></div></div>

<p>those parens start to get a bit annoying there.</p>

<p>So we instead write it as</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>f : int -&gt; bool -&gt; string -&gt; bool -&gt; string -&gt; int
</code></pre></div></div>

<p>but we all know what that means. So you’ll more likely see * typed like</p>

<ul>
  <li>: (alpha -&gt; Mbeta) -&gt; Malpha -&gt; Mbeta</li>
</ul>

<p>That is, it’s gonna be a function that takes an f, then it takes an ma.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define *
  (lambda (f)
    (lambda (ma) ...)))
</code></pre></div></div>

<p>And does … well, who knows what the /particular/ implementation does
at this point, but it does something like calling the function on that
argument.</p>

<p>A quick digression, seemingly apropos of nothing. Let’s define an
operator curried-app.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define curried-app
  (lambda (f)
    (lambda (a)
      (f a))))
</code></pre></div></div>

<p>Nothing terribly fancy here.</p>

<p>BUT–imagine a world in which that’s the only way you apply
functions. You don’t get to call them directly on their
arguments. Instead, when you wanna apply a function, you pass it to
curried-app, to which you then pass the argument upon which you wanna
call that function.</p>

<p>There’s not much use to doing such a thing when we do our regular
run-of-the-mill Scheme programming. But when we’re working with
monads, it’s a necessity. By the way, did you notice the type of curried-app?</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curried-app : (alpha -&gt; beta) -&gt; alpha -&gt; beta
</code></pre></div></div>

<p>Remarkably, strikingly, /suspiciously/ similar to the type of *. *
does what curried-app does, except it works over monads. When using
monads, we’ve given up the necessity of doing our own function
applications to arguments. It’s passe. Well, not really that, so much
as we’re modeling effects, and we want to make sure the effects happen
the right way. * (well, really it’ll be bind) is going to make sure
that happens, ‘cause it and it alone is allowed to /do/ the
application of functions to monadic arguments. So if * (bind) is
right, then the whole process is right. We’ve deputized * (bind) as
the function-apper. And because * (bind) has to obey the Monadic Laws
if it’s to be a genuine, bonified, monad. Since we’re using
pre-certified monads, we’re certain that they’re up to snuff, so if we
just use’em correctly * (bind) will make all the applications work
properly.</p>

<p>Alright, I’m done writing bind in parens. Let’s describe bind, so that
we can just get to using it. A couple of things.</p>

<ol>
  <li>Writing code with nested calls to * starts to get uuuugly.</li>
</ol>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>((* (lambda (x)
     ((* (lambda (y)
          ((* (lambda (z) ...))
           arg3)))
      arg2)))
 arg1)
</code></pre></div></div>

<p>The flow of control is going to the right. Programs written this way
end up building these giant rightward dagger shapes.</p>

<ol>
  <li>By doing all of our monadic code with calls to a function-apper
mechanism, it makes sense to think of that part of the program as
doing work in units of function-apping. “Do a *, which then demands
another *, which …”. Why bother to curry *? Nothing’s gonna happen
until we give it both parts, and it’s not really of use to do’em one
at a time.</li>
</ol>

<p>It’d be nice if my code read linearly, down the page, rather than
having to follow it out in that triangle pattern, and if I treated
these applications of function to argument as the real unit of work.</p>

<p>Bind does both of those.</p>

<p>The type of bind is</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bind : (Malpha x (alpha -&gt; Mbeta)) -&gt; Mbeta
</code></pre></div></div>

<p>That is, it takes two arguments at once, the argument and the
function, and it takes’em in that order. Notice, now, if we have some
stuff that’s nested, then the work that we do next, that’s part of the
function body, will be underneath the stuff above. We can read what’s
going to happen in order down the page.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define bind-maybe
  (lambda (ma f)
    (cond
      [(eq? (car ma) 'Just) (f (cadr ma))]
      [(eq? (car ma) 'Nothing) '(Nothing)])))
</code></pre></div></div>

<p>So here’s our definition of bind-maybe, again. We can see it’s doing
at least part of what we wanted it to do. It takes two arguments, in
the right order. We know that ma is one of the things in my maybe
monad. Which means it’s either a (Just <something>) or (Nothing). In
the first case, it's a real and actual value. In the second, there was
an error/failure/exception/badness up the road. If there was an error,
we can't compute on it, and we wanna propagate that forward. So if we
had an error, we return an error.</something></p>

<p>If instead we had a (Just <something>), a non-error value, well we
wanted to do that application. f takes a pure value. We see that,
here. Look, it's taking the cadr of ma. bind, as we theorized, knows
how to take the ma, unwrap the burrito and get ahold of the a, and
call f on it. Whatever comes out of bind needs to still be in the
monad. Pretend this bind is the last thing we do before we end the
computation. Well, I want to make sure I can tell the difference
between returning (Just (Nothing)) and (Nothing), like that yahoo
tried to pull earlier.</something></p>

<p>f, the function we pass in, the one we’re gonna build, needs to be of
alpha -&gt; Mbeta. That way, the thing we hand back is still safely
nestled in the monad. That’s the reason behind the “monads are
space-suits” metaphor.  You can’t open a space-suit
willy-nilly. You’ve got to do it nestled safely inside a
space-capsule. If you do it outside, or go outside not wearing one,
you’ll die in the cold, cold, blackness of space. Alone. That’s what
happens to you if you try to get at the pure inside the monad when you
aren’t supposed to.</p>

<p>A word about those alphas and betas there. They don’t /have/ to be
distinct types. They can be. But they don’t have to be. I’m gonna put
some !s around the parts that you really wanna pay attention to about
the type of bind.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bind : (!Malpha! x (!alpha! -&gt; Mbeta)) -&gt; Mbeta
</code></pre></div></div>

<p>The point is that the thing f takes as an argument is exacty the same
type as the first argument to bind, except the first argument to bind
has it all wrapped up in the monad (burrito).</p>

<p>So that’s the gist of what maybe is. Let’s real quick write findf-maybe
and, ‘cause findf-maybe doesn’t show off everything we’re gonna wanna
do, we’ll write a somewhat contrived example that’ll show off
bind-maybe, too.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define findf-maybe
  (lambda (p ls)
    (cond
      ((null? ls) (fail))
      ...)))
</code></pre></div></div>

<p>So far, so good, this makes sense. We’ve been promising that we’ll
return (Nothing) when we can’t findf the thing. Whelp, that’ll do it.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define findf-maybe
  (lambda (p ls)
    (cond
      ((null? ls) (fail))
      (else (let ((a (car ls)))
              (cond
                ((p a) ...)
                (else ...)))))))
</code></pre></div></div>

<p>So here, we’re just setting up and being a bit fancy. I happen to know
for a fact that we’re going to need a couple of times, potentially,
so I’m let-binding it above. There’s the remaining two cases:
either (p a), or not. We’ll handle’em one at a time.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define findf-maybe
  (lambda (p ls)
    (cond
      ((null? ls) (fail))
      (else (let ((a (car ls)))
              (cond
                ((p a) (return-maybe a))
                (else ...)))))))
</code></pre></div></div>

<p>We wrap the thing up in the monad. findf-maybe is written to have
return-type Mbeta. Which makes sense, according to our spec. We wanted
it to return the stuff wrapped up, again, so we could tell the
difference. That’s why we put it through return. Final case, the
recursive call. Well, findf-maybe spits back something of Mbeta, which
is what we’re after, so nothing special to do here, just the plain-ol’
regular recursion.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define findf-maybe
  (lambda (p ls)
    (cond
      ((null? ls) (fail))
      (else (let ((a (car ls)))
              (cond
                ((p a) (return-maybe a))
                (else (findf-maybe p (cdr ls)))))))))
</code></pre></div></div>

<p>Voilà. Go forth and findf to your heart’s content. I promised another
example, this time with bind-maybe. We’re gonna try to write an
operator that’ll take a list of numbers and return the product of
their reciprocals. Why? You caught me, no good reason. But let’s do it
anyway, for sport. Or something.</p>

<p>Now, the thing about reciprocals is that zero doesn’t have
one. Division by zero is undefined. So when we try to do this, we’re
gonna have to be on the lookout for a zero, and if we hit one, we come
back out with (Nothing).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define prod-recip-maybe
  (lambda (ls)
    ...))
</code></pre></div></div>

<p>We’re just gonna blast right through to the new and interesting bit.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define prod-recip-maybe
  (lambda (ls)
    (cond
      ((null? ls) (return-maybe 1))
      (else
       (let ((a (car ls)))
         (cond
           ((zero? a) (fail))
           (else ...)))))))
</code></pre></div></div>

<p>So we’ve got a non-zero number in the car. Let’s do the recursion, get
that value, and then use it to return the value we’re really
after. I’m doing the recursion, which means I’m coming back with a
value in the monad. And then I wanna do something with the value of
that recursive call, to get the value of the whole expression. This is
a job for bind-maybe. If this was being done non-monadically, and we
were using curried-app, again, it’d look like</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>((curried-app (lambda (rec) (* a rec)))
 (prod-recip-maybe (cdr ls)))
</code></pre></div></div>

<p>But we’re not, we’re 1. in the monad, and 2. really /done/ with that
curried-app thing. Since we’re in the monad, bind-maybe’s gonna do the
job of pulling the pure out of the monadic value. And we’re gonna make
sure that that function returns a monadic value, ‘cause the next fella
up the line is expecting a value in the monad.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define prod-recip-maybe
  (lambda (ls)
    (cond
      ((null? ls) (return-maybe 1))
      (else
       (let ((a (car ls)))
         (cond
           ((zero? a) (fail))
           (else
            (bind-maybe
             (prod-recip-maybe (cdr ls))
             (lambda (rec)
               (return-maybe (* (/ 1 a) rec)))))))))))
</code></pre></div></div>

<p>Well done. Buut, that is looking a little long, and is slightly
obscuring. That do syntax we introduced would certainly clean some of
this up.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define-syntax do
  (syntax-rules (&lt;-)
    ((_ bind e) e)
    ((_ bind (v &lt;- e) e* e** ...)
     (bind e (lambda (v) (do bind e* e** ...))))
    ((_ bind e e* e** ...)
     (bind e (lambda (_) (do bind e* e** ...))))))
</code></pre></div></div>

<p>It’s your standard, run-of-the-mill syntax-rules macro. We take which
bind function it is, and a whole bunch of expressions, and expand out
into nested calls to that bind in the right fashion. For our case,
this yields</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define prod-recip-maybe
  (lambda (ls)
    (cond
      ((null? ls) (return-maybe 1))
      (else
       (let ((a (car ls)))
         (cond
           ((zero? a) (fail))
           (else
            (do bind-maybe
              (rec &lt;- (prod-recip-maybe (cdr ls)))
              (return-maybe (* (/ 1 a) rec))))))))))
</code></pre></div></div>

<p>And /there/ we go.</p>

<p>Now, Go Eat A Burrito! Maybe While Wearing A Space-Suit!</p>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[Here is a use of Scheme’s findf operator.]]></summary></entry><entry><title type="html">Resolving emacs load path shadows</title><link href="https://hemann.pl/load-path-shadows/" rel="alternate" type="text/html" title="Resolving emacs load path shadows" /><published>2022-04-24T00:00:00+00:00</published><updated>2022-04-24T00:00:00+00:00</updated><id>https://hemann.pl/load-path-shadows</id><content type="html" xml:base="https://hemann.pl/load-path-shadows/"><![CDATA[<p>I recently experienced some emacs problems suggestive of load path
issues. Executing <code class="language-plaintext highlighter-rouge">M-x list-load-path-shadows</code> gives a nice long list
of shadowed files from load path. I use <code class="language-plaintext highlighter-rouge">straight.el</code> as my emacs
package manager. It’s very convenient for all the reasons that the
<code class="language-plaintext highlighter-rouge">straight.el</code> documentation lays out, but naive usage can lead you to
introducing load-path conflicts. Consider an example like the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(straight-use-package 'eri)
(straight-use-package 'agda2-mode)
</code></pre></div></div>

<p>I included both of these in my <code class="language-plaintext highlighter-rouge">.emacs</code> configuration, asking
<code class="language-plaintext highlighter-rouge">straight.el</code> to load, and install if necessary, both of these
packages at start-up. However! It turns out <code class="language-plaintext highlighter-rouge">agda2-mode</code> <em>already</em>
includes <code class="language-plaintext highlighter-rouge">eri</code>! But <code class="language-plaintext highlighter-rouge">straight</code> doesn’t know that. So instead we need
to inform it of that fact.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(straight-use-package '(agda2-mode :includes eri))
</code></pre></div></div>

<p>It turns out that <code class="language-plaintext highlighter-rouge">agda2-mode</code> contains within it a couple of things,
so <code class="language-plaintext highlighter-rouge">straight.el</code> provides some extra syntax for passing a list of
options.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(straight-use-package '(agda2-mode :includes (eri annotation)))
</code></pre></div></div>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[I recently experienced some emacs problems suggestive of load path issues. Executing M-x list-load-path-shadows gives a nice long list of shadowed files from load path. I use straight.el as my emacs package manager. It’s very convenient for all the reasons that the straight.el documentation lays out, but naive usage can lead you to introducing load-path conflicts. Consider an example like the following:]]></summary></entry><entry><title type="html">You know you’ve made it.</title><link href="https://hemann.pl/made-it/" rel="alternate" type="text/html" title="You know you’ve made it." /><published>2022-01-02T00:00:00+00:00</published><updated>2022-01-02T00:00:00+00:00</updated><id>https://hemann.pl/made-it</id><content type="html" xml:base="https://hemann.pl/made-it/"><![CDATA[<p>You know you’ve made it when Aphyr <a href="https://aphyr.com/posts/354-unifying-the-technical-interview">invokes you in an
interview</a>!
See microKanren in action!</p>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[You know you’ve made it when Aphyr invokes you in an interview! See microKanren in action!]]></summary></entry><entry><title type="html">Closure Conversion and Lambda Lifting</title><link href="https://hemann.pl/closure-conversion/" rel="alternate" type="text/html" title="Closure Conversion and Lambda Lifting" /><published>2021-07-23T00:00:00+00:00</published><updated>2021-07-23T00:00:00+00:00</updated><id>https://hemann.pl/closure-conversion</id><content type="html" xml:base="https://hemann.pl/closure-conversion/"><![CDATA[<p>If you’ve always wanted to know about closure conversion and lambda
lifting, <a href="https://raw.githubusercontent.com/jasonhemann/21FA-CS4400/master/_FAQ/closure-conv.md">here you go!</a></p>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[If you’ve always wanted to know about closure conversion and lambda lifting, here you go!]]></summary></entry><entry><title type="html">From what program is valof defunctionalized?</title><link href="https://hemann.pl/valof-defunctionalizes/" rel="alternate" type="text/html" title="From what program is valof defunctionalized?" /><published>2021-07-23T00:00:00+00:00</published><updated>2021-07-23T00:00:00+00:00</updated><id>https://hemann.pl/valof-defunctionalizes</id><content type="html" xml:base="https://hemann.pl/valof-defunctionalizes/"><![CDATA[<p>We use defunctionalization as program transformation, and see
defunctionalized aka data-structure representations as a <em>product</em> of
these. But we almost always start off with the <em>program itself</em> using
data structures, and punning at that. The natural question to arise
is: <a href="https://raw.githubusercontent.com/jasonhemann/21FA-CS4400/master/assets/code/valof-defunctionalizes.rkt">From what program is valof
defunctionalized?</a></p>]]></content><author><name>Jason Hemann</name><email>jason.hemann@shu.edu</email></author><summary type="html"><![CDATA[We use defunctionalization as program transformation, and see defunctionalized aka data-structure representations as a product of these. But we almost always start off with the program itself using data structures, and punning at that. The natural question to arise is: From what program is valof defunctionalized?]]></summary></entry></feed>