<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
 <title type="text">λk.(k blog): λk.(k blog)</title>
 <link rel="self" href="https://www.williamjbowman.com/feeds/all.atom.xml" />
 <link href="https://www.williamjbowman.com/blog/index.html" />
 <id>urn:https-www-williamjbowman-com:-blog-index-html</id>
 <updated>2026-03-25T00:26:51Z</updated>
 <entry>
  <title type="text">Please don't generate your bibliography</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2026/03/24/please-don-t-generate-your-bibliography/" />
  <id>urn:https-www-williamjbowman-com:-blog-2026-03-24-please-don-t-generate-your-bibliography</id>
  <published>2026-03-25T00:26:51Z</published>
  <updated>2026-03-25T00:26:51Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I read a lot of bibliographies. I also read a lot of bad bibliographies, most of which are clearly autogenerated. I don&amp;rsquo;t like reading bad bibliographies.&lt;/p&gt;

&lt;p&gt;There are two purposes to a bibliography.&lt;/p&gt;

&lt;p&gt;The first is to communicate which article is being cited to the reader. For that, it’s important to make the citation information very clear and consistent.&lt;/p&gt;

&lt;p&gt;The second is to make it possible for the reader to find the thing being cited. For that, you need as much information as necessary to track down the original article. If you have a DOI, that becomes pretty trivial, so most other information can be excluded. If you don’t have a DOI, you may need to call a librarian and they may need lots of specific information. If you haven&amp;rsquo;t had to do this, go find an old paper in your field and try to track down a physical copy. It&amp;rsquo;s a learning experience.&lt;/p&gt;

&lt;p&gt;I have a style guide and some rules-of-thumb I use to try to satisfy these two goals:&lt;/p&gt;

&lt;p&gt;For provenance:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;For all citations, include DOIs, or URLs from the most authoritative, least-likely to fail/change institution if no DOIs available.&lt;/li&gt;
 &lt;li&gt;If no DOI/URL is available, include as much citation information as possible.&lt;/li&gt;
 &lt;li&gt;When DOIs and canonical URLs are available, avoid including things like publisher names and addresses, editor names, etc. This is just clutter.&lt;/li&gt;
 &lt;li&gt;If a URL of dubious longevity is the only available, try to archive it with &lt;a href="https://web.archive.org/"&gt;https://web.archive.org/&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;For clarity:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Never use automatically generated bib information; always clean it up and try to keep consistent.
  &lt;ul&gt;
   &lt;li&gt;I always manually replace the conference name with something more legible. The autogenerated one will often also contain the venue location, the date, the venue’s iteration number. I exclude all that, since most of that is elsewhere in the bib or is irrelevant. You can use bibtex string constants to make this easy.&lt;/li&gt;
   &lt;li&gt;I exclude the ACM SIGPLAN nonsense for the most well-known venues.&lt;/li&gt;
   &lt;li&gt;I typically exclude editors, which don’t really matter&lt;/li&gt;
   &lt;li&gt;I typically exclude page number, except for journal articles&lt;/li&gt;
   &lt;li&gt;I typically exclude the publisher, unless there is no DOI or URL. The publisher is useful if you need to track down a copy of the article, but if you have a DOI or authoritative URL, the publisher shouldn’t be necessary.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
 &lt;li&gt;Avoid duplicate DOIs + URL.&lt;/li&gt;
 &lt;li&gt;Use braces {} to guard any word in titles that need capitalization, such as {AI} or {CIC}.&lt;/li&gt;
 &lt;li&gt;Never use the SIGPLAN Notices version of a citation. Some versions of ICFP, POPL, etc, papers were also published as &amp;ldquo;SIGPLAN Notices&amp;rdquo; journal articles. This can confuse readers. The two versions are the same paper, but have different DOIs and citation information. Make sure to find the conference version, and not the SIGPLAN Notices version. For example, see these two citations:
  &lt;ul&gt;
   &lt;li&gt;&lt;a href="https://dl.acm.org/doi/10.1145/3093333.3009886"&gt;https://dl.acm.org/doi/10.1145/3093333.3009886&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="https://dl.acm.org/doi/10.1145/3009837.3009886"&gt;https://dl.acm.org/doi/10.1145/3009837.3009886&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;To implement these rules, I use Jabref.  It can pull in the autogenerated information, then I manually clean it up according to my rules. Jabref supports marking fields as optional or required depending on the type, so I usually just delete all the optional fields, unless there&amp;rsquo;s not DOI. I use lots of bibtex string constants for common venues, to help clean up the bibtex and keep things consistent.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s always disappointing to me when I read a completely autogenerated bibliography. It&amp;rsquo;s obvious; it looks like slop, and accomplishes neither of the two goals of a bibliography. I was just reading one, and no entry had a DOI at all, titles had incorrect capitalization all over the place, many of the proceedings included cities and dates duplicated in the date field.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Against Vibes Part 2: Ought You Use a Generative Model</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2026/03/13/against-vibes-part-2-ought-you-use-a-generative-model/" />
  <id>urn:https-www-williamjbowman-com:-blog-2026-03-13-against-vibes-part-2-ought-you-use-a-generative-model</id>
  <published>2026-03-13T17:13:06Z</published>
  <updated>2026-03-13T17:13:06Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Since the wide-spread availability and forced deployment of generative models, people have argued about the ethics of using them. Many arguments have been presented to argue that they&amp;rsquo;re &lt;em&gt;bad&lt;/em&gt;: they use too much electricity, boil the oceans, massively infringe on copyright, put people out of work, and generate slop. And therefore, you are ethically obliged to &lt;em&gt;not use them&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I sympathize with the fundamental conclusion: that there is something ethically &lt;em&gt;bad&lt;/em&gt; about the current situation. But I can&amp;rsquo;t really take these arguments seriously, for two reasons: (1) if you look into any one of the arguments, the details are (shocking) a little more complicated (2) it&amp;rsquo;s hard to judge the validity of an ethical argument when no one is willing to make explicit their system of ethics.&lt;/p&gt;

&lt;p&gt;In this post, I&amp;rsquo;m not going to argue about whether generative models are useful. I came up with a model of usefulness in the previous post, which doesn&amp;rsquo;t &lt;em&gt;say&lt;/em&gt; generative models are useful, but gives you a framework for deciding whether one is for a given task and user. For the moment, though, I&amp;rsquo;ll &lt;em&gt;assume for the sake of argument&lt;/em&gt; that &lt;em&gt;there is a use for generative models&lt;/em&gt;, so now we need to answer a different question.&lt;/p&gt;

&lt;p&gt;Ought you use a generative model? I don&amp;rsquo;t mean &lt;em&gt;is it good for a specific task&lt;/em&gt;; that&amp;rsquo;s an &lt;em&gt;is&lt;/em&gt; question, about whether it &lt;em&gt;is&lt;/em&gt; useful. I mean &lt;em&gt;ought you use a model&lt;/em&gt;: is there an ethical argument for or against you using generative models, categorically. I&amp;rsquo;m not going to spoil the ending, because the argument is more important than my conclusion.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="an-ethical-framework"&gt;An Ethical Framework&lt;/h2&gt;

&lt;p&gt;It is slightly infuriating to me that people will argue about ethics without interrogating their own ethical axioms, or those of their interlocutor. It makes so many ethical arguments seem like a series of randomly generated sentences.&lt;/p&gt;

&lt;p&gt;The dominant ethics pretty much everywhere is Utilitarianism. Utilitarianism makes ethical decisions by not supposing apriori what is &lt;em&gt;good&lt;/em&gt; and &lt;em&gt;bad&lt;/em&gt;, but instead that everyone seeks some generalized notion of utility. Maybe you get utility from eating delicious baked goods, but you lose utility from having to work a soul-crushing 9&amp;mdash;5 job. An ethical action, under this framework, is the one that maximizes utility, or in negative utilitarianism, minimizes negative utility.&lt;/p&gt;

&lt;p&gt;This is a stupid ethical framework. It falls prey to various paradoxes, like stupid trolley problems and the utility monster who derives more utility from harming you than you lose by being harmed. It presupposes that &amp;ldquo;utility&amp;rdquo; is quantifiable, and ignores standard problems that arise in optimization problems, like that to optimize one variable you must both ignore and therefore minimize other variables. As a consequentialist framework, it falls prey to many of the standard problems of trying to predict the consequences of one&amp;rsquo;s actions, but as a framework that pretends to be very mathematical, it carries these problems out to infinity. This leads to bonkers philosophies like Effective Altruism and Longtermism, which support absurd beliefs like that to maximize utility we must rush headlong to develop a general purpose artificial intelligence that &lt;em&gt;is&lt;/em&gt; the utility monster and maximize its utility.&lt;/p&gt;

&lt;p&gt;But if I&amp;rsquo;m honest, I think my fundamental problem with it is that it exists to &lt;em&gt;justify harm&lt;/em&gt;&amp;mdash;to say, &amp;ldquo;yes, actually doing harm is the ethically correct choice&amp;rdquo;. That &lt;em&gt;feels wrong&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So let me start with &lt;em&gt;my&lt;/em&gt; ethical axioms, my framework for making ethical decisions. There are many like it, but this one is mine.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m some kind of hedonist: I believe that which is enjoyable is &lt;em&gt;ethically good&lt;/em&gt;, and that which is harmful is &lt;em&gt;ethically bad&lt;/em&gt;. I believe one should take actions that do not cause harm, and ideally take actions that are also enjoyable.&lt;/p&gt;

&lt;p&gt;I believe one is ethically obligated &lt;em&gt;not&lt;/em&gt; to cause harm, but has no positive obligation to cause pleasure; it is actually a kind of negative hedonism. But if you can cause pleasure, that is good.&lt;/p&gt;

&lt;p&gt;My hedonism is stratified: base &lt;code&gt;(Type 0)&lt;/code&gt; good things (e.g., deriving pleasure from eating a pastry) are good; base bad things (e.g., intentionally causing harm to an innocent being) are bad. Deriving pleasure from a &lt;code&gt;(Type 0)&lt;/code&gt; harm, sadism, is a &lt;code&gt;(Type 1)&lt;/code&gt; pleasure that is bad. This is ethically distinct from deriving a &lt;code&gt;(Type 0)&lt;/code&gt; pleasure merely at the expense of something else, like eating a cruelly harmed animal, which is also bad but for a different reason. I have notes on further levels somewhere, but I think these suffice for the purposes of my arguments.&lt;/p&gt;

&lt;p&gt;I reject that &amp;ldquo;good&amp;rdquo; and &amp;ldquo;bad&amp;rdquo; are quantifiable. I cannot decide, &lt;em&gt;ethically&lt;/em&gt;, whether one harm outweighs another. Harm always outweighs pleasure; there is no &amp;ldquo;quantity&amp;rdquo;. &amp;ldquo;Is it more ethical to kill one man to save two men?&amp;rdquo; what a stupid question.&lt;/p&gt;

&lt;p&gt;Instead, my framework is &lt;em&gt;incomplete&lt;/em&gt;: some actions are neither ethical nor unethical. For example, if you are &lt;em&gt;required&lt;/em&gt; to act and any choice you make causes harm, this framework does not help you, except in one way: it decides no action you take is &lt;em&gt;unethical&lt;/em&gt;, since there is no ethical choice. You are only ethically obligated to act in a particular way when you have a choice between an action that causes harm, and an action that does not cause harm. &amp;ldquo;Should you cause harm to save a life?&amp;rdquo;, well, if failing to take action results in harm, and your action results in harm, then either action is equivalent under my framework. I&amp;rsquo;m happier to admit ignorance than to admit paradoxes.&lt;/p&gt;

&lt;p&gt;I also subscribe to some kind of bounded rationality. It is entirely pointless to try to consider all consequences of your actions out to infinity, taking into account all possible information. I am only obligated to act on information I can reasonably be expected to have, and with respect to consequences that are reasonably foreseeable. It also entirely pointless to try to consider all possible actions one could take; you aren&amp;rsquo;t actually infinitely capable. As things get more and more complex, and less and less certain, I say: who knows, try your best.&lt;/p&gt;

&lt;p&gt;So there&amp;rsquo;s my framework: a stratified anti-quantitative bounded negative hedonism. Now that we have a framework, lets start looking at ethical arguments about generative models.&lt;/p&gt;

&lt;h2 id="the-resource-argument"&gt;The Resource Argument&lt;/h2&gt;

&lt;p&gt;One argument against generative models is that these models &amp;ldquo;use too many resources&amp;rdquo;, typically electricity or water. So what are the ethics of this argument?&lt;/p&gt;

&lt;p&gt;Using electricity, in itself, does not cause harm. There are many examples of using electricity bringing joy and happiness to people; those uses are good. There are certainly uses to which electricity can be put that are unethical: I could electrocute you, causing you harm (unless you&amp;rsquo;re into that). But that&amp;rsquo;s not the electricity causing harm; that would be me causing harm.&lt;/p&gt;

&lt;p&gt;The argument about electricity is probably about the effect on climate change, since increased electricity use &lt;em&gt;probably&lt;/em&gt; means increased carbon emissions, which cause harm. So using a generative model, and therefore increasing electricity use, and therefore &lt;em&gt;maybe&lt;/em&gt; increasing emissions, may cause harm.&lt;/p&gt;

&lt;p&gt;This is not a strong argument. The source of electricity matters, for one. If all or most electricity came from renewables, there would be no harm. Increasingly, renewables are becoming a dominant mode of electricity generation.&lt;/p&gt;

&lt;p&gt;Given the uncertainty involved, I don&amp;rsquo;t think this on its own creates an ethical obligation on individuals to use or not use generative models.&lt;/p&gt;

&lt;p&gt;Worse, the argument is contingent on the technical capabilities of generative models. If they become more efficient, do they become ethical?&lt;/p&gt;

&lt;p&gt;There are other other forms of this argument, but they aren&amp;rsquo;t &lt;em&gt;really&lt;/em&gt; about resources. For example, one might argue: they use more electricity than alternatives and produce worse results. I&amp;rsquo;ll call this a &amp;ldquo;slop argument&amp;rdquo;; it&amp;rsquo;s not really about resource use, but about capabilities. This implies it&amp;rsquo;s okay to use more electricity, and therefore possibly worsen climate change, as long as the generative model is &lt;em&gt;good enough&lt;/em&gt;. Any such argument is doomed to failure on many fronts, such as the booster&amp;rsquo;s favourite argument that the models are going to get better and better until they eventually achieve AGI. However, its fundamental flaw in my mind is that it&amp;rsquo;s utilitarian: it &lt;em&gt;justifies&lt;/em&gt; harm.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s one other form of this argument, which shifts the conversation from the mere resource cost to the cost of data centres or the industry as a whole. This is also not really a resource argument: I&amp;rsquo;ll call it &amp;ldquo;the power argument&amp;rdquo;, and address it separately. Again, a data centre using electricity doesn&amp;rsquo;t &lt;em&gt;necessarily&lt;/em&gt; cause harm, and even if it did, it doesn&amp;rsquo;t tell us whether an individual ought to use a generative model, since their action has no effect on the deployment of new data centres and therefore the increased resource usage.&lt;/p&gt;

&lt;p&gt;So in short, I don&amp;rsquo;t think there is an ethical imperative to not use generative models because using them increases resource consumption.&lt;/p&gt;

&lt;h2 id="the-intellectual-property-argument"&gt;The Intellectual Property Argument&lt;/h2&gt;

&lt;p&gt;One argument I find super weird is the intellectual property argument: training generative models has &amp;ldquo;stolen&amp;rdquo; tons of work, or reproduces copyrighted work. This is particularly weird when it comes from people who normally don&amp;rsquo;t give a shit about intellectual property, consuming much of their media via pirate sites or torrents.&lt;/p&gt;

&lt;p&gt;Worse, it&amp;rsquo;s not even clear whether this &lt;em&gt;is&lt;/em&gt; infringement of intellectual property rights. &lt;em&gt;Downloading&lt;/em&gt; copyrighted material isn&amp;rsquo;t a violation; only reproduction is. It&amp;rsquo;s very clear that some models will reproduce stuff from their training data, so you might argue there is infringement there, but it&amp;rsquo;s not clear. Sometimes reproduction is &amp;ldquo;fair use&amp;rdquo;. Reproduction for the purposes of commentary or criticism is usually fair use. The argument for and against has to do with demonstrating economic harm to the rights holder, which might be difficult. Do you think economic harm has been caused to book publishers as a result of training generative models? I kind of doubt it, but maybe. And it&amp;rsquo;s not what generative models are &lt;em&gt;supposed&lt;/em&gt; to be doing, which makes the argument harder. You can genuinely argue that reproduction is a bug to be fixed.&lt;/p&gt;

&lt;p&gt;Even if it &lt;em&gt;were&lt;/em&gt; infringement, while infringement might be illegal, that doesn&amp;rsquo;t make it unethical. Who is harmed if I pirate all of The Fast and Furious movies, or if I train a model that reproduces GPL source code?&lt;/p&gt;

&lt;p&gt;Ignoring whether or not it even &lt;em&gt;is&lt;/em&gt; infringement, intellectual property itself isn&amp;rsquo;t necessarily good. Why is it ethically good to give a person a complete monopoly on the production of something? And for copyright, that monopoly is &lt;em&gt;crazy&lt;/em&gt;. 70 years after the death of the original author? What kind of creativity does that inspire? Why should we give such power to one individual, to legally go after anyone who wants to compete at the production of a good idea whose author is long dead? There&amp;rsquo;s nothing ethical about this, and in fact, I firmly believe intellectual property as it is currently implemented causes significant harm.&lt;/p&gt;

&lt;p&gt;So, no, I don&amp;rsquo;t think you have an ethical imperative to avoid generative models because they might infringe copyright.&lt;/p&gt;

&lt;h2 id="the-slop-argument"&gt;The Slop Argument&lt;/h2&gt;

&lt;p&gt;A very common complaint, and sort of argument, is that generative models produce slop. That is, they produce output that is not of high quality; it doesn&amp;rsquo;t meet the requirements or goals of the output. In technical work, it doesn&amp;rsquo;t meet engineering standards or design requirements. In creative work, it fails to express anything of artist interest or intent.&lt;/p&gt;

&lt;p&gt;This is not really an ethical argument, but a description of technical capability. If the models improve, do they become ethical to use? The mere slop argument would suggest they do!&lt;/p&gt;

&lt;p&gt;It could be an ethical argument, if you form it as a utilitarian argument: they produce more harm than the produce utility. This would require us to admit they produce harm, and start to &lt;em&gt;justify&lt;/em&gt; the harm. But I&amp;rsquo;ve already rejected utilitarianism.&lt;/p&gt;

&lt;p&gt;If not careful, the slop argument also attributes the cause of the harm to the &lt;em&gt;generative model&lt;/em&gt;. But a model does not, despite the fevered branding of the industry, have agency. It cannot produce something that causes harm by itself. If I go stopper all your sinks and leave the water running in your house, it wasn&amp;rsquo;t the water that caused you harm.&lt;/p&gt;

&lt;p&gt;If the output is poor and &lt;em&gt;you&lt;/em&gt; decide to use it in a situation that causes harm, &lt;em&gt;you&lt;/em&gt; caused harm. For example, if you submit a thoughtless research paper that wastes reviewer time, it was not the use of the generative model that wasted reviewer time, it was &lt;em&gt;you&lt;/em&gt;. If I&amp;rsquo;m forced to reject garbage generated pull requests, it&amp;rsquo;s not the generative model&amp;rsquo;s fault, it&amp;rsquo;s the fault of whoever setup the model or agent and caused it to go out spewing slop.&lt;/p&gt;

&lt;p&gt;This argument might be a good argument for not allowing generative models to be used in some settings. If the balance of probability is that the output will cause harm compared to an alternative, best not to use a generative model. This quickly becomes a technical argument: whether or not the quality of the output can be assured. Perhaps it can&amp;rsquo;t, so a conservative approach is needed. But this isn&amp;rsquo;t an ethical argument categorically forbidding the use of generative models.&lt;/p&gt;

&lt;p&gt;So I don&amp;rsquo;t think there is an ethical imperative to not use generative models because some of their output is not of high quality.&lt;/p&gt;

&lt;h2 id="the-employment-argument"&gt;The Employment Argument&lt;/h2&gt;

&lt;p&gt;One argument is see from time to time is: generative models are putting people out of jobs, and therefore you shouldn&amp;rsquo;t use them. As statement, this is a confused argument in many ways.&lt;/p&gt;

&lt;p&gt;For one, an individual&amp;rsquo;s use of a generative model probably doesn&amp;rsquo;t put anyone out of a job.&lt;/p&gt;

&lt;p&gt;For two, it&amp;rsquo;s not clear to me that this is necessarily harmful. &amp;ldquo;Not having a job&amp;rdquo; is not necessarily harmful, and so this debate quickly devolves into questions about unemployment, about whether new jobs created in place of old jobs, &lt;em&gt;etc.&lt;/em&gt; This has nothing to do with an individual&amp;rsquo;s use of a generative model, and much more to do with the economic systems we&amp;rsquo;re embedded in, and all the particulars matter.&lt;/p&gt;

&lt;p&gt;For three, it&amp;rsquo;s not obviously true that generative models are putting people out of work. Many CEO&amp;rsquo;s are &lt;em&gt;claiming&lt;/em&gt; that&amp;rsquo;s why they&amp;rsquo;re firing people, but there&amp;rsquo;s plenty of evidence to suggest that&amp;rsquo;s either a lie to make layoffs more acceptable, or a lie to convince shareholders that the trillions in investments are paying off.&lt;/p&gt;

&lt;p&gt;Finally, the generative model didn&amp;rsquo;t decide to lay anyone off and therefore make their continued existence in a society in which having a job is a necessary precondition to continued survival. Some profit seeking business boy did.&lt;/p&gt;

&lt;p&gt;So I don&amp;rsquo;t really think there&amp;rsquo;s an ethical imperative to not use generative models based on layoffs.&lt;/p&gt;

&lt;h2 id="the-power-argument"&gt;The Power Argument&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s only one argument I buy at all, and I don&amp;rsquo;t see it very often.&lt;/p&gt;

&lt;p&gt;Even phrasing this argument requires care: we have to separate the individual use of a generative model from the &amp;ldquo;AI&amp;rdquo; industry.&lt;/p&gt;

&lt;p&gt;Here, I use &amp;ldquo;AI&amp;rdquo;, which I&amp;rsquo;ve been loath to use until now, very explicitly. &amp;ldquo;AI&amp;rdquo; is a brand. It is not a technology. It is a marketing term deployed to convince people that the underlying technology (most recently, generative models) is more capable than it is&amp;mdash;that the technology is &amp;ldquo;intelligent&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;The power argument goes like this: the &amp;ldquo;AI&amp;rdquo; industry is accumulating power at the expenses of others, possibly doing harm in the process, possibly using that power to do harm. Therefore one should not use generative models.&lt;/p&gt;

&lt;p&gt;This argument&amp;hellip; doesn&amp;rsquo;t follow. Not as is, anyway.&lt;/p&gt;

&lt;p&gt;The &amp;ldquo;AI&amp;rdquo; industry is concentrating power in the hands of capital, and removing it from labour. The claim of the industry is that tasks previously only able to be done by highly skilled people can&amp;mdash;sort of, in some cases&amp;mdash;be done by generative models. This would allow someone with a lot of GPUs and a ton data to exercise power over people they previously couldn&amp;rsquo;t. And the industry definitely wants to use that power, and obviously doesn&amp;rsquo;t care who they harm in the process.&lt;/p&gt;

&lt;p&gt;In fact, all the previous arguments can be augmented into a power argument, and they start to make more sense.&lt;/p&gt;

&lt;p&gt;The problem with resource usage isn&amp;rsquo;t about generative models, but about the &amp;ldquo;AI&amp;rdquo; industry. The &amp;ldquo;AI&amp;rdquo; industry is spinning up data centre after data centre, without regard for resource use. They sometimes deploy carbon-intensive generators to meet capacity, or consume already scarce water because they have the power to take it from others who need it. These are direct harms that the &amp;ldquo;AI&amp;rdquo; industry is engaging in.&lt;/p&gt;

&lt;p&gt;The problem with slop is not that one can produce poor quality work. That is not even a new problem. The enshittification process was started long before generative models reached their current capabilities. Long before large language models, others forms of text generation were used to mass produce garbage webpages for small amounts of profit. The problem is that the &amp;ldquo;AI&amp;rdquo; industry is wielding an immense amount of power to force &amp;ldquo;AI&amp;rdquo; use that lowers the quality of work into new areas. They&amp;rsquo;re replacing web search with &amp;ldquo;AI&amp;rdquo;. They&amp;rsquo;re replacing customer service with &amp;ldquo;AI&amp;rdquo; (chatbots were already common, but this makes them next to trivial to deploy). They&amp;rsquo;re forcing engineers to use &amp;ldquo;AI&amp;rdquo; to generate software. They&amp;rsquo;re deploying &amp;ldquo;AI&amp;rdquo; to make decisions about who to investigate for crimes, who to arrest, who to kill.&lt;/p&gt;

&lt;p&gt;The problem with employment isn&amp;rsquo;t that generative models can take jobs, which I doubt, but that the &amp;ldquo;AI&amp;rdquo; industry can replace the output of skilled workers with poor quality output created by generative models. The &amp;ldquo;AI&amp;rdquo; industry can replace labour with capital. They&amp;rsquo;re not even particularly coy about this; some of them have gone on record about this goal. The goal is to gain power over labour, and exercise that power for profit.&lt;/p&gt;

&lt;p&gt;Interestingly, sometimes I see the &lt;em&gt;opposite&lt;/em&gt; of this argument: people arguing that somehow generative models &lt;em&gt;democratize&lt;/em&gt; skilled labour. This is &lt;em&gt;madness&lt;/em&gt;. That &lt;em&gt;could&lt;/em&gt;, possibly, maybe, be true if these models were tiny and could run on lower powered devices that everyone had access to. Even then, I&amp;rsquo;m skeptical, as so far I don&amp;rsquo;t believe they can be used unless you already have the domain skills required to do the work in the first place.&lt;/p&gt;

&lt;p&gt;But ignoring my arguments about utility, it&amp;rsquo;s certainly not true now that generative models give labour power. The only useful ones burn billions of dollars merely to operate, and required almost trillions to reach that state. The only useful models are owned and operated by the &amp;ldquo;AI&amp;rdquo; industry. If you want to use them, you have to go to the &amp;ldquo;AI&amp;rdquo; industry. That&amp;rsquo;s not democratization of anything; that&amp;rsquo;s the &amp;ldquo;AI&amp;rdquo; industry having power over you.&lt;/p&gt;

&lt;p&gt;So the &amp;ldquo;AI&amp;rdquo; industry definitely has power, and they use that power to cause harm. So is there an ethical imperative to not use generative models, based on the power of the &amp;ldquo;AI&amp;rdquo; industry?&lt;/p&gt;

&lt;p&gt;Well, these harms are not caused by generative models. They&amp;rsquo;re caused by the &amp;ldquo;AI&amp;rdquo; industry, not the underlying technology. They do not go away if you stop using generative models.&lt;/p&gt;

&lt;p&gt;But your action to use a generative model &lt;em&gt;may&lt;/em&gt; give power to this industry, and thus, cause harm. So let&amp;rsquo;s consider individual actions.&lt;/p&gt;

&lt;h2 id="the-individual-action-problem"&gt;The Individual Action Problem&lt;/h2&gt;

&lt;p&gt;The main source of the &amp;ldquo;AI&amp;rdquo; industry&amp;rsquo;s power is economic power. They promise to be able to reduce labour costs, and they need a lot of money to make that a reality (or so their pitch goes).&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m skeptical that mere use supports the &amp;ldquo;AI&amp;rdquo; industry in a monetary sense. The &amp;ldquo;AI&amp;rdquo; industry is currently supported by an ungodly amount of investor money and debt, not by the small amount of revenue it brings in. You using a generative model, and even paying a subscription, does not provide support for the power of this industry.&lt;/p&gt;

&lt;p&gt;I want to be clear that I&amp;rsquo;m not rejecting individual action. I think individual action is important. If your action causes harm, no matter how small, I consider that unethical.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m saying &lt;em&gt;this particular&lt;/em&gt; individual action, using a generative model or even subscribing to a generative model, does not cause harm &lt;em&gt;at all&lt;/em&gt;. This is not the ethical problem, because it does not contribute to the power of this industry. If every human on earth boycotted the industry, it would still have as much power as it currently has. In fact, given that most subscriptions appear to &lt;em&gt;cost&lt;/em&gt; the &amp;ldquo;AI&amp;rdquo; industry money, they might be better off if we boycotted them. We could debate this; I don&amp;rsquo;t think it&amp;rsquo;s clear. But let&amp;rsquo;s accept my premise for a moment.&lt;/p&gt;

&lt;p&gt;The money you give the &amp;ldquo;AI&amp;rdquo; industry is not the only way to give the &amp;ldquo;AI&amp;rdquo; industry power, and taking these other actions causes harm. Using generative models uncritically gives the &amp;ldquo;AI&amp;rdquo; industry power, supporting the claims they make and the transfer of power to them. Reporting on generative models and the &amp;ldquo;AI&amp;rdquo; industry uncritically gives their claims credibility, giving the &amp;ldquo;AI&amp;rdquo; industry power. Enabling their wide-spread deployment, in addition to any harm caused by slop, gives the &amp;ldquo;AI&amp;rdquo; industry power over the context in which they were deployed.&lt;/p&gt;

&lt;p&gt;In addition to being a hedonist, or perhaps because of it, I&amp;rsquo;m also an anarchist. I am &lt;em&gt;very&lt;/em&gt; against power and hierarchy. I think the main thing they do is cause harm, and we should seek to reduce power and hierarchy as much as possible.&lt;/p&gt;

&lt;p&gt;I think there is plenty of evidence that this technology, in the hands of this industry, &lt;em&gt;is&lt;/em&gt; causing harm. I don&amp;rsquo;t think certain individual uses of generative models are unethical, but any action that empowers the &amp;ldquo;AI&amp;rdquo; industry is certainly unethical.&lt;/p&gt;

&lt;h2 id="so-what-should-you-do"&gt;So what should you do?&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m normally pretty reluctant to give direct advice on actions you should take. My standard disclaimer is: all advice is one person&amp;rsquo;s opinion.&lt;/p&gt;

&lt;p&gt;&amp;hellip; But we&amp;rsquo;re several thousand words in and I&amp;rsquo;ve made my ethical arguments as clear and precise as I can, so strap in buddy while I tell you what to think and how to act.&lt;/p&gt;

&lt;p&gt;There is no ethical imperative to not use a generative model; that depends on whether the particular use will cause harm or not.&lt;/p&gt;

&lt;p&gt;There is an ethical imperative to deny &amp;ldquo;AI&amp;rdquo; (the industry) power.&lt;/p&gt;

&lt;p&gt;So how does one deny &amp;ldquo;AI&amp;rdquo; power? Well if I knew that, I assure you we wouldn&amp;rsquo;t be in this mess. But I can tell you some actions I&amp;rsquo;m taking.&lt;/p&gt;

&lt;p&gt;First is education.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve given talks on &amp;ldquo;prompt engineering&amp;rdquo; and how it&amp;rsquo;s not engineering, written these blog posts, and remain engaged in the &amp;ldquo;AI&amp;rdquo; discourse despite hating it.&lt;/p&gt;

&lt;p&gt;I want people to think clearly about this technology, this industry, and ethics. I want people to understand the technology, which is not magic. I think this is necessary to refute the lies this industry is telling. I think it&amp;rsquo;s necessary to demonstrate exactly what the technology is and is not capable of. I want people to be able to separate out different concerns and arguments so &lt;em&gt;they&lt;/em&gt; can refute lies and nonsense arguments others are telling.&lt;/p&gt;

&lt;p&gt;Will this work? I don&amp;rsquo;t know; maybe.&lt;/p&gt;

&lt;p&gt;Second is policy work.&lt;/p&gt;

&lt;p&gt;At UBC, I&amp;rsquo;ve tried to inform policy around the use of generative model. I&amp;rsquo;m trying to restrict the use of generative models around the university. Some of that is public, some is not. Some has been successful, some has not.&lt;/p&gt;

&lt;p&gt;In my own lab, I am in a position of power (ugh), and in that role I try to create sensible policies. I don&amp;rsquo;t outright forbid the use of generative models; I&amp;rsquo;m against my own power, and not sure using a generative model is necessarily problematic. I do make clear that the user is responsible for the use of the generative model. Every line of every artifact, if the user cannot stand by it, cannot justify a design decision, cannot explain something, then &lt;em&gt;they&lt;/em&gt;, not the &amp;ldquo;AI&amp;rdquo;, have failed.&lt;/p&gt;

&lt;p&gt;Third is boycotting.&lt;/p&gt;

&lt;p&gt;As I said already, I&amp;rsquo;m not sure that mere use is unethical. It&amp;rsquo;s certainly not if you have no choice. Even if you have a choice, mere use may not empower the industry.&lt;/p&gt;

&lt;p&gt;Still, I, largely, refuse to pay money for this technology. (I spent $10 on various experiments.) I don&amp;rsquo;t think this has a direct effect, but I think it&amp;rsquo;s an important line to draw to do what I can to deny &amp;ldquo;AI&amp;rdquo; power. I try to avoid technologies and companies and products that adopt &amp;ldquo;AI&amp;rdquo; and support this industry.&lt;/p&gt;

&lt;p&gt;I think boycotts have indirect effects as well as direct effects. Refusing to engage can cause conversations, it can change minds. That will probably have more effect than denying these companies a few dollars a month.&lt;/p&gt;

&lt;p&gt;I have no qualms about using local models. The ones I&amp;rsquo;ve used are little more than toys. We have some running in the lab that I haven&amp;rsquo;t tried; maybe I&amp;rsquo;ll build a machine with a proper GPU and give those a shot.&lt;/p&gt;

&lt;p&gt;I do use some industry models; as a faculty member, I can access some pro models for free. I don&amp;rsquo;t use them very enthusiastically, but I also don&amp;rsquo;t worry too much about using them. I think using them is necessary to understand them and to educate others. And it marginally costs the industry money when I use them, which is a small bonus.&lt;/p&gt;

&lt;p&gt;Fourth is sabotage.&lt;/p&gt;

&lt;p&gt;I have deployed lots of &amp;ldquo;AI&amp;rdquo; countermeasures, both for training and inference. I don&amp;rsquo;t know how effective these are, but I deploy them anyway. I should probably go read some activism books, such as &lt;em&gt;How to Blow Up a Pipeline: Learning to Fight in a World on Fire&lt;/em&gt;, to find more effective strategies.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not sure any of this will be effective, but I&amp;rsquo;m ethically obligated to do something.&lt;/p&gt;

&lt;h2 id="addendum"&gt;Addendum&lt;/h2&gt;

&lt;p&gt;There are many things I wish I&amp;rsquo;d said differently, and other things I could have considered in this blog post. I&amp;rsquo;m going to leave it mostly as is, but I will add a few addenda following discussions:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;I didn&amp;rsquo;t discuss one argument that I didn&amp;rsquo;t see phrased as an ethical  argument until after publishing this: the brain rot argument.  Mere use of a generative model can harm the user, by limiting stunting their  learning.  There is scientific evidence that supports this in the context of education.  I hadn&amp;rsquo;t seen it posed as harm, but instead about the effectiveness of the tools for education.  However, I find the harm argument compelling, and don&amp;rsquo;t see why harm against  oneself shouldn&amp;rsquo;t be considered unethical.&lt;/li&gt;
 &lt;li&gt;One criticism of my &amp;ldquo;mere use&amp;rdquo; arguments is that they suppose a &amp;ldquo;spherical  [generative model] user in a vacuum&amp;rdquo;. This is a valid criticism. In  practice, a generative model user may be unable to act as independently of all  systems and all harms as I&amp;rsquo;ve presented, or be unable to correctly judge the  quality and therefore harm of their actions.  Therefore an ethical user may only exist in theory.  That&amp;rsquo;s very possibly true, and I think there&amp;rsquo;s plenty of evidence to support it.  I think it&amp;rsquo;s still useful to isolate the pure theory of harm for the  purposes of discussion.&lt;/li&gt;
 &lt;li&gt;In the power argument, mere use may be unethical because mere use may  provide e.g. usage analytics that support continued investment and therefore  the concentration of power.  This is a pretty compelling argument, and is probably related to why I  instinctively boycott these things.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;There are certainly other arguments I haven&amp;rsquo;t considered, but as I said in the beginning, my conclusion is not the important part of this post.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Against Vibes: When is a Generative Model Useful</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2026/03/05/against-vibes-when-is-a-generative-model-useful/" />
  <id>urn:https-www-williamjbowman-com:-blog-2026-03-05-against-vibes-when-is-a-generative-model-useful</id>
  <published>2026-03-05T23:58:20Z</published>
  <updated>2026-03-05T23:58:20Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Let&amp;rsquo;s suppose I wanted to answer a question: is the tool X useful for the task Y. If I were scientific about this, I would analyze the properties of tool X and develop a model, and the task Y and the requirements for it and develop a model, and I would use my models to predict the behaviour of tool X in the context of task Y. &amp;ldquo;Can I use timber instead of stainless steel as a support beam for this structure?&amp;rdquo; &amp;ldquo;Will this acid be an appropriate solvent for this reaction?&amp;rdquo; &amp;ldquo;Will this programming language provide these real-time guarantees?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;The discourse on generative models is not like this. Instead, you get claims like &amp;ldquo;software engineering is dead&amp;rdquo;, and attempts to shove generative models into literally everything without a thought. Search? Generative models. Code completion? Generative models. Summarization? Generative models. Voice to text? Generative models. Stock images? Generative models.&lt;/p&gt;

&lt;p&gt;Any attempt to criticize this tends to go in circles and/or have people arguing past each other. Is a generative model useful for internet search? Well, look, it produces text that is plausibly related to the input prompt, so. So&amp;hellip; what? That doesn&amp;rsquo;t answer the question. But the newest models are so much better! Better at.. what?&lt;/p&gt;

&lt;p&gt;I was upset about this when it was being called &amp;ldquo;prompt engineering&amp;rdquo;, and found no sign of engineering, but instead a series of vibes about how to phrase a prompt in a particular version of a particular model, which sometimes produced output that is plausibly related to the input prompt and therefore plausibly close to what you might have intended. I&amp;rsquo;m upset now when people are making claims that agents are so useful, but can&amp;rsquo;t tell me when or why or how they&amp;rsquo;re useful beyond vibes about feeling more productive (vibes that have been refuted by real science contrasting objective measure of productivity vs. subjective reports), or examples of having produced a lot of plausible output.&lt;/p&gt;

&lt;p&gt;(Okay, there are some researchers doing actual science and writing papers; I&amp;rsquo;m talking about the arguments being made as this stuff is integrating into schools, workplaces, etc.)&lt;/p&gt;

&lt;p&gt;I want to &lt;em&gt;know&lt;/em&gt; when generative models are &lt;em&gt;useful&lt;/em&gt;. I don&amp;rsquo;t want to &lt;em&gt;feel&lt;/em&gt; like they&amp;rsquo;re useful, that&amp;rsquo;s just a vibe. I&amp;rsquo;ve been a generative model skeptic basically from the beginning. I could not convince myself that generative models were useful. But I was also skeptical of my own subjective experience. I could imagine that a model capable of produce code from natural language would be useful, in some use cases that I had not found. I imagine there must be a model of when a generative model X is useful for task Y.&lt;/p&gt;

&lt;p&gt;In this post, I&amp;rsquo;m not addressing ethical, political, or social questions. Those questions are important, and I want to address them separately from what the technology is capable of. Just for context: I think the widespread deployment of this technology is deeply problematic and irresponsible. I think further investment in it at its current scale is an almost criminal level of fiduciary negligence and will cause economic harm. I think the ethics of all of this are deeply troubling.&lt;/p&gt;

&lt;p&gt;But for now, I just want to know what they&amp;rsquo;re technically capable of.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="a-model-of-generative-model-utility"&gt;A model of generative model utility&lt;/h2&gt;

&lt;p&gt;I think the usefulness of a generative model is a function of three things:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;What is the cost of encoding a generative task in a prompt vs. directly producing the artifact? This is a function of the task, the model, and the user.&lt;/li&gt;
 &lt;li&gt;What is the cost of verifying the generated artifact meets requirements vs. a directly produced artifact? This is mostly a function of the task and the user, but also the generative model.&lt;/li&gt;
 &lt;li&gt;How much is the task dependent on the artifact vs. the process? This is a function of the task.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Each of these touch on things many others have said, but I think all three considered simultaneously are important. They make it possible to be scientific in an argument about the use of generative models.&lt;/p&gt;

&lt;p&gt;If you want to claim a new model is &amp;ldquo;more useful&amp;rdquo;, you must specify all of these variables. You must specify a class of tasks, and demonstrate the cost of encoding for some set of users is lower than directly producing the artifacts of tasks; or that perhaps encoding is higher, but that verifying design requirements is lower.&lt;/p&gt;

&lt;p&gt;More importantly, if I want to predict whether a generative model will be useful, I have a model to work with.&lt;/p&gt;

&lt;p&gt;My model predicts that usefulness of a generative model may decrease as task complexity increases. Generative models are probabilistic: the output will be less likely to satisfy complex requirements, particularly if those requirements differ from common patterns in the training data, or worse, &lt;em&gt;subtly&lt;/em&gt; different from common patterns. Verifying complex requirements is also hard, and harder than having a human following good engineering processes that lead to more easily verified outputs.&lt;/p&gt;

&lt;p&gt;On the other hand, generative models should be useful when directly creating the artifact is hard for the user, but verifying the artifact is trivial. This could be the case for artifacts that require cross-referencing extremely specific information that is time consuming for a user to do, but once done, is trivial to check. It could also be the case for generative models integrated into formal verification systems with extremely reliable and highly automated verification, where no knowledge of the artifact being generated is necessary. But in general, it is unlikely to be the case for a novice in some domain trying to generate a complex artifact, since the user will not have the expertise to ensure the output meets requirements. This predicts there will still be a need for users of generative models to have domain expertise.&lt;/p&gt;

&lt;p&gt;The model also predict that generative models are essentially useless for tasks that are highly process dependent, since all a generative model can do is produce an artifact by a blackbox process.&lt;/p&gt;

&lt;h3 id="1-relative-encoding-cost"&gt;1. Relative Encoding Cost&lt;/h3&gt;

&lt;p&gt;A lot of arguments in favour of the usefulness of generative models make arguments about, in essence, the relative encoding cost. For a generative model to be useful, the total encoding cost must be lower than the total cost of directly producing the artifact.&lt;/p&gt;

&lt;p&gt;The total encoding cost includes all the work that goes in to writing a prompt, and all of the compute required to run the prompt. If the task is simple to express in a prompt, the total encoding cost is low. If the task is both simple to express in a prompt, and tedious or difficult to produce directly, the relative encoding cost is low. As models get more capable, more complex prompts can be easily expressed: more semantically dense prompts can be used, referencing more information from the training data. An agent capable of refining or retrying a task after an initial prompt might succeed at a complex task after a single simple prompt. However, both of these also increase the compute cost of the prompt, sometimes substantially, driving up the total encoding cost. More &amp;ldquo;capable&amp;rdquo; models may have a higher probability of producing correct output, reducing costs reprompting with more information (&amp;ldquo;prompt engineering&amp;rdquo;), and possibly reducing verification costs.&lt;/p&gt;

&lt;p&gt;Moreover, as a &lt;em&gt;user&lt;/em&gt; gets more capable, they may be able to complete the tasks directly much faster than they can prompt a model to do it, driving up the relative encoding cost.&lt;/p&gt;

&lt;p&gt;One may argue that the newest models are &amp;ldquo;more powerful&amp;rdquo; or &amp;ldquo;actually intelligent&amp;rdquo; or whatever. But these are unscientific claims.&lt;/p&gt;

&lt;p&gt;The scientific version of these claims is &amp;ldquo;the total encoding cost (for some class of tasks) is lower than previous models&amp;rdquo;. Phrased this way, it&amp;rsquo;s clear this still doesn&amp;rsquo;t mean the new models are useful.&lt;/p&gt;

&lt;p&gt;For most of my tasks, I think the relative encoding cost has been high. Many of my software engineering tasks are constructing small, semantically dense programs, with very specific design requirements, in a language much more concise than English that I can write fluently. I can systematically design and implement such software faster than I can encode the specification into a prompt for a generative model.&lt;/p&gt;

&lt;p&gt;As one example, I tried using Claude Opus 4.6 to generate a program that would interpret a custom DSL I use for typesetting grammars, and generate Haskell type definitions. After 8 hours of prompting, several million tokens, the code it generated was still absolutely useless. It passed the tests I had prompted it on, but just looking at the code, one could easily identify type errors and logic that tried to special case specific identifiers from the tests. The logic for sanitizing identifiers was a mess, and would occasionally generate empty strings. A correct implementation would take me 300&amp;mdash;400 line of code to write, which I can certainly write in less than 8 hours.&lt;/p&gt;

&lt;p&gt;However, not true of &lt;em&gt;all&lt;/em&gt; tasks are writing semantically dense code with very tight design requirements. For example, I was recently trying to install a package whose name I forgot. I prompted the model to &amp;ldquo;install that x11 fake gui thing&amp;rdquo;, a trivial prompt. Actually completing the task myself would have required a lot of &lt;em&gt;tedious&lt;/em&gt; work, with lots of accidental complexity. I would have needed to search the internet to identify the name of this software, cross-reference that with the distribution of the operating system I was running and the name used by its package manager, possibly cross-reference the installation command for this particular package manager, and then write and execute a shell script to perform the install. I was able to use the agent to do all of this with an extremely easy to write prompt. This task had a very low relative encoding cost.&lt;/p&gt;

&lt;h3 id="2-relative-verification-cost"&gt;2. Relative Verification Cost&lt;/h3&gt;

&lt;p&gt;Some arguments about generative models focus on verification: &amp;ldquo;formal verification will become more important as more code is generated&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;I think these arguments are also unscientific. Verification is also not magic. Software designed in one way may be easier to verify than in another way. A user who carefully designed and implemented the software may be able to more easily verify it than when dropped into a fully generated code base.&lt;/p&gt;

&lt;p&gt;All of this depends on the task, the user, and what the model is capable of generating. For my prompt to install a package, verification is trivial. I will recognize the right command when I see it, and it&amp;rsquo;s one line long.&lt;/p&gt;

&lt;p&gt;Relative verification cost also goes up with the size of the task. If you&amp;rsquo;re generating a 1 line script, no problem. If you&amp;rsquo;re trying to generate a very large artifact, you&amp;rsquo;re going to get bored validating every command, every edit. You&amp;rsquo;re not going to be able to check every line of code that was generated. You&amp;rsquo;re going to need some other approach to verifying the output, increasing cost.&lt;/p&gt;

&lt;p&gt;Relative verification cost also depends on the user. If I&amp;rsquo;m prompting a model to produce Racket, a language I am very fluent in, I can quickly evaluate the design and implementation of the generated code. If I tried to prompt a model to produce C, I&amp;rsquo;d be far better off just writing the C myself, following a systematic approach that would result in safe C. And then running it in a sandbox. After running some sanitizers on it.&lt;/p&gt;

&lt;p&gt;Relative verification cost somewhat depends on the capabilities of the model, too. Some of the early models I experimented with produced trash code. Not merely bad code with bad design, but errors so basic I wouldn&amp;rsquo;t think to look for them: it would produce Racket with mismatched parenthesis, references to functions that didn&amp;rsquo;t exist, etc. Those are easy enough to detect by running the compiler, but what about the ones that aren&amp;rsquo;t so easy to detect?&lt;/p&gt;

&lt;p&gt;One key part of this relative verification cost is that generative models produce &lt;em&gt;plausible output&lt;/em&gt;. It&amp;rsquo;s not accurate to say a model produces &amp;ldquo;correct&amp;rdquo; or &amp;ldquo;incorrect&amp;rdquo; output, or &amp;ldquo;makes mistakes&amp;rdquo;. It does exactly what it&amp;rsquo;s designed to do: produce output that is statistically related to the input prompt, in some way. That doesn&amp;rsquo;t mean &amp;ldquo;statistically correct&amp;rdquo;, just &amp;ldquo;statistically related&amp;rdquo;. All output is correct, in the sense that all it&amp;rsquo;s suppose to be is a point in the distribution of things related to the prompt. Maybe you produce C code with memory errors most of the time, but &lt;em&gt;most&lt;/em&gt; C code has memory errors. Maybe you mostly produce correct bash scripts for installing packages, because most bash scripts for installing packages on the internet are correct.&lt;/p&gt;

&lt;p&gt;Plausibility of generative models greatly increases the relative verification cost, since the output is essentially optimized to be &lt;em&gt;close&lt;/em&gt; to correct. I&amp;rsquo;d predict that relative verification cost could &lt;em&gt;go up&lt;/em&gt; as the models get more complex. The class of errors we&amp;rsquo;re likely to find in generated code will be very different than the class of errors we&amp;rsquo;re used to looking for in human generated code: generated code will have &lt;em&gt;subtle&lt;/em&gt; errors. As the models get more capable, you might be more likely to trust the output, and less likely to spot these subtle errors. This cost can be reduced by formal methods, but formal methods aren&amp;rsquo;t necessarily cheap. You might be better off with an engineer following a design process.&lt;/p&gt;

&lt;p&gt;For some tasks, verifying the output may be impossible, or at least impossible without redoing exactly the work you were trying to use a generative model for. I think internet search is a good example of this. A generative model generated response to an internet search query that you did not know the answer too is essentially unverifable, unless you go and search for credible sources to verify the summary. At which point, the generative model did entirely wasted work.&lt;/p&gt;

&lt;h3 id="3-artifact-vs-process"&gt;3. Artifact vs. Process&lt;/h3&gt;

&lt;p&gt;Some tasks aren&amp;rsquo;t about the output. Or maybe they aren&amp;rsquo;t &lt;em&gt;just&lt;/em&gt; about the output, and require the output be created following a specific process.&lt;/p&gt;

&lt;p&gt;Easy examples of this are in education. I don&amp;rsquo;t need students to implement factorial for the one billionth time because I need an implementation of factorial. They implement factorial because going through the process creates knowledge in their head. Writing code is a fundamentally different process than reading code, in the same way that writing this blog post is a fundamentally different process than reading it.&lt;/p&gt;

&lt;p&gt;This blog post is an example of a process-driven task. I&amp;rsquo;m writing this post. My hands are typing the words that appear in this post. They are not merely typing prompts that cause a generative model to generate plausibly-related words. That&amp;rsquo;s because I&amp;rsquo;m not trying to create a blog post. I&amp;rsquo;m trying to create knowledge, within myself and then within others. Writing this post is me thinking through all the details.&lt;/p&gt;

&lt;p&gt;Process-driven tasks also come up in engineering. Some engineering requires specific processes are followed, because if the processes are followed, the end result will satisfy certain properties that may be difficult or impossible to verify just looking at the artifact. A large fruit company, for example, might forbid engineers from contributing to open source projects as part of the process by which they engineer software in order to mitigate intellectual property risks. There is no way, just looking at the software the engineer writes, to guarantee freedom from those risks.&lt;/p&gt;

&lt;p&gt;The process argument against generative models comes up a lot. The argument goes something like &amp;ldquo;X is about human communication, or creativity, so generative models cannot be used to create Y&amp;rdquo;. And I &lt;em&gt;really&lt;/em&gt; sympathize with this argument, because I think far too much is produced by ignoring the process.&lt;/p&gt;

&lt;p&gt;But there are certainly tasks for which I really only* care about the output. My shell script example is one: I don&amp;rsquo;t care how the package gets installed; I care that it&amp;rsquo;s installed. (* Well, assuming the output wasn&amp;rsquo;t produced through some truly problematic process, which, well&amp;hellip; but that&amp;rsquo;s a future post.)&lt;/p&gt;

&lt;p&gt;The same can be true of writing. I am writing this post manually, because the process matters, but some writing is functional. For example, I used a generative model to draft a policy document. Policy documents don&amp;rsquo;t have much creative structure to them; they express a set of rules. I&amp;rsquo;m still reading and redrafting the document, since I need the particulars to better suit me, but it was useful to start from a generated draft, in the same way I might start from a template.&lt;/p&gt;

&lt;p&gt;But even when the output is boring and easily verified, the process may be important. Junior engineers might write lots of boring, easily verified code. It might be extremely cheap the replace them with agents. But junior engineers writing that code are going through a process by which they gain experience, knowledge, and skills. Generative models can replace their output, but nothing can replace that process.&lt;/p&gt;

&lt;p&gt;For almost all software I write, I do care about the process. I&amp;rsquo;m typically designing software as part of research, and me doing the design and implementation work creates knowledge that I will then share. The &lt;em&gt;software&lt;/em&gt; isn&amp;rsquo;t the important output, or not the only important output. I think this is another big reason I haven&amp;rsquo;t found these things useful, and why it&amp;rsquo;s been such a struggle to figure out how they could possibly be useful.&lt;/p&gt;

&lt;h2 id="we-just-need-people-who-can-make-a-computer-produce-useful-work"&gt;We just need people who can make a computer produce useful work&lt;/h2&gt;

&lt;p&gt;So when is a generative model useful? Just when the (1) relative cost of encoding the work in a prompt is low (compared to doing the work some other way); (2) and/or relative cost of verifying the output satisfies requirements is low; (3) and the process used to complete the work doesn&amp;rsquo;t matter. To judge all of this accurately, the user of the model needs to know quite a lot about the work being done, about verifying design requirements in the domain, and about working with generative models and/or the model in question.&lt;/p&gt;

&lt;p&gt;Navigating these trade-offs is engineering. If you&amp;rsquo;re navigating those trade-offs to produce software, you&amp;rsquo;re doing software engineering. If you&amp;rsquo;re not considering these trade-offs, you&amp;rsquo;re just going on vibes and what you produce will be something between accidentally useful and extremely harmful.&lt;/p&gt;

&lt;p&gt;These trade-offs aren&amp;rsquo;t unique to generative models, but one thing is: they&amp;rsquo;ve made it incredibly cheap to produce an immense amount of output that is plausibly described by a natural language description. But plausible doesn&amp;rsquo;t mean useful, and there&amp;rsquo;s nothing in generative models that could ever guarantee useful output. As the models get more sophisticated, the complexity of the output and the prompts are getting more sophisticated. That&amp;rsquo;s not necessarily more useful. As that complexity goes up, so do the costs: of compute, of verification, and of relying on output over process.&lt;/p&gt;

&lt;p&gt;I understand the temptation of these tools. Sometimes useful work is incredibly complex and frustrating to do. Writing software, running scripts, and organizing all my notes can be very tedious. Sometimes that is accidental complexity, but much of the time it is essential. It is very easy to use a generative model produce output. I don&amp;rsquo;t think it&amp;rsquo;s very easy to use them produce useful output.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Are the ACM's profits supporting its mission yet?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2025/10/03/are-the-acm-s-profits-supporting-its-mission-yet/" />
  <id>urn:https-www-williamjbowman-com:-blog-2025-10-03-are-the-acm-s-profits-supporting-its-mission-yet</id>
  <published>2025-10-03T22:08:18Z</published>
  <updated>2025-10-03T22:08:18Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Last year, as UBC got involved in ACM Open negotiations, I got curious about ACM financials. As I dug into them, I didn&amp;rsquo;t like what I saw, and wrote a &lt;a href="/blog/2023/12/14/a-high-level-summary-and-interpretation-of-acm-finances/"&gt;blog post&lt;/a&gt; and then a &lt;a href="https://doi.org/10.1145/3663958"&gt;CACM Opinion piece&lt;/a&gt;. The ACM honoured me with a &lt;a href="https://doi.org/10.1145/3673863"&gt;response article&lt;/a&gt;, which includes lots more data and a contrary perspective on the ACM&amp;rsquo;s $250,000,000 in assets and $10,000,000/yr in profit. The response also made an interesting claim:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;In terms of DL subscription revenue alone, the ACM is projecting a loss of $6M to $8M in 2026 when the DL goes fully open. The five-year projection is for a loss of $25M to $30M.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I was very interested in this claim. In making it, they have activated the trap card of falsifiability.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m quite happy that the ACM is moving to an open access model, and want that to be financially viable. But, as I said last year,&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;I do not think it is in the public or professional interest, nor does it advance art, science, engineering, and so on, to charge unnecessarily high publication and conference fees, taken out of public, research, and educational funding, and to hold that surplus income as an increasingly large pile of assets.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;So I was keen to pay attention to this claim about the need for that surplus, and its use in supporting ACM Open.&lt;/p&gt;

&lt;p&gt;Well I&amp;rsquo;ve got to reading the &lt;a href="https://dl.acm.org/doi/pdf/10.1145/3749885"&gt;new ACM 2023 and 2024 publication finance report&lt;/a&gt;, and the &lt;a href="https://projects.propublica.org/nonprofits/organizations/131921358/202531209349303908/full"&gt;new FY2023 IRS data&lt;/a&gt;, and attention I am paying. So&amp;hellip; is the ACM losing money in the switch to ACM Open, and is its hundreds of millions in profit over the past decades helping it achieve its mission?&lt;/p&gt;

&lt;p&gt;TLDR: Na. The ACM remains profitable and its net assets have continued to grow by tens of millions of dollars a year. And IMO, some of their rhetoric is even more worrying than that.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;First, some context.&lt;/p&gt;

&lt;p&gt;As in my prior article, I will rely heavily on the IRS 990 filings. Since my previous article, &lt;a href="https://projects.propublica.org/nonprofits/organizations/131921358/202531209349303908/full"&gt;FY2023 has become available&lt;/a&gt;. This data provides a good overview of the considerable income from all sources, such as conferences, gifts, ads, investments, and membership fees, and all expenses. However, the IRS reporting uses a different financial year and different categorization of income and expenses than the ACM uses internally.&lt;/p&gt;

&lt;p&gt;ACM have also recently published &lt;a href="https://dl.acm.org/doi/pdf/10.1145/3749885"&gt;the 2023 and 2024 finance report&lt;/a&gt;, which I will pull from. These data are incomplete: they only report the finances for the publishing arm of the business, sorry, enterprise, sorry, non-profit mission that is the ACM. However, it includes more fine-grained information than the IRS data.&lt;/p&gt;

&lt;p&gt;The differences between these two sources could result in apparent contradictions that are in fact totally benign. I won&amp;rsquo;t dwell on this. Both sources tell interesting stories, both separately, and together.&lt;/p&gt;

&lt;p&gt;Okay! Let&amp;rsquo;s look at income.&lt;/p&gt;

&lt;p&gt;Notable facts and figures about income from the ACM finance report:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;ACM DL subscriptions dropped from $11,500,000 to $3,900,000, representing a loss of revenue of about ($7,600,000). However, this is totally expected, since the ACM DL subscriptions are being phased out in favour of ACM Open.&lt;/li&gt;
 &lt;li&gt;ACM Open revenue climbed from $7,700,000 to $15,300,000, representing an increase in revenue of about&amp;hellip; $7,600,000. Fancy that.&lt;/li&gt;
 &lt;li&gt;In total, publication revenue increased $200,000 from 2023 to 2024, from about $25,000,000 to $25,200,000.&lt;/li&gt;
 &lt;li&gt;In total, revenue has increased about 1% per year from 2019&amp;mdash;2024.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;So, ACM Open doesn&amp;rsquo;t seem to be harming revenue much at all. And, as a result, science has become much more accessible! Well done ACM! That&amp;rsquo;s how you serve the public and member interests!&lt;/p&gt;

&lt;p&gt;Revenue growth at 1% seems problematic, since it&amp;rsquo;s below inflation, and below the increase in expenses. But, that&amp;rsquo;s partly by design: the ACM has frozen prices during the transition to ACM Open. So the fact that revenue is growing despite the transition to ACM Open cannibalizing other sources of revenue, providing free services to previously paying customers, and not increasing prices to keep up with inflation, suggests that actually ACM Open is&amp;hellip; overpriced?&lt;/p&gt;

&lt;p&gt;The finance report couches this in other term that I completely disagree with. They start with the claim that:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;it’s reasonable to ask why income growth has been so slow?&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;And go on to assure the reader that these restrictions on income growth are temporary and, not to fear, income will begin to grow again soon!&lt;/p&gt;

&lt;p&gt;But you know what: no, no it&amp;rsquo;s not reasonable to ask why income growth has been slow. That was the entire point of my original article. The mission of the ACM is not to grow income&amp;mdash;to make a profit&amp;mdash;but to serve the public and professional interest. The ACM should not be aiming to make a profit, and yet it&amp;rsquo;s clear that they both DO make a massive profit, and believe it is part of their mission to do so.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s zoom out and look at the IRS data. In FY2022, the ACM made $12,000,000 in profit, while in FY2023 they made $380,000 (which is an interesting outlier I&amp;rsquo;ll return to). Their total assets are up from to $211,500,000 to $264,000,000; I use total rather than net, because a major liability is deferred revenue, which is not a liability in the same way as other debts.&lt;/p&gt;

&lt;p&gt;So the ACM does not appear to be on track for a $25,000,000 to $30,000,000 loss, and is &lt;em&gt;still&lt;/em&gt; certainly not using their hoard to support its mission. ACM Open does not seem to be harming revenue, or profit much, even with its temporarily limited price increases.&lt;/p&gt;

&lt;p&gt;But.. what about that drop to $380,000 in profit, from an average of $11,000,000 per year for many years?&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at that more carefully. This drop seems to come from two places:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;Revenue, but importantly &lt;em&gt;not&lt;/em&gt; program service revenue (i.e., from ACM Open) fell a bit.&lt;/li&gt;
 &lt;li&gt;Expenses, but &lt;em&gt;not&lt;/em&gt; publication expenses, increased a lot.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;As we&amp;rsquo;ve seen, revenue from DL subscription and ACM Open balanced out. All program service revenue (which includes conferences, publications, memberships, and advertising) increased from $69,000,000 in FY2022 to $74,000,000; it&amp;rsquo;s way up. Membership fees and advertising revenue is down, a bit. Conference revenue is up, from $39,000,000 to $43,200,000, although so are conference expenses. Contributions, which includes gifts and grants, have remained essentially the same at $8,000,000 in FY2021, $10,000,000 in FY2022, and $8,000,000 in FY2023. Investment income is down a lot, but possibily due to an outlier in 2022. Between investment income and investment sales, it was about $7,000,000 in FY2021, $12,000,000 in FY2022, and only $5,000,000 in FY2023. So income is pretty stable, but down.&lt;/p&gt;

&lt;p&gt;Now expenses.&lt;/p&gt;

&lt;p&gt;Again, I&amp;rsquo;ll start with the publications finance report. The expenses section is weird, but I&amp;rsquo;ll start with the reported facts and figures.&lt;/p&gt;

&lt;p&gt;Notable facts and figures about expenses:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;In total, publication expenses &lt;em&gt;fell&lt;/em&gt; from $29,200,000 to $28,800,000 from 2023 to 2024, saving $400,000.&lt;/li&gt;
 &lt;li&gt;Digital library expenses, particularly infrastructure expenses, increased from $6,800,000 to $7,900,000, by about $1,100,000.&lt;/li&gt;
 &lt;li&gt;Anything related to print publication fell, enough to offset all that DL expense and then some.&lt;/li&gt;
 &lt;li&gt;In total, expenses rose about 4.4% per year from 2019 to 2024.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Notably, publication expenses are still greater than publication revenue. This has been the case for some time, but the profits from conferences offsets that difference. Recall the ACM is still reporting a profit, and a substantial growth in assets.&lt;/p&gt;

&lt;p&gt;The expenses also report some&amp;hellip; bizarre&amp;hellip; claims. The two claims are:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;overall expenses have continued to increase, with the most significant increase of 27.91% occurring between 2023 and 2024, when the program grew from 29,691 articles in 2023 to 37,978 articles in 2024.&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;
 &lt;p&gt;Over the longer period from 2019–2024, expenses grew at a rate of 13.66% per year.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;These claims are.. nonsense. The expenses clearly didn&amp;rsquo;t grow 27.91% from 2023 to 2024, and nor by 13.66% per year, which obviously contradicts the earlier (correct) claim that they grew by about 4.4% per year. I believe they&amp;rsquo;re meant to say that the &lt;em&gt;number of articles published&lt;/em&gt; increased by 27.91% from 2023 to 2024, and 13.66% per year. That at least matches the number of articles reported in the sentence. I can only assume the claims are typos. I&amp;rsquo;ve reached out to the director of publications, who has said my interpretation is likely correct and that they will fact-check this, but it has been some weeks and I want to finish writing this post.&lt;/p&gt;

&lt;p&gt;The IRS data on expenses basically supports the data in the finance report. A nontrivial amount of the increases was on DL expenses. This is reflected in the IRS data as &amp;ldquo;information technology&amp;rdquo; expenses, which are up to $7,000,000, from $5,700,000 in FY2022. Publication also does seem to be getting slightly more expensive. Publication production and services at up to $6,700,000, from $5,300,000. But, that is not nearly enough to make up for the $12,000,000 drop in profit.&lt;/p&gt;

&lt;p&gt;Conferences appear to be a big expense. Conference expenses are up to $41,700,000, from $36,700,000 But conference revenue has grown to match, and still subsidizes other parts of the business.&lt;/p&gt;

&lt;p&gt;Lots of little things went up: employee salaries, travel expenses, occupancy, amounts paid to independent contractors such as Conference Publishing. So, yeah expenses are going up, and without increasing revenue, and with a bad year for investments, the ACM didn&amp;rsquo;t make quite as much in profit as usual. (Although investments still appreciated by $10,000,000, that&amp;rsquo;s not counted as revenue since the gain hasn&amp;rsquo;t been realized yet.)&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s more interesting is to try to understand WHY these expenses are going up. Sure occupany, employee salaries, conferences&amp;mdash;those are a bit out of the ACM&amp;rsquo;s control. The ACM believes it can reduce publication expesnes:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;ACM had expenses of $28,854,059, and while we anticipate being able to reduce this figure over the next few years&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;So hopefully those are growing pains.&lt;/p&gt;

&lt;p&gt;But one place where expenses are increasing is very telling.&lt;/p&gt;

&lt;p&gt;In its own words, the ACM believes income growth is part of its mission, and is spending money to increase future revenue. A non-trivial amount of the increase in expenses is on the digital library, but not for anything that benefits the public or members interests: on product differentiation to grow profit.&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;ACM has invested heavily &amp;hellip; and embarked on a large-scale initiative to launch both Basic and Premium versions of the DL platform with robust features, functionality, and value-added content in 2026 [including] advanced search tools, such as AI assisted search; and research insights, such as usage metrics, citation trends, institutional and author profile pages, and altmetrics.&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;
 &lt;p&gt;For any researcher, student, practitioner, or educator working in this domain, access to the Premium version of the ACM Digital Library should be considered essential.&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;
 &lt;p&gt;ACM will work hard to identify new value-added products and services for the researcher, practitioner, and educator communities,&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This is absurd and insulting. We don&amp;rsquo;t need to spend money on AI assisted search, supporting an ethically dubious industry and bubble to get slop full of bullshit (in the technical sense) in our search engine, especially if we need to control costs. That approach has made search engines increasingly useless. We don&amp;rsquo;t need more stupid, useless metrics for bureaucrats to optimize at the expenses of real value. All of this is make work; all of this is bullshit jobs.&lt;/p&gt;

&lt;p&gt;Sure, ACM Open prices might need to go up over time to keep up with costs, maintain the digital library, etc. I understand the need to have a robust network infrastructure to serve all our papers and archive them indefinitely. But some these costs are self inflicted, and the ACM has openly declared a goal of profit seeking product development that has nothing to do with its mission.&lt;/p&gt;

&lt;p&gt;Sooo &amp;hellip; is the ACM losing money on ACM Open? No. Revenue loss from DL subscriptions are matched by ACM Open revenue increases. The ACM still appears to be extremely profitable overall. Unless things have gone completely off the rails since FY2023, the ACM is still profitable and now has a hoard of ~$280,000,000 (projected). If you consider publications in isolation, yes, ACM Open is losing money, but is more efficient than DL subscriptions&amp;mdash;it lost about ($3,600,000) in 2024, compared to a loss of ($4,200,000) in 2023. Personally, I think it&amp;rsquo;s a little disingenuinous to completely ignore conference revenue when considering publications; the profit from conferences almost entirely covers the loss on publications.&lt;/p&gt;

&lt;p&gt;Is the ACM spending down its hoard? Obviously not. It continues to grow, and at essentially the same pace as before.&lt;/p&gt;

&lt;p&gt;Is the ACM using its profit to support its mission? Well. I&amp;rsquo;ll give them one thing: with the price freeze in place despite increasing costs, the ACM has cut into its profit, &lt;em&gt;mostly&lt;/em&gt; to support its mission. But it also spent a huge chunk on for-profit behaviour, developing new nonsense products and setting an explicit goal of increasing profits. The ACM is profiting, and making it a goal to profit, at the expense of its members and/or the public it is meant to serve.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What's higher-order about so-called higher-order references?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2025/06/02/what-s-higher-order-about-so-called-higher-order-references/" />
  <id>urn:https-www-williamjbowman-com:-blog-2025-06-02-what-s-higher-order-about-so-called-higher-order-references</id>
  <published>2025-06-02T21:56:43Z</published>
  <updated>2025-06-02T21:56:43Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;A reviewer, in one of those off-hand little low-level comments they leave, which one is sometimes tempted to ignore as one works on a revision because they&amp;rsquo;re not &lt;em&gt;strictly&lt;/em&gt; actionable, has absolutely nerd-sniped me.&lt;/p&gt;

&lt;p&gt;What does &amp;ldquo;higher-order&amp;rdquo; in &amp;ldquo;higher-order references&amp;rdquo; mean? (References as in &lt;a href="https://doi.org/10.1145/362349.362364"&gt;Reynolds 1970&lt;/a&gt;.)&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;We appear to have inherited the phrase &amp;ldquo;higher-order&amp;rdquo; from higher-order logic, which it refers to the union of first-order logic, and second-order logic, and third-order logic, and so on. Here, &amp;ldquo;order&amp;rdquo; refers to what quantifiers can quantify over. For example, zeroth-order logic has no quantifiers. First-order logic can quantify individuals. Second-order logic can quantify over things that quantify over individuals (sets). &lt;em&gt;Etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So what is a higher-order function? Well, a function that can quantify over functions that can quantify over functions, &lt;em&gt;etc&lt;/em&gt;. Really, we could perhaps generalize to higher-order values to make a closer analogy to higher-order logic. A zeroth-order value cannot quantify over other values&amp;mdash;values such as naturals and booleans. These are sometimes called ground values. A function cannot be a zeroth-order value, since it quantifies over other values. A first-order value can quantify over zeroth-order values. A fairly restricted function would be a first-order value. A second-order value could quantify over values that quantify over values, so for example a function of type &lt;code&gt;(A -&amp;gt; B) -&amp;gt; C&lt;/code&gt;, where &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;C&lt;/code&gt; are ground values, would be second order.&lt;/p&gt;

&lt;p&gt;So far all this makes sense.&lt;/p&gt;

&lt;p&gt;What is a higher-order reference?&lt;/p&gt;

&lt;p&gt;Well&amp;hellip; that is a surprisingly complicated question.&lt;/p&gt;

&lt;p&gt;Of late, &amp;ldquo;higher-order reference&amp;rdquo; seems to mean &amp;ldquo;reference to a higher-order, effectful function&amp;rdquo;. The phrase appears in this sense at least as early as 1998 (&lt;a href="https://doi.org/10.1109/LICS.1998.705669"&gt;Abramsky &lt;em&gt;et al.&lt;/em&gt;&lt;/a&gt;), in which Abramsky &lt;em&gt;et al&lt;/em&gt;. use &amp;ldquo;higher-order reference&amp;rdquo; to refer to references that contain higher-order functions that can, when called, modify the heap. But this use of &amp;ldquo;higher-order&amp;rdquo; is at odds with most other uses of &amp;ldquo;higher-order&amp;rdquo;. It&amp;rsquo;s not used to mean that the reference merely quantifies over other references. Instead, it&amp;rsquo;s used to mean references that quantify over &lt;em&gt;higher-order, effectful functions&lt;/em&gt;, a different class of values. That is, this use of &amp;ldquo;higher-order&amp;rdquo; refers not to the order of the reference, but the order of the values the reference contains. If we were to use &amp;ldquo;higher-order reference&amp;rdquo; more consistently with &amp;ldquo;higher-order logic&amp;rdquo;, it should mean references to references to references &lt;em&gt;etc.&lt;/em&gt; to values.&lt;/p&gt;

&lt;p&gt;The phrase &amp;ldquo;general references&amp;rdquo; avoids the problem, but does not solve it. This phrase is often used, including by &lt;em&gt;op. cit.&lt;/em&gt;, to include other forms of higher quantification in references, such as cyclic references and references to existential types, &lt;em&gt;etc.&lt;/em&gt;, as well as references to higher-order, effectful functions. To quote:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;By general references we mean references which can store not only values of ground types (integers, booleans, etc.) but also those of higher types (procedures, higher-order functions, or references themselves).&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.cs.princeton.edu/techreports/2004/713.pdf"&gt;Ahmed (2004)&lt;/a&gt; uses similar phrasing:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;general references — that is, mutable cells that can hold values of any closed type including other references, functions, recursive types, and impredicative quantified types.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The emphasis is on their &lt;em&gt;generality&lt;/em&gt;, which distracts from a key semantic issues (higher-order, effectful functions &lt;em&gt;in particular&lt;/em&gt; are responsible for interesting semantics questions).&lt;/p&gt;

&lt;p&gt;The situation is worse if we look at the phrase &amp;ldquo;first-order references&amp;rdquo;, which also appears in &lt;a href="https://doi.org/10.1109/LICS.1998.705669"&gt;Abramsky &lt;em&gt;et al.&lt;/em&gt;&lt;/a&gt;. This appears to refer to references to ground values, &lt;em&gt;i.e.&lt;/em&gt;, references to zeroth-order values. So a first-order reference is indeed a first-order value, in that it quantifies over zeroth-order values. But that means &amp;ldquo;first-order&amp;rdquo; in &amp;ldquo;first-order reference&amp;rdquo; is used in a difference sense than &amp;ldquo;higher-order&amp;rdquo; in &amp;ldquo;higher-order references&amp;rdquo;: it refers to the order of quantification of the reference itself, and not to the order of the quantification of the contents of the reference.&lt;/p&gt;

&lt;p&gt;Even more frustratingly, it seems the phrase &amp;ldquo;higher-order reference&amp;rdquo; &lt;em&gt;used&lt;/em&gt; to use &amp;ldquo;higher-order&amp;rdquo; in the original sense. &lt;a href="https://doi.org/10.1007/3-540-08342-1_22"&gt;Janssen &lt;em&gt;et al.&lt;/em&gt; (1977)&lt;/a&gt; use &amp;ldquo;higher order reference&amp;rdquo; to refer to references that quantify over references! Readings over some of the related papers around that time, it seems the semantics of such references were quite interesting. It&amp;rsquo;s unclear to me when exactly the phrase took on the new sense of &amp;ldquo;higher-order&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;So how do I concisely, and pedantically, refer to those references that can contain higher-order (effectful) functions (but not necessarily other non-first-order values)? My student Sean Bocirnea proposed &amp;ldquo;higher-order value references&amp;rdquo; (HOVR; pronounced &amp;ldquo;hoover&amp;rdquo;). Perhaps we&amp;rsquo;d use &amp;ldquo;higher-order function reference&amp;rdquo; (HOFR; &amp;ldquo;hoofer&amp;rdquo;) to speak of those only required to contain higher-order functions. These are less verbose than any alterantive I&amp;rsquo;ve come up with, but have bad mouth-feel.&lt;/p&gt;

&lt;p&gt;Given the phrase has had a new sense for at least almost 30-years old at this point, I&amp;rsquo;m a a little reluctant to be inventing new phrases. Perhaps I should just leave it at this, with this note serving as a historical marker of this accident of language. But I&amp;rsquo;m also insufferably pedantic, and the phrase &lt;em&gt;does&lt;/em&gt; have two meanings, so perhaps I should create a new phrase.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Academic freedom, freedom of speech, and politics</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2025/04/10/academic-freedom-freedom-of-speech-and-politics/" />
  <id>urn:https-www-williamjbowman-com:-blog-2025-04-10-academic-freedom-freedom-of-speech-and-politics</id>
  <published>2025-04-10T17:19:10Z</published>
  <updated>2025-04-10T17:19:10Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Recently, there has been an attack on academic freedom and free speech at UBC, by fringe right-wing extremists, under the guise of protecting free speech. They recently escalated this attack from bullshit internal political wrangling (which I&amp;rsquo;ve been helping fight), to a BC Supreme Court Petition: &lt;a href="/resources/Petition-VLC-S-S-252602-filed-7Apr2025.pdf"&gt;Petition-VLC-S-S&amp;ndash;252602-filed&amp;ndash;7Apr2025.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m so tired. So angry. This is such bullshit.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s talk about academic freedom and freedom of speech.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;This whole petition is nonsense. It rests on the false claims that:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;UBC is forcing faculty to make take certain political positions.&lt;/li&gt;
 &lt;li&gt;UBC is requiring faculty to express certain political speech.&lt;/li&gt;
 &lt;li&gt;UBC is required to be apolitical, which it is not if it makes statements on political topics.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;All of this is nonsense.&lt;/p&gt;

&lt;p&gt;UBC is not limiting the speech of faculty, nor requiring faculty to make any speech and this attempt to ban speech under the guise of free speech and being apolitical is the same kind of attempt to destroy institutions that&amp;rsquo;s happening in the US. But, if you intentionally mislead people and conflate different categories, it could look like UBC is being political. So let&amp;rsquo;s deconstruct some categories.&lt;/p&gt;

&lt;p&gt;The petition conflates &amp;ldquo;UBC&amp;rdquo; and its administration with the faculty that make up the university, and conflates &amp;ldquo;speaking on topics related to politics&amp;rdquo; with &amp;ldquo;being political&amp;rdquo;. It is vital that UBC faculty maintain their academic freedom, including to speak on political topics. It is vital that UBC faculty be able to state facts about political topics; that is not being political.&lt;/p&gt;

&lt;p&gt;Unrestricted speaking on political topics is vital to academic freedom. All this petition does is try to limit faculty from one kind of speech, thereby benefiting one perspective (and faculty that have their perspective) over another. Merely stating facts is not political, even if those facts are related to politics. Even sharing expert analysis and opinion about political topics is not &amp;ldquo;being political&amp;rdquo;. The intention of a university being &amp;ldquo;apolitical&amp;rdquo; is for the university to serve the public, regardless of their political perspective, and for its faculty to be protected from political whims, regardless of their political perspective.&lt;/p&gt;

&lt;p&gt;What is the university and why do we think it needs to be apolitical?&lt;/p&gt;

&lt;p&gt;We faculty need to, need to be trusted to, provide expert analysis, opinion, and education, to everyone, equally&amp;mdash;regardless of political stance. The faculty need to be able to speak freely, even and especially on topics that are politically sensitive, to do that. That means they need protection from political whims in the exercise of their academic mission. That doesn&amp;rsquo;t mean not speaking about politics. It means exactly the opposite: enabling and protecting faculty and groups of faculty to speak about political topics.&lt;/p&gt;

&lt;p&gt;So being &amp;ldquo;apolitical&amp;rdquo; means to be protected to work on, for, and with anyone regardless of politics. It does not mean &amp;ldquo;not touching politics&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Consider a particular policy, say introducing a wealth tax. It&amp;rsquo;s critical that faculty be able to study, and argue the advantages and disadvantages of a wealth tax. Or, in the exercise of their expert opinion, to argue for a wealth tax as a good policy, or argue against it as a bad policy.&lt;/p&gt;

&lt;p&gt;Being &amp;ldquo;apolitical&amp;rdquo; does mean that UBC, as an institution, cannot unreasonably restrict the work of the faculty that make up UBC based on political considerations. We can&amp;rsquo;t have a university administrator telling faculty what to study or support a particular policy. We can&amp;rsquo;t have university say, as a whole, it is in support of such a policy, over the views of the individual faculty. We can&amp;rsquo;t have the university come out and say &amp;ldquo;We&amp;rsquo;re only providing expert opinions to the liberal party&amp;rdquo;. That would be &amp;ldquo;the university being political&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;But that is a straw man that just isn&amp;rsquo;t happening, and by attempting to restrict speech related to politics to prevent that straw man, you&amp;rsquo;re actually restricting the speech of individual faculty in the exercise of their academic mission.&lt;/p&gt;

&lt;p&gt;This petition is making the same mistake as the above strawman (I&amp;rsquo;d guess, intentionally).&lt;/p&gt;

&lt;p&gt;It is not political to state that &amp;ldquo;UBC exists on the unceded ancestral territory of the first nations&amp;rdquo;. That&amp;rsquo;s just a fact. It does.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;might&lt;/em&gt; be political for UBC to come out and say &amp;ldquo;and we should give it back&amp;rdquo;. Probably not all faculty agree with that, such as those putting forth this petition.&lt;/p&gt;

&lt;p&gt;However, any individual faculty &lt;em&gt;must&lt;/em&gt; be protected in saying &amp;ldquo;and we should give it back&amp;rdquo;, because they may want to make an academic, political, ethical, sociological, or economic argument about this topic, and conclude that this would be a good policy. Unfortunately, by the same token, individual faculty must also be protected if they want to make the argument that &amp;ldquo;and it&amp;rsquo;s super good that we killed a bunch of people and took their land&amp;rdquo;. That&amp;rsquo;s a pretty unpopular argument, and I think it would be hard to make, and while you probably shouldn&amp;rsquo;t lose your academic job if you&amp;rsquo;re making that argument academically, everyone is in their right to tell you you&amp;rsquo;re a bad person for making it.&lt;/p&gt;

&lt;p&gt;It is also not political to say &amp;ldquo;We condemn killing children, bombing hospitals, murdering journalists. This meets all the definitions of a genocide, and is bad&amp;rdquo;. It &lt;em&gt;might&lt;/em&gt; be political to for UBC, as an institution, to then suggest we should break off ties with Israel. But individual faculty must be protected in making that argument.  It would certainly be a restriction of academic freedom and free speech to say faculty cannot say that, or make that argument. Unfortunately, by the same token, individual faculty must be protected in making an academic argument that Israel is within it&amp;rsquo;s right to wage total war. Although, that would be a tough argument, given the clear violations of international law. And everyone would be well within their rights to tell you you&amp;rsquo;re a bad person for making such an argument.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m being a little extreme in the above examples; academic freedom isn&amp;rsquo;t that absolute. Governments can, and do, reasonably restrict faculty from certain kind of speech, and impose other reasonable limits on rights to limit harm. So maybe actually a faculty can&amp;rsquo;t go around arguing &amp;ldquo;genocide is good&amp;rdquo;, because they might incite people to violence and cause a lot of harm. But at least in principle, even distasteful arguments on political topics need to be protected, and at the very least it&amp;rsquo;s not the university&amp;rsquo;s role to restrict such rights, but a government&amp;rsquo;s role. But it would certainly be unreasonable to restrict faculty from making the argument that genocide is bad. What would be the harm; inciting people to stop doing genocide?&lt;/p&gt;

&lt;p&gt;Similarly, it might be that a government imposes a reasonable restriction to advance some good. If land acknowledgement statements were political, and I&amp;rsquo;m not convinced they are, they could be a reasonable restriction of speech in order to undo a harm or advance a common good. If this was a policy set by a government, I wouldn&amp;rsquo;t have much to say about it. I would still argue that a university shouldn&amp;rsquo;t set such a policy, and faculty should be protected if they want to argue against that policy (even as they are bound by it).&lt;/p&gt;

&lt;p&gt;This attempt to ban certain political speech at the university is a blatant attempt to &lt;em&gt;reduce academic freedom&lt;/em&gt; and &lt;em&gt;restrict free speech&lt;/em&gt;, and is itself &lt;em&gt;being political&lt;/em&gt;. By preventing faculty from expressing facts and opinions on political topics, you benefit exactly one side: the side currently in power that is being spoken out against. Doing that &lt;em&gt;is&lt;/em&gt; political; it makes a policy decision. It shifts political power. Exercising academic freedom to speak on political topics is different from &amp;ldquo;being political&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;If we had a policy that says &amp;ldquo;UBC can&amp;rsquo;t support Palestine&amp;rdquo;, does that mean the institution can&amp;rsquo;t, or are you restricting the individual faculty? Given that UBC, as an institution, isn&amp;rsquo;t doing this, this petition can only have the effect of restricting individual faculty. This petition &lt;em&gt;is political&lt;/em&gt;, and is trying to restrict academic freedom and free speech.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">The Structure and Interpretation of Computer Science Academic Metrics</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2025/04/02/the-structure-and-interpretation-of-computer-science-academic-metrics/" />
  <id>urn:https-www-williamjbowman-com:-blog-2025-04-02-the-structure-and-interpretation-of-computer-science-academic-metrics</id>
  <published>2025-04-02T20:39:11Z</published>
  <updated>2025-04-02T20:39:11Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I&amp;rsquo;ve been unhappy with metrics lately, watching academics (of all people) apply metrics without interpretation. I&amp;rsquo;m losing my mind over it.&lt;/p&gt;

&lt;p&gt;This was free written in one sitting don&amp;rsquo;t @ me.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="publication-count"&gt;Publication Count&lt;/h2&gt;

&lt;p&gt;This probably started when my department introduced a new policy explicitly measuring publication count. They wanted an objective, transparent metric of research productivity. They decided (well, some of them decided, and pushed through a policy against all department norms) that the metric of research productivity would be (drum roll please): publication count. At least 1 paper per year (ish) would be required.&lt;/p&gt;

&lt;p&gt;As if &amp;ldquo;1 paper per year&amp;rdquo; is a meaningful metric. As if &amp;ldquo;1 paper&amp;rdquo; is a thing that exists. We all know there is no consistent interpretation of &amp;ldquo;1 paper&amp;rdquo;. There was much discussion on this point. Everyone admitted that &amp;ldquo;1 paper&amp;rdquo; varies greatly from field to field. Some papers are smaller, some are large, some take many years to do the research, write, polish, and some are small results easily accepted in small venues. But surely, &amp;ldquo;1 paper&amp;rdquo; is the bare minimum anyone could possibly be expected to publish in any field. So the policy was codified.&lt;/p&gt;

&lt;p&gt;Publication count has long been a proxy for research productivity, and while it is objective and transparent, it&amp;rsquo;s also meaningless.&lt;/p&gt;

&lt;p&gt;Number of physical chairs in a department is also objective and transparent, and almost equally meaningless. Surely most chairs in a department are assigned to people doing research? They need a place to sit in order to do research. So as the number of physical chairs increase, the research productivity increases, because more researchers are sitting in chairs doing research. Sure, there are differences between chairs. Some are rolly chairs, some have lumbar support, some are mere stools. Some, of course, are assigned to admin staff, and really only indirectly support research productivity. It&amp;rsquo;s not a perfect metric, but it&amp;rsquo;s objective and transparent!&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m generally skeptical of metrics. &amp;ldquo;When a measure becomes a target, it ceases to be a good measure.&amp;rdquo; &amp;mdash; &lt;a href="https://en.wikipedia.org/wiki/Goodhart%27s_law"&gt;Goodhart&amp;rsquo;s Law&lt;/a&gt;. Merely the act of measuring changes peoples&amp;rsquo; actions. It provides an incentive to game the metric. You can use evolutionary game theory to show that introducing a metric as a fitness function will destroy any other variable, say, quality. If only the fittest survive, then anyone who better optimizes the fitness function wins and survives. When the fitness function is &amp;ldquo;number of publications&amp;rdquo;, and if this is not identical to &amp;ldquo;quality&amp;rdquo; (it&amp;rsquo;s not; it takes longer to polish a paper than to merely publish one), then trying to maintain &amp;ldquo;quality&amp;rdquo; is a losing strategy. Any rational actor seeking to survive will change their strategy, avoid &amp;ldquo;quality&amp;rdquo;, and optimize &amp;ldquo;quantity&amp;rdquo;. Any irrational actor, seeking to maintain &amp;ldquo;quality&amp;rdquo; over &amp;ldquo;quantity&amp;rdquo;, will lose and not survive.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;1 paper&amp;rdquo; is not a measure of research productivity. It is a measure of how many papers one has written, which is loosely correlated with, but not the same as, research productivity. It&amp;rsquo;s fairly easy to write papers which no research content. There are lots of venues that will accept a tutorial paper, or a neat idea paper, or controversial opinion, or a talk abstract. I&amp;rsquo;ve written some of these; it&amp;rsquo;s not bad to write them. But they&amp;rsquo;re not necessarily the same as research productivity. I would not equate my ACM Opinion article (a paper, with a DOI) with a POPL paper. That would be absurd. I wrote that as a blog post late one night after getting mad about ACM fees. Probably my &amp;ldquo;lowest tier&amp;rdquo; publication is a paper at Scheme Workshop. Scheme Workshop appears to be slowly dying, doesn&amp;rsquo;t have a formal proceedings (most of the time?), gets few submissions and the accept rate is almost 100%. But that paper involved a year of writing code, documenting, deploying to hundreds of users, testing, writing 24 pages of technical explanation, and preparing and delivering a 30 minute talk. That&amp;rsquo;s some research output. I&amp;rsquo;d have been smarter, more fit, to submit a neat little toy in Scheme that took no time to write about.&lt;/p&gt;

&lt;p&gt;How could academics, trained in studying and understanding data in minute details, so naively apply metrics this way? Don&amp;rsquo;t tell me; I know the answer. They wanted to make decisions more easily, and they found an objective, transparent metrics to do that.&lt;/p&gt;

&lt;h2 id="emery-bergers-ranking"&gt;Emery Berger&amp;rsquo;s Ranking&lt;/h2&gt;

&lt;p&gt;This is literally the reason &lt;a href="http://emerybergersrankings.org"&gt;http://emerybergersrankings.org&lt;/a&gt; was was created. To provide an objective, transparent metric to aid grad student in making decisions about which grad school to go to.&lt;/p&gt;

&lt;p&gt;I also hate Emery Berger&amp;rsquo;s Ranking. The goal is to provide &amp;ldquo;a metrics-based ranking of computer science institutions&amp;rdquo;. Ranking of what? Metric that measures what? It measures the output at a completely arbitrary list of conferences divided by author count per paper. What does that tell you? Why is is the school that is Number 1 in Arbitrary Conference Set Papers Divided By Author Count the &amp;ldquo;best&amp;rdquo; school? The one you want to spend ~6 years of your life studying at? At best, Emery Berger&amp;rsquo;s Ranking tells you that going to the most highly Ranked school will probably result in you producing some conference publications, likely with fewer coauthors than at other institutions? If that&amp;rsquo;s your goal, this is a great metric! Otherwise, it&amp;rsquo;s a bad metric. Honestly, US News and World report is a better metric for choosing a grad school, as it takes into account things like how nice the campus is, which greatly contributes to my happiness on a day-to-day basis.&lt;/p&gt;

&lt;p&gt;And even that much is an overstatement of what the metric measures, because it arbitrarily chooses a cut off for default inclusion into the metric of approximately 30% rejection rate. Why rejection rate of the conference is at all related to which is the best school is completely beyond me, but this means the ranking as actually the order on Number of Papers at Arbitrary Conferences with Below a 30% Rejection Rate Divided by Author Count.&lt;/p&gt;

&lt;p&gt;All of these things are proxies, loosely correlated with, but not the same as, quality. Rejection rate is a proxy for quality of a venue, since a highly prestigious venue (not the same as quality, but correlated) will attract more submissions. Since a conference can only accept so many talks, more submissions will be correlated with (but not the same as) a higher rejection rate. Author count is correlated with (but not the same as) a measure of effort per publication, since (in theory) more authors should reduce the effort involved in publishing a paper. Why this particular set of conferences? Well obviously those are &amp;ldquo;the very top conferences in each area&amp;rdquo;, according to Emery Berger&amp;rsquo;s judgement.&lt;/p&gt;

&lt;p&gt;So this metric measures SOMETHING, but it&amp;rsquo;s not what is the best CS grad school, or the most research productive CS department, or really, anything other than &amp;ldquo;Number of Papers at Arbitrary Conferences with Below a 30% Rejection Rate Divided by Author Count&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;But it is objective and transparent (at least, if you actually spend the time to interpret it and don&amp;rsquo;t just sort by it). And it does let people make decisions more easily. Not good decisions, but they sure are easy!&lt;/p&gt;

&lt;p&gt;We know for sure that Emery Berger&amp;rsquo;s Ranking has had exactly the effect predicted by behavioural game theory. We have examples of committees using it to judge quality of publication (note: it cannot measure that, see above interpretation). We have examples of people choosing venues not based on the best fit for the work, but to optimize the Emery Berger&amp;rsquo;s Ranking of their research. Of course they would; that&amp;rsquo;s the winning strategy when the fitness function uses the Emery Berger&amp;rsquo;s Ranking of a venue for promotion and tenure (see above).&lt;/p&gt;

&lt;h2 id="iclr-points"&gt;ICLR Points&lt;/h2&gt;

&lt;p&gt;Imagine my surprise when a new metric based on the same dataset underlying Emery Berger&amp;rsquo;s Ranking popped up, and after one look&amp;hellip; I LIKED IT.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cspubs.org"&gt;https://cspubs.org&lt;/a&gt; roughly measures the relative effort required to publish 1 paper in terms of ICLR papers. What is this, a metric that seeks to measure effort per publication count? That is actually a thing this data COULD measure. The data takes into account number of authors, which is pretty related to effort. More coauthors mean you can produce more research. It takes into account rejection rate, which is related to effort. More frequent rejections and resubmission require more effort. It takes into account area norms about how much work is required to get a paper at a particular venue, which is pretty much the definition of effort. Since it&amp;rsquo;s directly measuring effort, it&amp;rsquo;s not a measure that easily gamed: if you want to increase your ICLR points, then you, what, switch to publishing in venues that require more effort? That will almost certainly net you exactly the same number of ICLR points, since they measure effort.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s not a perfect metric. It&amp;rsquo;s not precise. Is the difference between 1 POPL paper and 1 OOPSLA paper 1.2 ICLR papers? Uh&amp;hellip; I dunno, not all OOPSLA papers are the same, not all POPL papers are the same, but maybe? But there is at least a difference in effort.&lt;/p&gt;

&lt;p&gt;And yet, I saw people complaining. &amp;ldquo;Why doesn&amp;rsquo;t cspubs like ICFP and OOPSLA&amp;rdquo;. That&amp;rsquo;s not what it says! It says ICFP and OOPSLA require less effort, which is probably true! They have a lower rejection rate, which decreases effort!! This is quite a good metric for that.&lt;/p&gt;

&lt;p&gt;Or maybe I&amp;rsquo;m just biased because it says PL papers requires the 2nd most effort out of any area in CS. Damn straight I put a lot of effort into my papers.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">A high-level summary and interpretation of ACM finances</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/12/14/a-high-level-summary-and-interpretation-of-acm-finances/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-12-14-a-high-level-summary-and-interpretation-of-acm-finances</id>
  <published>2023-12-14T20:06:46Z</published>
  <updated>2023-12-14T20:06:46Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I&amp;rsquo;m in the middle of liaising with the UBC library to attempt to negotiate joining ACM Open. It&amp;rsquo;s not going well. While US universities appear to see cost increases of 2x&amp;mdash;3x, Canadian universities are seeing costs of 10x&amp;mdash;20x. And our budgets run much tighter, and with far less research funding, particularly for article processing and other publication costs. A 10x&amp;mdash;20x increase in publication costs is hard or impossible to swallow.&lt;/p&gt;

&lt;p&gt;So, I&amp;rsquo;ve been forced to look at publishing&amp;mdash;where should I publish, how much will it cost, etc&amp;mdash;and one question I asked was: why does ACM Open cost so much? It&amp;rsquo;s a lot more than other open access journals. So I started looking at ACM finances and.. well&amp;hellip;&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s my dive into ACM finances, and questioning fundamental claims surrounding ACM publishing costs.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;UPDATE, March 1 2024&lt;/strong&gt; After discussions with other ACM members and feedback on this article, I&amp;rsquo;ve realized there are several errors in the analysis and the interpretation. I&amp;rsquo;ll publish an updated version eventually, but leave this version for transparency and as a record.&lt;/p&gt;

&lt;p&gt;In short, here are a list of &lt;em&gt;errors in the below facts and analysis&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;The data relied upon, FY 2022, is atypical due to including running conferences under COVID restritions. Conferences generally pay for themselves.&lt;/li&gt;
 &lt;li&gt;The $700 average cost of an article is justified by the Form 990s, despite the profit. This can be seen by cross-referencing the ACM publications finances report with the Form 990s, which is somewhat difficult to do because of the difference in categorizations and granularity of the different reports.&lt;/li&gt;
 &lt;li&gt;Eliminating membership fees would actually increase costs, since it would likely increase membership, and members receive various benefits which incur costs.&lt;/li&gt;
 &lt;li&gt;The ACM is probably not as bad as it seems at investing. The calculated return on investment appears to be atypical or artificially low. Further, for very good reasons, the ACM has a conservative investment strategy.&lt;/li&gt;
 &lt;li&gt;The assets, and income from assets, are at least partially restricted in various ways, both from donors (restricted or endowed funds), or because it is held for the SIGs, which limits how it could be spent down.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;However, I still stand by my high-level interpretation of the high profit and high assets of the ACM.&lt;/p&gt;

&lt;hr /&gt;
&lt;!-- more--&gt;

&lt;div id="invalid-watermark"&gt;Outdated, invalid information&lt;/div&gt;

&lt;h2 id="a-high-level-summary-of-acm-finances-from-an-objective-view-point"&gt;A high-level summary of ACM finances, from an objective view point&lt;/h2&gt;

&lt;p&gt;The ACM publishes annual reports in which it summarizes financial information such as its revenue and costs etc. The most recent is available here: &lt;a href="https://cacm.acm.org/magazines/2023/4/271230-acm-publications-finances-for-2021/fulltext"&gt;https://cacm.acm.org/magazines/2023/4/271230-acm-publications-finances-for&amp;ndash;2021/fulltext&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/sigchi/what-benefits-do-traditional-publishers-provide-83b7bd3fcbc0"&gt;Others have relied on this to infer where the $700 APC is spent&lt;/a&gt;, and I will argue about that later.&lt;/p&gt;

&lt;p&gt;But these reports are presented in the best possible light, to tell a story; they come from a very subjective view point. They&amp;rsquo;re also at a very low level, so I have a hard time making sense of them at first.&lt;/p&gt;

&lt;p&gt;The ACM is also required to file annual IRS disclosures to maintain their non-profit status, which are available with convenient summaries here:  &lt;a href="https://projects.propublica.org/nonprofits/organizations/131921358"&gt;https://projects.propublica.org/nonprofits/organizations/131921358&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These are incredibly boring pure figures, presented on PDFs of tables of rows of undigested data&amp;mdash;IRS tax documents. Interpreting them can be difficult, for multiple reasons&amp;mdash;tax accounting can be different from our intuitive classifications of things; can involve figures from the past and future, anticipated figures, and completely imaginary figures. However, they should be exact and objective.&lt;/p&gt;

&lt;p&gt;Here are some salient facts about that ACM&amp;rsquo;s finances, as reported to the IRS and the public in these filings, and as somewhat inexpertly summarized to a few significant digits by me:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;The ACM has been making, on average, ~$8,000,000 in annual &amp;ldquo;net income&amp;rdquo; for the past 10 years, and on average $10,000,000 in &amp;ldquo;net income&amp;rdquo; for the past 5 years.&lt;/li&gt;
 &lt;li&gt;The ACM currently has approximately $150,000,000 in investments, essentially all publicly traded securities.&lt;/li&gt;
 &lt;li&gt;From these investments, the ACM made approximately $3,000,000 in dividends and $3,000,000 in net gains&amp;mdash;an approximately 4.4% return on their investment.&lt;/li&gt;
 &lt;li&gt;The ACM is currently sitting on $25,000,000 in uninvested, non-interest bearing, cash. (I assume it&amp;rsquo;s filling a swimming poll in Times Square.)&lt;/li&gt;
 &lt;li&gt;The ACM spent ~$3,300,000 on &amp;ldquo;good works&amp;rdquo; related to its mission&amp;mdash;grants, student awards, travel awards, etc.  This does not include any expenses spent on operating the ACM, publishing, running conference, running the digital library, salaries, etc.&lt;/li&gt;
 &lt;li&gt;The ACM&amp;rsquo;s total revenue was $66,000,000, with a breakdown of the major sources below:
  &lt;ul&gt;
   &lt;li&gt;Publishing: $24,500,000&lt;/li&gt;
   &lt;li&gt;Conferences: $18,000,000&lt;/li&gt;
   &lt;li&gt;Membership fees: $7,500,000&lt;/li&gt;
   &lt;li&gt;Ads: $1,000,000&lt;/li&gt;
   &lt;li&gt;Investments: $6,500,000
    &lt;ul&gt;
     &lt;li&gt;Dividends: $3,300,000&lt;/li&gt;
     &lt;li&gt;Capital gains: $3,200,000&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
 &lt;li&gt;The ACM&amp;rsquo;s total expenses were $56,000,000, with a breakdown of major categories below.  There are quite a few other smaller categories, all of which are pretty reasonable.
  &lt;ul&gt;
   &lt;li&gt;Conferences: $20,000,000&lt;/li&gt;
   &lt;li&gt;Salaries (non-executies): $7,200,000&lt;/li&gt;
   &lt;li&gt;Publication production and services: $6,200,000&lt;/li&gt;
   &lt;li&gt;IT: $5,000,000&lt;/li&gt;
   &lt;li&gt;&amp;ldquo;Good works&amp;rdquo; (grants and awards etc): $3,300,000&lt;/li&gt;
   &lt;li&gt;Executives pay: $1,500,000&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;This summary of the IRS filing is easy to misunderstand. For example, the &amp;ldquo;conferences&amp;rdquo; category is probably the most difficult to understand from the IRS filings. Some of this could involve some publication costs, since publications are associated with conferences. The publication costs probably looks artificially low, since the IT category is probably almost entirely related to the digital library, which we would consider part of publication costs, but the IRS considers as a separate line item. Much of the salaries are related to staff for support publication, but salaries are considered separately.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Good works&amp;rdquo; is an ill-defined term that comes up in discussion about the ACM&amp;rsquo;s mission. In the IRS numbers, the things I&amp;rsquo;ve labeled &amp;ldquo;good works&amp;rdquo; are what the IRS calls grants. These are unambiguous expenditures of money by the ACM not on operating any business or service, but that it just gives away. However, note that running conferences, publishing, and maintaining the library &lt;em&gt;are&lt;/em&gt; part of the ACM mission.&lt;/p&gt;

&lt;h2 id="a-subjective-interpretation-of-the-high-level-acm-finances"&gt;A subjective interpretation of the high-level ACM finances&lt;/h2&gt;

&lt;h3 id="digital-library-subscriptions-and-apcs-are-the-main-source-of-revenue"&gt;Digital library subscriptions and APCs are the main source of revenue&lt;/h3&gt;

&lt;p&gt;The &amp;ldquo;publishing&amp;rdquo; revenue of $24,500,000 is the main source of revenue. We can ignore the conference revenue entirely. This is money that ACM collects ($18,000,000), and then immediately spends on conferences ($20,000,000). The ACM appear to marginally subsidize the cost of conferences, although this is deceptive given the membership fees and the possible misinterpretation of the conference expense category.&lt;/p&gt;

&lt;p&gt;Given that they are the main source of revenue, it&amp;rsquo;s pretty understandable why any change to the structure of that revenue greatly concerns that ACM. A significant change in publication revenue could bankrupt the ACM&amp;hellip;. although, it would take several years of literally $0 revenue, given the large pile of reserves the ACM is sitting on.&lt;/p&gt;

&lt;h3 id="the-acm-is-sitting-on-a-very-large-rainy-day-fund"&gt;The ACM is sitting on a very large rainy day fund&lt;/h3&gt;

&lt;p&gt;The ACM has $25,000,000 in cash and $150,000,000 in investments. Given annual expenses of $50,000,000, the ACM could afford to take in 0 revenue for 3 years, and still wouldn&amp;rsquo;t be bankrupt.&lt;/p&gt;

&lt;p&gt;This seems pretty excessive, but I&amp;rsquo;m not experienced enough as a financial analyst. The only point of comparison I could quickly find was arXiv, which in 2013 was aiming to cover half of their annual expenses in a rainy day fund: https://info.arxiv.org/about/reports/arXiv_Reserve_Funds_Policy.pdf.&lt;/p&gt;

&lt;p&gt;The investments are a little different than the cash, since they could take a while to sell off, you might sell them at a loss, and selling them cuts of a small bit of future revenue. But we&amp;rsquo;re talking about emergencies and unlikely events here.&lt;/p&gt;

&lt;h3 id="the-acm-is-very-profitable-particularly-for-a-non-profit"&gt;The ACM is very profitable, particularly for a non-profit&lt;/h3&gt;

&lt;p&gt;Normally, a for-profit business would call net income &amp;ldquo;profit&amp;rdquo;. The ACM is quite profitable, averaging $10,000,000 per year in profit. It&amp;rsquo;s not unusual or bad for a non-profit entity to have net income in a given year; it would be a very precarious entity that was constantly breaking even or running a deficit. But this long term trend of surplus is interesting, at least to me, a member, who is being charged various fees that form the revenue of the ACM.&lt;/p&gt;

&lt;p&gt;The purpose of a non-profit is not to make profit, but to achieve its mission, which according to Schedule O is:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt; TO ADVANCING THE ART, SCIENCE, ENGINEERING, AND APPLICATION OF INFORMATION TECHNOLOGY, SERVING BOTH PROFESSIONAL AND PUBLIC INTERESTS BY FOSTERING THE OPEN INTERCHANGE OF INFORMATION AND BY PROMOTING THE HIGHEST PROFESSIONAL AND ETHICAL STANDARDS.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I do not think it is in the public or professional interest to charge unnecessarily high fees, taken out of research and educational funding, and to hold onto that surplus income as an increasingly large pile of assets.&lt;/p&gt;

&lt;p&gt;The profit margin for the ACM is 15%. For context, Elsevier &lt;a href="https://www.theguardian.com/science/2023/may/07/too-greedy-mass-walkout-at-global-science-journal-over-unethical-fees"&gt;has profit margin of around 40%&lt;/a&gt;, while &lt;a href="https://group.springernature.com/gp/group/media/press-releases/springer-nature-releases-annual-progress-report/23572562"&gt;Springer has a adjusted operating margin (similar enough to profit margin for our purposes) of 26%&lt;/a&gt;. These two are notorious for-profit academic publishers, and should be considered outliers. They have absurdly large profit margins.&lt;/p&gt;

&lt;p&gt;For a better view, we could look at various related industries. Given that this is essentially entirely from publishing, I&amp;rsquo;ll compare this to publishing companies:  &lt;a href="https://ised-isde.canada.ca/app/ixb/fpd-dpf/report"&gt;https://ised-isde.canada.ca/app/ixb/fpd-dpf/report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From here, I generated the NAICS 513 - Publishing industries - Financial Performance Data, for year 2022, for companies with average revenue $5,000,000&amp;mdash;$20,000,000. The publishing industry profit margin range is &amp;ndash;8.8%&amp;mdash;17.5%.&lt;/p&gt;

&lt;p&gt;The ACM has a very high profit margin for the publishing industry.&lt;/p&gt;

&lt;h3 id="the-acm-is-not-spending-700-per-article"&gt;The ACM is not spending $700 per article&lt;/h3&gt;

&lt;p&gt;The ACM is not spending $700 per article to publish and maintain the library, no matter how we look at it.&lt;/p&gt;

&lt;p&gt;The easiest way to see this is to observe the approximately $10,000,000 in profit the ACM makes, on average, every year, which comes almost entirely from its publication licensing. The ACM could afford to cut the APC to $595, 85% of the APC, giving up its 15% profit margin, and benefiting its members at the same time.&lt;/p&gt;

&lt;p&gt;Arguably, it should not give up &lt;em&gt;all&lt;/em&gt; net income, as you want some saved for a rainy day. However, the ACM currently has as large rainy day fund.&lt;/p&gt;

&lt;h3 id="the-acm-funds-no-good-works-at-all"&gt;The ACM funds no good works at all&lt;/h3&gt;

&lt;p&gt;The ACM funds essentially no good works at all. 5% of the ACM&amp;rsquo;s costs go to good works, which represents a margin of error in costs. The good works the ACM funds represent the same amount of money, about 3 million dollars, as it makes in annual dividends from its investments. Arguably, nothing the ACM &lt;em&gt;does&lt;/em&gt;&amp;mdash;collecting revenue from publishing, membership fees, conferences, or donations&amp;mdash;funds the good works. It&amp;rsquo;s only the passive investment in publicly traded companies that fund the good works&amp;mdash;the profit from the ACM&amp;rsquo;s private capital funds good works.&lt;/p&gt;

&lt;h3 id="the-acm-doesnt-need-to-charge-membership-fees"&gt;The ACM doesn&amp;rsquo;t need to charge membership fees&lt;/h3&gt;

&lt;p&gt;The ACM could cut its membership fees to 0 tomorrow and still be running a $2,500,000 surplus. In fact, probably more, because it could reduce expenses in maintaining infrastructure to collect membership fees, accounting, etc.&lt;/p&gt;

&lt;h3 id="the-acm-seems-very-bad-at-investing"&gt;The ACM seems very bad at investing&lt;/h3&gt;

&lt;p&gt;The investment numbers can be very deceptive because its very easy, totally legal, and advisable to play various tax shenanigans with how investments are taxed, so the actual return may be higher.&lt;/p&gt;

&lt;p&gt;But, taken at face value, and considering the ~$500,000 in investment management fees, the ACM is extremely bad at investing their money. If they stuck it in a CD right now, they could in principle receive about 5% return for 0 fees. My personal investments currently return about 4.5% dividends and total return of 13%.&lt;/p&gt;

&lt;p&gt;If the ACM would like to hire me to manage their money, my rate is $499,000 per year, payable directly to my unrestricted account at UBC. Past performance is no indication of future success; investments may lose value; this does not constitute legal advice; please consult your doctor before starting any medication; etc.&lt;/p&gt;

&lt;h2 id="conclusions-what-should-i-do-with-this-information"&gt;Conclusions: What should I do with this information?&lt;/h2&gt;

&lt;p&gt;If you&amp;rsquo;re an ACM member, then there are several things you could call for, press for, attempt to change, etc.&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;A policy around limiting the net income, or at least directing the use of the net income, of the ACM could substantially reduce costs for members. This could be short-sighted: investing the net income does build an endowment and future income, could better reduce costs in the future. However, the ACM seems bad at investing, and tying the stability of the ACM to the stock market doesn&amp;rsquo;t seem any more stable than having a long-term balanced budget at lower costs.&lt;/li&gt;
 &lt;li&gt;A policy to spend down ACM assets. It&amp;rsquo;s reasonable to keep some cash in reserves, but it may be unreasonable to keep &lt;em&gt;that&lt;/em&gt; much cash invested. On the other hand, all universities have large endowments that are similarly managed, so maybe you don&amp;rsquo;t want to spend it down.&lt;/li&gt;
 &lt;li&gt;Eliminate membership fees. They represent 75% of the profit.&lt;/li&gt;
 &lt;li&gt;Eliminate conferences. Conferences are a major expense for the ACM, and apparently a net cost. Removing them could reduce the obvious costs, but also some of the non-obvious indirect costs, and enable reducing publishing costs.&lt;/li&gt;
 &lt;li&gt;Fund more good works. Maybe we&amp;rsquo;re fine with the costs, but we just want to spend that profit on good works. We could afford to triple them, and still be profitable.&lt;/li&gt;
 &lt;li&gt;Do nothing. Maybe things are fine the way they are.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;To draw any more conclusions, I think we&amp;rsquo;d need to dive into the low-level details of ACM&amp;rsquo;s budget, start comparing it to other publishers, other organizations, reconsidering the services we want the ACM to provide, etc. Some good, low-level information is available in the annual reports: &lt;a href="https://dl.acm.org/doi/pdf/10.1145/3389687"&gt;https://dl.acm.org/doi/pdf/10.1145/3389687&lt;/a&gt;. One bit that sticks out to me is the cost of copyediting, which is about $1,000,000, and I&amp;rsquo;d really pay for them to stop destroying my work.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Academia Is a For-Profit Industry</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/09/18/academia-is-a-for-profit-industry/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-09-18-academia-is-a-for-profit-industry</id>
  <published>2023-09-18T17:44:45Z</published>
  <updated>2023-09-18T17:44:45Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;An ill-advised blog post in which I speculate that academia is actually for-profit, but not in the usual sense of &amp;ldquo;profit&amp;rdquo;.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Profit is often narrowly construed as about money. It&amp;rsquo;s not; it&amp;rsquo;s about value, particularly surplus value. Money is a proxy for value, and often a useful one.&lt;/p&gt;

&lt;p&gt;In academia, however, money is not a good proxy for value. I&amp;rsquo;d argue the primary proxy for value is academia is paper and citation counts, although there are others. And by these measures, academia operates like a for-profit industry with many of the problems that entails: concentration of market power by accumulation of capital, the exploitation of labour, the externalizations of costs, all following the drive for ever higher surplus value. By disguising itself as non-profit, by eschewing money as value, academia disguises these issues.&lt;/p&gt;

&lt;p&gt;If paper and citation counts represent value, whence profit? To profit is not to merely produce things of value, but to seek to produce surplus value, and use the capture of that surplus value to incentive production. If papers represent value, then surplus value would represent papers and citation counts beyond what is required to produce the embodied knowledge. If academia were for-profit, we&amp;rsquo;d expect structural incentives to produce more and more papers and citations, and to produce them more efficiently (or at lower cost anyway). We&amp;rsquo;d expect to see that academic institutions measure success by increasing profit (i.e., papers and citations). That, for example, academics are hired and retained based on their ability to bring profit to the employing institution. We would expect capital to accumulate that makes increasing profit easier, so some groups accumulate profit that they can reinvest into increasing numbers of papers and publications.&lt;/p&gt;

&lt;p&gt;Some of these are easy to test; the others are testable with some straightforward data collection and analysis. I&amp;rsquo;m not going to do that now because (1) I&amp;rsquo;m bad at numbers (2) research is my job and no one is paying me for this.&lt;/p&gt;

&lt;p&gt;Academics and universities do judge their success, at least in part, by the number of papers and citations. See for example https://csrankings.org for one formalization of this; it&amp;rsquo;s like the Dow of CS universities. Or something. Researchers are hired and rewarded based on publication count and citations. These go into the hiring packets for new faculty and faculty up for tenure. Some contracts have specific publications counts you have to hit to make tenure. This is analogous to high-level management positions with profit targets; missing them could well get you fired.&lt;/p&gt;

&lt;p&gt;On it&amp;rsquo;s face, this isn&amp;rsquo;t necessarily a problem, and in some ways, is less problematic than a for-profit economy in general. At least papers represent knowledge, so we&amp;rsquo;re incentivizing the production of knowledge. The reasons I dwell are: (1) an incentive to optimize a proxy, a metric, is IMO bad; it leads to &lt;em&gt;perverse&lt;/em&gt; incentive, i.e., incentives to optimize merely the metric at the expense of the thing measured. This might not be a problem but for: (2) while papers represent knowledge-as-value, this value can be exchanged for monetary gain, so exploitation of the paper metric is profitable in the usual sense, and at the expense of knowledge.&lt;/p&gt;

&lt;p&gt;So, does the &amp;ldquo;profit&amp;rdquo; motive lead to exploitation? I&amp;rsquo;d say so, and in the same predictable ways as the usual profit motive. The easiest ways to increase production and decrease costs aren&amp;rsquo;t do hard work at making things more efficient, but to lie, cheat, and steal. We see these are work in academia. Made up data, plagiarized papers, etc. But let me zoom in on some higher level stuff.&lt;/p&gt;

&lt;p&gt;Exploitation of labour happens, at least until tenure. Grad students are often exploited and receive only a part of the value of their labour, although interesting I&amp;rsquo;d argue that by the measure of paper and citation count, less exploited than other industries. Grad students usually receive an equal share of the paper count and the citations. However, they might put in a disproportionate share of the labour required to produce a paper. I&amp;rsquo;ve heard of cases where students are cut out of a paper they worked on, or a supervisor puts almost no work in but receives a paper and citations. Very capitalist&amp;mdash;they provided the capital to produce the paper, even if they provide no labour, and receive a share of profit in return. Importantly, though, junior faculty (at least) are exploited as well. Here, it&amp;rsquo;s not by a direct superior, but indirectly by the institution, through a series of committees of &amp;ldquo;peers&amp;rdquo;. &amp;ldquo;Publish or perish&amp;rdquo; means they must produce value, papers, or be replaced by the many workers willing to step into the scarce high-demand faculty positions. Even highly respected workers who miss arbitrary targets are denied tenure, because they don&amp;rsquo;t produce enough profit. Exploitation of the individual worker only ceases if they get tenure, although systemic exploitation continues. In this view, I guess tenure is finally accumulating enough capital to become a capitalist, and live off the rents of capital accumulated? You never have to produce another paper again. Here, the exchange of &amp;ldquo;profit&amp;rdquo; for profit seems important.&lt;/p&gt;

&lt;p&gt;The analogy to capital accumulation holds as well. The more publications and citations you get, the easier it is to get more. To produce more and more citable papers requires grant funding, top graduate students, and post-docs. To get these, you need to have sufficient grant funding, and sufficient reputation and renown to attract top workers. In a typical for-profit industry, those with the most profit can afford to recruit the best talent, by paying more. In academia, though, salaries as in money are relatively fixed by institutions, not individual advisors (exceptions exist). Instead, academics compete largely on reputations&amp;mdash;who can train you to produce, and get you the most, high quality publications. That is, who can help you acquire the most capital-of-academia. Profit should also be translatable into capital, and this happens. Grants and awards look, in part, at publications and citations (and, ironically, other awards received) to decide who gets awards. These grants and award fund more papers and citations. Higher profits lead to the accumulation of capital, which leads to higher profits. Metrics like the H-index even ensure papers and citations depreciate, unless they generate ever higher citations over time.&lt;/p&gt;

&lt;p&gt;Costs of production get externalized. The most notable might be, as in many industries, greenhouse gasses. To produce papers and make them well known to gain citations often requires travelling, often internationally, often frequently. One other I worry about, although it&amp;rsquo;s unclear whether it&amp;rsquo;s a real problem, is the training of large numbers (I&amp;rsquo;d argue, unnecessarily large numbers) of PhDs. I&amp;rsquo;d argue we produce more than academia needs, except that we need them to produce research cheaply. In some places, there is pressure to increase the size of the PhD program. There&amp;rsquo;s a straightforward way to reduce these costs, and like in other industries, there&amp;rsquo;s no way in hell we&amp;rsquo;re doing it: produce less, or produce slower, or both. Of course, like in other industries, there&amp;rsquo;s reason. If we do stop producing sufficient profit (papers), people will lose their livelihood. Grad students may not get jobs if they don&amp;rsquo;t produce enough papers presented at international venues. Junior faculty may not get tenure.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t think any of this is a particularly novel observation, except the explicit analogy as profit. And even that I doubt.&lt;/p&gt;

&lt;p&gt;And the analogy isn&amp;rsquo;t perfect, and it&amp;rsquo;s complicated by the intersection with the money economy. That&amp;rsquo;s okay; no model is perfect, but some are useful. I think this for-profit model of academia is useful.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What is a model?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/06/15/what-is-a-model/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-06-15-what-is-a-model</id>
  <published>2023-06-15T20:25:25Z</published>
  <updated>2023-06-15T20:25:25Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;What is a model, particularly of a programming language? I&amp;rsquo;ve been struggling with this question a bit for some time. The word &amp;ldquo;model&amp;rdquo; is used a lot in my research area, and although I have successfully (by some metrics) read papers whose topic is models, used other peoples&amp;rsquo; research on models, built models, and trained others to do all of this, I don&amp;rsquo;t really understand what a model is.&lt;/p&gt;

&lt;p&gt;Before I get into a philosophical digression on what it even means to understand something, let&amp;rsquo;s ignore all that and try to discover what a model is from first principles.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="definitions-of-model"&gt;Definitions of &amp;ldquo;model&amp;rdquo;&lt;/h2&gt;

&lt;p&gt;The apparent place to start to understand the meaning of a word is to read its definition. This is actually no help at all. There are lots of uses of the word &amp;ldquo;model&amp;rdquo;, with several definitions. Here are some.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 0&lt;/strong&gt; In science and engineering, a model is &amp;ldquo;an abstract description of a concrete system using mathematical concepts and language&amp;rdquo;. See &lt;a href="https://en.wikipedia.org/wiki/Mathematical_model" title="Mathematical model"&gt;Wikipedia&lt;/a&gt; provides a nice introduction to this kind of model, and the &lt;a href="https://plato.stanford.edu/entries/model-theory/#Modelling" title="Models and Modelling"&gt;Standard Encylopedia of Philosophy&lt;/a&gt; provides a nice explanation in the context of model theory, which will be relevant later in this post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 1&lt;/strong&gt; A &lt;em&gt;syntactic model&lt;/em&gt; (of a type theory) is defined by &lt;a href="https://doi.org/10.1145/3018610.3018620" title="The Next 700 Syntactical Models of Type Theory"&gt;Boulier, Pédrot, and Tabareau&lt;/a&gt; as a translation from one type theory into another that preserves typing, the definition of false, and definitional equivalence. This syntactic model enables the source type theory to inherit properties of the target type theory&amp;mdash;such as consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 2&lt;/strong&gt; A &lt;em&gt;model&lt;/em&gt; (of a &lt;em&gt;vocabulary&lt;/em&gt; also called a &lt;em&gt;language&lt;/em&gt; \(\sigma\)) in the sense of model theory (as defined by &lt;a href="https://doi.org/10.1007/978-3-662-07003-1" title="Elements of Finite Model Theory"&gt;Elements of Finite Model Theory&lt;/a&gt;) is a &lt;em&gt;\(\sigma\)-structure&lt;/em&gt; (&amp;ldquo;also called a &lt;em&gt;model&lt;/em&gt;&amp;rdquo;) defining a set &lt;em&gt;A&lt;/em&gt; along with 3 sets providing interpretations of that vocabulary. These sets are \(Ic_A\), which interprets each constant in \(\sigma\) as an element of \(A\), \(IP_A\), which interprets each n-ary predicate symbol or relation symbol from \(\sigma\) as an n-ary (set-theoretic) relation between elements of \(A\), and \(If_A\), which interprets each n-ary function symbol in \(\sigma\) as a (set-theoretic) function from n elements of \(A\) to an element of \(A\).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 3&lt;/strong&gt; The above definition is confusing, since it conflates &lt;em&gt;structure&lt;/em&gt; and &lt;em&gt;model&lt;/em&gt;, which the text later distinguishes with the following separate definition. A &lt;em&gt;model&lt;/em&gt; (of a &lt;em&gt;theory&lt;/em&gt; (over a vocabulary \(\sigma\))) is a &lt;em&gt;structure&lt;/em&gt; (&amp;ldquo;also called a &lt;em&gt;model&lt;/em&gt;&amp;rdquo;) of &lt;em&gt;vocabulary&lt;/em&gt; \(\sigma\) such that every sentence in the theory is interpreted in the structure to make the sentence true. (A &lt;em&gt;theory&lt;/em&gt; is a set of sentences drawn from a vocabulary.) My rephrasing of the definition of model is intentionally confusing and difficult to parse, to make apparent the inherit confusingness created by the several layers of definitions and one definition that defines &amp;ldquo;model&amp;rdquo; using a second definition of &amp;ldquo;model&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 4&lt;/strong&gt; &lt;a href="https://ncatlab.org/nlab/show/structure+in+model+theory#Definition" title="Definition of 'structure' in model theory"&gt;Nlab hosts an article&lt;/a&gt; with a much clarified definition, which distinguishes &lt;em&gt;language&lt;/em&gt;, &lt;em&gt;theory&lt;/em&gt;, &lt;em&gt;structure&lt;/em&gt;, and &lt;em&gt;model&lt;/em&gt; carefully. In particular, it is careful to only call &lt;em&gt;structure&lt;/em&gt; the interpretation of the &lt;em&gt;language&lt;/em&gt; (call &lt;em&gt;vocabulary&lt;/em&gt; above), and only call &lt;em&gt;model&lt;/em&gt; an interpretation that makes true the &lt;em&gt;axioms&lt;/em&gt; composing the &lt;em&gt;theory&lt;/em&gt; of the &lt;em&gt;language&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 5&lt;/strong&gt; &lt;a href="https://twitter.com/carloangiuli/status/1640421574733078528?s=20"&gt;Carlo Anguli once gave me the following definition of model&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;A collection of interpretation functions that interpret every syntactic category in such that the original relationship is respected.&lt;/p&gt;
 &lt;p&gt;e.g., 
  &lt;br /&gt; - interpret every context as a set, 
  &lt;br /&gt; - interpret every (non-dependent) type as a set, and 
  &lt;br /&gt; - interpret every term-of-a-type indexed-by-a-context as an element-of-the-interpretation-of-that-type indexed-by-elements-of-the-interpretation-of-that-context.&lt;/p&gt;
 &lt;p&gt;Implicit in this definition is that the interpretations must respect equality &amp;mdash; because if you don&amp;rsquo;t respect equality of arguments then you&amp;rsquo;re not a function!&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This definition seems to be close to &lt;strong&gt;Definition 2&lt;/strong&gt;, as it doesn&amp;rsquo;t mention axioms and their interpretation. However, it might be &lt;strong&gt;Definition 3&lt;/strong&gt; instead, as there could be implicit in the definition of &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;syntax&lt;/a&gt; an inclusion of all judgements of the programming language, and therefore in the phrase &amp;ldquo;such that the original relationship is respected&amp;rdquo; a requirement that axioms of those judgements become true.&lt;/p&gt;

&lt;p&gt;Also implicit in this definition of model is what it is a model &lt;em&gt;of&lt;/em&gt;. Perhaps a programming language, but it again depends on what &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;syntax&lt;/a&gt; means and thus what &amp;ldquo;every syntactic category&amp;rdquo; refers to.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m interested in the requirement that the interpretation is a collection of &lt;em&gt;functions&lt;/em&gt;, which seems to be missing or only implied in some model theory definitions of &amp;ldquo;model&amp;rdquo;.&lt;/p&gt;

&lt;h2 id="so-what-is-a-model"&gt;So what &lt;em&gt;is&lt;/em&gt; a model?&lt;/h2&gt;

&lt;p&gt;One of the first thing that jumps out to me after reviewing the above definitions is that to understand each definition, you &lt;em&gt;have&lt;/em&gt; to reframe the definition of &lt;em&gt;model&lt;/em&gt; into &lt;em&gt;model [of what]&lt;/em&gt;. It really never makes sense to give a definition of merely &amp;ldquo;model&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 0&lt;/strong&gt; defines a &lt;em&gt;model of a system [of the real world]&lt;/em&gt;. &lt;strong&gt;Definition 1&lt;/strong&gt; defines a &lt;em&gt;model of a type theory&lt;/em&gt;. &lt;strong&gt;Definitions 2&lt;/strong&gt; and &lt;strong&gt;3&lt;/strong&gt; give definitions of a &lt;em&gt;model&lt;/em&gt;, in the sense of model theory, but of two different objects: &lt;em&gt;model of a vocabulary (or language)&lt;/em&gt;, which is more often called a structure, and &lt;em&gt;model of a theory&lt;/em&gt; (which everyone seems to agree is a &amp;ldquo;model&amp;rdquo;). &lt;strong&gt;Definition 4&lt;/strong&gt; makes this distinction very clear. &lt;strong&gt;Definition 5&lt;/strong&gt; seems to use &amp;ldquo;model&amp;rdquo; in the model-theoretic sense, but has abstracted a bit away from a particular notion of &lt;em&gt;theory&lt;/em&gt; and generalized to &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;&lt;em&gt;syntax&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="what-is-a-model-of-a-programming-language"&gt;What is a model &lt;em&gt;of&lt;/em&gt; a programming language?&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve had two problems understanding the word &amp;ldquo;model&amp;rdquo; in the context of programming languages.&lt;/p&gt;

&lt;p&gt;First, we use &amp;ldquo;model&amp;rdquo; in three different senses, and I have neither understood that nor understood the relationships between them.&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;Model in the sense of an abstract description of a system. This is &lt;strong&gt;Definition 0&lt;/strong&gt;. This sense of &amp;ldquo;model&amp;rdquo; means something like &amp;ldquo;mathematical description&amp;rdquo;. What we want is a description in which we can work using math, so we can make predictions about the real world. Ideally, the predictions we make will be true.&lt;/li&gt;
 &lt;li&gt;Model in the strict sense of model theory. These are &lt;strong&gt;Definitions 2, 3, and 4&lt;/strong&gt;. This sense of &amp;ldquo;model&amp;rdquo; is the closet to having a strict definition. It often carries a set-theoretic connotation, asking for a set defining the domain of values, and three interpretation functions that interpret specifics parts of a theory in specific ways.&lt;/li&gt;
 &lt;li&gt;Model in the generalized sense, inheriting from or related to model theory. I hesitate to even call this distinct from the second sense, but I will anyway. I also hesitate to speculate about history&amp;mdash;perhaps this sense actually predates model theory. But I distinguish it from the second sense, because it frequently generalizes away from the strict 3 category &amp;ldquo;constant symbol&amp;rdquo;, &amp;ldquo;predicate symbol&amp;rdquo;, &amp;ldquo;function symbol&amp;rdquo; specification and doesn&amp;rsquo;t seem beholden to set theory. &lt;strong&gt;Definitions 1 and 5&lt;/strong&gt; use &amp;ldquo;model&amp;rdquo; in this sense.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;In the second sense of &amp;ldquo;model&amp;rdquo;, the first sense of the word remains&amp;mdash;we&amp;rsquo;re still interested in a description of some system (the &lt;em&gt;theory&lt;/em&gt;), and of using the model to make predictions or reason. However, since the theory is also mathematical, we can be more rigid about our reasoning requirements&amp;mdash;axioms of the theory &lt;em&gt;must&lt;/em&gt; be true of the model, and relationships &lt;em&gt;must&lt;/em&gt; be preserved in the model. This is rarely true of a model of the real world; &lt;em&gt;e.g.&lt;/em&gt;, the Newtonian model of gravity works pretty well, until it doesn&amp;rsquo;t, so it&amp;rsquo;s a model that doesn&amp;rsquo;t &lt;em&gt;quite&lt;/em&gt; make all axioms true or preserve all relationships.&lt;/p&gt;

&lt;p&gt;The third sense seems closer to the idea of &lt;a href="https://en.wikipedia.org/wiki/Semantics_of_logic" title="Semantics of Logic"&gt;&lt;em&gt;semantics&lt;/em&gt;&lt;/a&gt;, in the mathematical logic sense of the word as assigning meaning or interpretation to &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;syntax&lt;/a&gt;. In this sense, the word &amp;ldquo;model&amp;rdquo; frequently avoid committing to set theory as a formal foundation, generalizes away from the three interpretation functions, and focuses instead on the &lt;em&gt;relationships&lt;/em&gt; between uninterpreted &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;syntax&lt;/a&gt; being preserved by the interpretation. For example, in &lt;strong&gt;Definition 1&lt;/strong&gt;, the relationships of interest are well-typedness, definitional equivalence, and falsehood, and the formal foundation is type theory. Category theory seems to come closest to a complete formalization of this sense of the word &amp;ldquo;model&amp;rdquo;, although I&amp;rsquo;ve had a hell of a time understanding that. Nlab articles don&amp;rsquo;t say this explicitly, but reading between the lines in articles linked to from &lt;a href="https://ncatlab.org/nlab/show/model+theory" title="Nlab Article on Model Theory"&gt;the Nlab article on model theory&lt;/a&gt; for the words &lt;a href="https://ncatlab.org/nlab/show/internal+language" title="Nlab Article linked from 'syntax'"&gt;syntax&lt;/a&gt; and &lt;a href="https://ncatlab.org/nlab/show/structure" title="Nlab Article linked from 'semantics'"&gt;semantics&lt;/a&gt; implies that the &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;idea of syntax&lt;/a&gt;, &lt;em&gt;i.e.&lt;/em&gt;, uninterpreted symbols with relationships between themselves and judgements about them, can be formalized in category theory, and then so can the idea of semantics, &lt;em&gt;i.e.&lt;/em&gt;, providing an interpretation in some other domain of those uninterpreted symbols; a domain in which one can use all the power of the other domain to reason about the judgements one wishes to make about the uninterpreted symbols.&lt;/p&gt;

&lt;p&gt;The second problem with the word &amp;ldquo;model&amp;rdquo; is that we frequently work with two senses simultaneously.&lt;/p&gt;

&lt;p&gt;When I write down a programming language, I&amp;rsquo;m often trying to &lt;em&gt;model&lt;/em&gt; (in the first sense) a real programming language (or some feature of it), one actual software developers use to make real things happen in the real world. I am not merely describing a mathematical object for study. (Okay, sometimes I do that, but usually to the first end, eventually.) When I write down such a model, I may describe the abstract syntax, the typing judgement, and an abstract machines or reduction rules. These form a pretty good mathematical description of how a real language behaves. A compiler will reject syntactically invalid expressions. It may then type check the abstract syntax tree, and reject some possibly semantically invalid expressions. If judged well typed, the compiler may transform the tree into something that runs, and that run-time behaviour can be predicted using the reduction rules.&lt;/p&gt;

&lt;p&gt;However, for much programming languages work, I&amp;rsquo;m not interested in merely predicting the behaviour of a single program. I might want to predict behaviour or properties of the entire language, or its typing judgement, etc. To reason about single programs, the &lt;em&gt;model&lt;/em&gt; (in the first sense) may work well. But it might not work well for, say, trying to decide whether certain types can even be inhabited. To solve this, we might build a &lt;em&gt;model&lt;/em&gt; (in the second or third sense). We interpret the abstract syntax tree and typing judgement in some other domain. That is, the AST and the typing judgement, being a &lt;em&gt;model&lt;/em&gt; in the first sense, form a &lt;em&gt;theory&lt;/em&gt; in the model theoretic sense. We can then construct a model (in the second sense) of a model (in the first sense). The Standard Encyclopedia of Philosophy &lt;a href="https://plato.stanford.edu/entries/model-theory/#Modelling" title="Models and Modelling"&gt;article on model theory&lt;/a&gt; goes into this in detail in the context of model theory, which is great.&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s more interesting is how these two senses of model interact in programming languages. If one is interested in a model, in the second sense, it may inform how one develops a model (in the first sense). If I know I will want to construct a model (in the second sense) to reason about the typing judgement, I may decide that single-step reduction rules are actually irrelevant; I only care that certain program equivalences hold, really, and any implementation that has those equivalences suffices. So rather than create a model (in the first sense) with an abstract machine or small-step operational semantics, I&amp;rsquo;ll specify an equivalence judgement. This might give less predictive power about a real world implementation, but allow the predictions I do make to apply to many implementations.&lt;/p&gt;

&lt;p&gt;If you see these patterns, you may have some insight into how the author is approaching their work, and in what senses they are using the word &amp;ldquo;model&amp;rdquo;.&lt;/p&gt;
&lt;!-- ## References--&gt;</content></entry>
 <entry>
  <title type="text">What is syntax?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-06-07-what-is-syntax</id>
  <published>2023-06-07T20:58:46Z</published>
  <updated>2023-06-07T20:58:46Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I&amp;rsquo;m in the middle of confronting my lack of knowledge about denotational semantics. One of the things that has confused me for so long about denotational semantics, which I didn&amp;rsquo;t even realize was confusing me, was the use of the word &amp;ldquo;syntax&amp;rdquo; (and, consequently, &amp;ldquo;semantics&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;For context, the contents of this note will be obvious to perhaps half of programming languages (PL) researchers. Perhaps half enter PL through math. That is not how I entered PL. I entered PL through software engineering. I was very interested in building beautiful software and systems; I still am. Until recently, I ran my own cloud infrastructure&amp;mdash;mail, calendars, reminders, contacts, file syncing, remote git syncing. I still run some of it. I run secondary spam filtering over university email for people in my department, because out department&amp;rsquo;s email system is garbage. I am &lt;em&gt;way&lt;/em&gt; better at building systems and writing software than math, but I&amp;rsquo;m interested in PL and logic and math nonetheless. Unfortunately, I lack lot of background and constantly struggle with a huge part, perhaps half, of PL research. The most advanced math course I took was Calculus 1. (well, I took a graduate recursion theory course too, but I think I passed that course because it was a grad course, not because I did well.)&lt;/p&gt;

&lt;p&gt;So when I hear &amp;ldquo;syntax&amp;rdquo;, I think &amp;ldquo;oh sure. I know what that is. It&amp;rsquo;s the grammar of a programming language. The string, or more often the tree structure, used to represent the program text.&amp;rdquo;. And that led me to misunderstand half of programming languages research.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="the-first-meaning-of-syntax"&gt;The First Meaning of Syntax&lt;/h2&gt;

&lt;p&gt;Syntax has two meanings in programming languages, and both meanings can frequently be found in the same paper.&lt;/p&gt;

&lt;p&gt;The first meaning is the one I gave above. I could give a definition of the syntax (in the first sense) of the lambda-calculus as follows.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;e ::= x | (lambda (x) e) | (e e)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ah. Beautiful syntax.&lt;/p&gt;

&lt;p&gt;If we were following a standard text, such as &lt;a href="http://www.cs.cmu.edu/~rwh/pfpl/2nded.pdf"&gt;Harper&amp;rsquo;s &lt;em&gt;Practical Foundation for Programming Languages (2nd ed)&lt;/em&gt;&lt;/a&gt;, we might next define the &amp;ldquo;semantics&amp;rdquo; of this &amp;ldquo;syntax&amp;rdquo;. We might define the &amp;ldquo;static semantics&amp;rdquo;, &lt;em&gt;i.e.&lt;/em&gt;, the type system or binding rules, then the &amp;ldquo;dynamic semantics&amp;rdquo;, &lt;em&gt;i.e.&lt;/em&gt;, the rules governing the evaluation behaviour of the syntax. For example, I might write the following small-step operational semantics.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;((lambda (x) e) e') -&amp;gt; e[x := e']&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ah. Beautiful semantics.&lt;/p&gt;

&lt;p&gt;Except, everything I wrote above, reduction rule included, is also &lt;em&gt;syntax&lt;/em&gt; and &lt;em&gt;not semantics&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id="historical-interlude"&gt;Historical Interlude&lt;/h2&gt;

&lt;p&gt;The words &amp;ldquo;syntax&amp;rdquo; and &amp;ldquo;semantics&amp;rdquo; come from mathematical logic.&lt;/p&gt;

&lt;p&gt;In that context, &amp;ldquo;syntax&amp;rdquo; describes sentences, statements, symbols, formulas, etc, without respect to any meaning. You can write down a logical formula say as "∀ X.P(X, A)" (where &amp;ldquo;A&amp;rdquo; is a logical constant, &amp;ldquo;X&amp;rdquo; is a variable, &amp;ldquo;P&amp;rdquo; is a proposition), and it has no meaning; it&amp;rsquo;s mere syntax. It might be true, or might be false, depending on its interpretation of &amp;ldquo;P&amp;rdquo;, &amp;ldquo;A&amp;rdquo;, and "∀". I could say that it means &amp;ldquo;all leaves are green&amp;rdquo;, which would be false. A more relevant example for PL might be the syntax &lt;code&gt;((lambda (x) x+1) 2) = 3&lt;/code&gt;, which I would certainly like to be true, but it very much depends on what I mean. If &lt;code&gt;+&lt;/code&gt; means string append as in JavaScript, then the statement is false since &lt;code&gt;''.concat(1, 2) = '12'&lt;/code&gt;. Wikipedia is a good start for trying to understand this history of the word &amp;ldquo;syntax&amp;rdquo;: &lt;a href="https://en.wikipedia.org/wiki/Syntax_(logic)"&gt;https://en.wikipedia.org/wiki/Syntax_(logic)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By contrast, in that same context, &amp;ldquo;semantics&amp;rdquo; is the means by which syntax is given an interpretation. Perhaps the most widely used approach to providing an interpretation of syntax is model theory, which I never learned. In model theory, we start with a &amp;ldquo;syntax&amp;rdquo; (or &amp;ldquo;theory&amp;rdquo;). This theory is a collection of constants, function symbols, and predicate symbols. A model then is a map from the uninterpreted syntax to some interpretation that preserves relationships. I&amp;rsquo;ll say more of this in a later post, but for now, consider the following example. I might provide a model of our earlier example that interprets &lt;code&gt;+&lt;/code&gt; as &lt;code&gt;''.concat&lt;/code&gt;, and &lt;code&gt;=&lt;/code&gt; is mapped to, say &lt;code&gt;===&lt;/code&gt;. This preserves relationships, if all my constants are mapped to strings. Wikipedia is a good source for this history too: &lt;a href="https://en.wikipedia.org/wiki/Semantics_of_logic"&gt;https://en.wikipedia.org/wiki/Semantics_of_logic&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="when-semantics-is-the-syntax"&gt;When Semantics is the Syntax&lt;/h2&gt;

&lt;p&gt;What&amp;rsquo;s interesting about this history is how it was adopted in programming languages, and evolved in two different ways. On the one hand, a programming language grammar is &lt;em&gt;syntax&lt;/em&gt;, in the sense of being uninterpreted statements. That syntax can be given a semantics, an interpretation, by using operation semantics (this is the sense in which operational semantics &lt;em&gt;is&lt;/em&gt; a semantics). The operational semantics provides an interpretation to our grammar.&lt;/p&gt;

&lt;p&gt;But, in another sense, the grammar, typing rules, and evaluation rules (the &amp;ldquo;syntax&amp;rdquo;, &amp;ldquo;static semantics&amp;rdquo;, and &amp;ldquo;dynamic semantics&amp;rdquo;) are mere syntax, in the older logical sense. They are a theory, in the model-theoretic sense. To see why, we must understand what the earlier example &lt;code&gt;((lambda (x) x+1) 2) = 3&lt;/code&gt; means. Or in fact, realize that it doesn&amp;rsquo;t mean anything at all.&lt;/p&gt;

&lt;p&gt;To write this down is to write down a proposition about the grammar: that one piece of the grammar is equal to another. Except I didn&amp;rsquo;t write a proposition that the two were equal. I wrote the uninterpreted proposition symbol &lt;code&gt;=&lt;/code&gt;, the syntax &lt;code&gt;=&lt;/code&gt;, next to two pieces of uninterpreted grammar, two other pieces of syntax. Every syntactic judgment about our grammar is itself syntax, in the model theoretic sense. At least, this is true if we follow the tradition of writing them down synthetically, axiomatically, about the grammar, as is done in standard programming languages textbooks such as &lt;a href="https://www.worldcat.org/search?q=bn:0262162091"&gt;&lt;em&gt;Types and Programming Languages&lt;/em&gt;&lt;/a&gt; or &lt;a href="http://www.cs.cmu.edu/~rwh/pfpl/2nded.pdf"&gt;&lt;em&gt;Practical Foundations for Programming Languages&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this view, the typing rules and reduction relations are syntax. This is a bizarre perspective from a software engineering perspective, but makes sense from the mathematical logic perspective.&lt;/p&gt;

&lt;p&gt;With this perspective, it might make sense to call &amp;ldquo;operational semantics&amp;rdquo; &amp;ldquo;syntactic semantics&amp;rdquo;, or to imagine a tower of syntax and semantics where one level&amp;rsquo;s semantics become the next level&amp;rsquo;s syntax. This view finally helped me make sense of why we call &amp;ldquo;syntactic logical relations&amp;rdquo; &lt;em&gt;syntactic&lt;/em&gt;, when they are clearly semantics. (A problem I danced around in &lt;a href="https://www.williamjbowman.com/blog/2023/03/24/what-is-logical-relations/"&gt;my previous post on logical relations&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;This perspective is also useful, for two reasons. The first is that reasoning purely syntactically, while very general, prevents you from importing any other reasoning principles from any other domain. By viewing the typing system as syntax, and then building a model of it (and by necessity, the programming language terms) in, say, set theory, we can import all set-theoretic reasoning in our attempts to reason about our type system. But more than that, we can reinterpret the syntax freely, to prove general results. While I might have written a type system using syntax that looks like numbers, I could build a model that interprets that type system as over strings, and know that actually the entire system is safe for strings, too. Appropriately generalized, I wouldn&amp;rsquo;t need to do any additional proofs.&lt;/p&gt;

&lt;p&gt;Unfortunately, this double meaning of the word syntax seems to be completely taken for granted by some. nLab is a good example of this. To quote from the introduction to the nLab model theory page:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;On the one hand, there is &lt;a href="https://ncatlab.org/nlab/show/internal+language"&gt;syntax&lt;/a&gt;. On the other hand, there is &lt;a href="https://ncatlab.org/nlab/show/structure"&gt;semantics&lt;/a&gt;. Model theory is (roughly) about the relations between the two: model theory studies classes of &lt;a href="https://ncatlab.org/nlab/show/models"&gt;models&lt;/a&gt; of &lt;a href="https://ncatlab.org/nlab/show/theories"&gt;theories&lt;/a&gt;, hence classes of “&lt;a href="https://ncatlab.org/nlab/show/structures+in+model+theory"&gt;mathematical structures&lt;/a&gt;”.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;What&amp;rsquo;s most interesting about this quote isn&amp;rsquo;t what it says, but what it links to. The link for &amp;ldquo;syntax&amp;rdquo; is to the page on the internal logic of a category. From the software perspective, this is not syntax, but semantics. How on earth could it be syntax? The link for &amp;ldquo;semantics&amp;rdquo; is to the page on structure, the idea of equipping a category with a particular functor. How on earth is that any more semantics than the original abstract nonsense version of syntax?&lt;/p&gt;

&lt;p&gt;Before I understood &amp;ldquo;syntax&amp;rdquo;, I couldn&amp;rsquo;t make any sense of that, but now I&amp;rsquo;m beginning to understand. The internal logic of a category in some sense must be able to express the grammar of a language, and the judgments of a language, but in a purely syntactic way&amp;mdash;in the same way that when I write down the grammar and typing rules of a language, I don&amp;rsquo;t refer to any interpretation of those symbols beyond the way I combine them on the page. Then the semantics or structure is a the particular functor over that category, providing an interpretation, a semantics, of that original category (the syntax).&lt;/p&gt;

&lt;p&gt;Anyway, now I think I&amp;rsquo;m ready to understand what a model is.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">In What Sense is WebAssembly Memory Safe?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/05/18/in-what-sense-is-webassembly-memory-safe/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-05-18-in-what-sense-is-webassembly-memory-safe</id>
  <published>2023-05-19T02:35:56Z</published>
  <updated>2023-05-19T02:35:56Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I&amp;rsquo;ve been trying to understand the semantics of memory in WebAssembly, and realized the &amp;ldquo;memory safety&amp;rdquo; doesn&amp;rsquo;t mean what I expect in WebAssembly.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="what-is-memory-safety"&gt;What is memory safety?&lt;/h2&gt;

&lt;p&gt;Here are some definitions.&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;Memory safety is a feature of programming languages that prevents certain types of memory-access bugs, such as out-of-bounds reads and writes, and use-after-free bugs. In an app that manages a list of to-do items, for example, an out-of-bounds read could involve accessing the nonexistent sixth item in a list of five, while a use-after-free bug could involve accessing one of the items on an already deleted to-do list.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt; &lt;a href="https://spectrum.ieee.org/memory-safe-programming-languages"&gt;https://spectrum.ieee.org/memory-safe-programming-languages&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;Memory safety is the state of being protected from various software bugs and security vulnerabilities when dealing with memory access, such as buffer overflows and dangling pointers. For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt; &lt;a href="https://en.wikipedia.org/wiki/Memory_safety"&gt;https://en.wikipedia.org/wiki/Memory_safety&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="memory-unsafety-in-wasm"&gt;Memory (un)safety in Wasm&lt;/h2&gt;

&lt;p&gt;WebAssembly (Wasm) is a &lt;em&gt;language&lt;/em&gt; that guarantees &amp;ldquo;type safety &amp;hellip; [preventing] invalid calls or illegal accesses to locals, &amp;hellip; memory safety, and &amp;hellip; inaccessibility of code addresses or the call stack&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;(Technically, the Wasm paper describes Wasm as a binary code format, that happens to be presented as a language.)&lt;/p&gt;

&lt;p&gt;Formally, a whole Wasm program that type checks is guaranteed to either be a well-typed value, or take an evaluation step to a well-typed program, or evaluate to the well-known dynamic error &amp;ldquo;trap&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;This is in contrast to an unsafe language like C. A well-typed C program might take a step to a well-typed program, or it might evaluate to a value of arbitrary type or no type. For example, a well-typed program of type &lt;code&gt;char&lt;/code&gt; that reads from a buffer might evaluate to a well-typed &lt;code&gt;char&lt;/code&gt;, or it might evaluate to an arbitrary integer that does not correspond to any character because you were reading uninitialized memory.&lt;/p&gt;

&lt;p&gt;For example, consider the following C program.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// unsafe.c
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main(int argc, char** argv) {
  char* buf = malloc(0);
  memcpy(buf, "Hello world\n", 12);
  write(1, buf, 12);
  return 0;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(compiled with &lt;code&gt;clang -o unsafe.exe unsafe.c&lt;/code&gt;; run with &lt;code&gt;./unsafe.exe&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;This program creates a buffer of size &lt;code&gt;0&lt;/code&gt;, writes &amp;ldquo;Hello world\n&amp;rdquo; to it, and tries to print that to standard out. The program printed &amp;ldquo;Hello world&amp;rdquo; when I ran it, but it&amp;rsquo;s undefined behaviour, so anything could happen. I tried to writing a loop that &lt;code&gt;malloc&lt;/code&gt;d lots of memory and wrote arbitrary numbers, but never managed to crash the program. Still, it&amp;rsquo;s not memory safe.&lt;/p&gt;

&lt;p&gt;The equivalent Wasm program is below.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;;; safe.wat
(module
 (import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))

 (memory 0)
 ;;(memory 1)
 (export "memory" (memory 0))

 (data (i32.const 0) "Hello World\n")

 (func $main (export "_start")
       (i32.store (i32.const 12) (i32.const 0))
       (i32.store (i32.const 16) (i32.const 12))
       (call $fd_write (i32.const 1) (i32.const 12) (i32.const 1) (i32.const 20))
       drop))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(run with &lt;code&gt;wasmtime safe.wat&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;In this example, we create a string &amp;ldquo;Hello World\n&amp;rdquo; at address 0 in the module&amp;rsquo;s memory. We then create (encode) a new &lt;code&gt;iovs&lt;/code&gt; just after it, starting as address &lt;code&gt;12&lt;/code&gt;, with a pointer to address &lt;code&gt;0&lt;/code&gt; and length &lt;code&gt;12&lt;/code&gt;. Then we call &lt;code&gt;fd_write&lt;/code&gt;, from the wasi API.&lt;/p&gt;

&lt;p&gt;Unfortunately, we declared the memory size to be &lt;code&gt;0&lt;/code&gt;, so trying to allocate this string fails, traps safely, and the process exits with an error message.&lt;/p&gt;

&lt;p&gt;So wasm is memory safe right?&lt;/p&gt;

&lt;p&gt;Well, sort of, but there&amp;rsquo;s a pretty key distinction here.&lt;/p&gt;

&lt;p&gt;In C, we are creating a new pointer with &lt;code&gt;malloc&lt;/code&gt;. We are allocating a new data structure, then using it (unsafely).&lt;/p&gt;

&lt;p&gt;In Wasm, there is exactly one memory for the entire module. Inside that memory, we encode 2 data structures: our string, and the &lt;code&gt;iovs&lt;/code&gt; structure used by &lt;code&gt;fd_write&lt;/code&gt;. All access to the global memory are safe. But not all accesses to the encoded data structures are.&lt;/p&gt;

&lt;p&gt;Most application will create data structure within the memory. That&amp;rsquo;s what our call to &lt;code&gt;fd_write&lt;/code&gt; did. The two &lt;code&gt;store&lt;/code&gt;s actually create an &lt;code&gt;iovs&lt;/code&gt; structure in the global memory. We have no guarantees, within Wasm, about that data structure.&lt;/p&gt;

&lt;p&gt;For example, here&amp;rsquo;s our Hello World program in Wasm which uses the &lt;code&gt;memory&lt;/code&gt; safely and correctly, but creates an &lt;code&gt;iovs&lt;/code&gt; whose length is claimed to be 100, larger than the actual string.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;;; unsafe.wat
(module
 (import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))

 (memory 1)
 (export "memory" (memory 0))

 (data (i32.const 0) "Hello World\n")

 (func $main (export "_start")
       (i32.store (i32.const 12) (i32.const 0))
       (i32.store (i32.const 16) (i32.const 100))
       (call $fd_write (i32.const 1) (i32.const 12) (i32.const 1) (i32.const 20))
       drop))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(run with &lt;code&gt;wastime unsafe.wat&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;When I run this, I get &amp;ldquo;Hello world\nd&amp;rdquo; printed to stdout. I have no idea where that trailing &lt;code&gt;d&lt;/code&gt; comes from, and it didn&amp;rsquo;t crash, suggesting it read uninitialized memory of some kind.&lt;/p&gt;

&lt;p&gt;Arguable, this is cheating: Wasm does not and cannot make claims about external system functions, and &lt;code&gt;wasi&lt;/code&gt; is unstable. But IMO the root of the error isn&amp;rsquo;t really about &lt;code&gt;wasi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Really, the root cause of this error is memory unsafety, but of a data structure encoded within a Wasm module. In a truly memory-safe language, if I try to access the 100th element of a 12-character long string, I get an error:&lt;/p&gt;

&lt;div class="brush: sh"&gt;
 &lt;pre&gt;&lt;code&gt;&amp;gt; racket
Welcome to Racket v8.9 [cs].
&amp;gt; (string-ref "Hello world\n" 100)
; string-ref: index is out of range
;   index: 100
;   valid range: [0, 11]
;   string: "Hello world\n"
; [,bt for context]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But that doesn&amp;rsquo;t happen in Wasm.&lt;/p&gt;

&lt;p&gt;Wasm memory safety doesn&amp;rsquo;t apply to &lt;em&gt;data structures&lt;/em&gt; implemented (encoded) within the &lt;code&gt;memory&lt;/code&gt;. It only applies to the module&amp;rsquo;s &lt;code&gt;memory&lt;/code&gt;, which is protected from other modules, even those running in the same process&amp;rsquo;s virtual address space.&lt;/p&gt;

&lt;p&gt;This means Wasm modules are protected from each other, and so this kind of memory unsafety probably isn&amp;rsquo;t a security risk, only a cause of logic bugs.&lt;/p&gt;

&lt;p&gt;In Wasm, data structures have to be encoded anyway, since Wasm doesn&amp;rsquo;t provide any kind of structure data primitives; you only have integers and some integers are interpreted as addresses into &lt;code&gt;memory&lt;/code&gt;. But, when you encode such data structures in the &lt;code&gt;memory&lt;/code&gt; and use them incorrectly, you have no guarantees about what happens. You could read some arbitrary data (from your own module), or read some uninitialized memory (from your own module). I.e., you get out-of-bounds reads and writes.&lt;/p&gt;

&lt;p&gt;In another view of this, &lt;code&gt;memory&lt;/code&gt; is the only data structure in Wasm, and it is memory safe. That&amp;rsquo;s all the language can be responsible for; if you go about encoding weird things inside that data structure, errors are likely. But this doesn&amp;rsquo;t seem like what people would expect when they hear &amp;ldquo;memory safe&amp;rdquo;. At least, it&amp;rsquo;s not what I expected at first.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What is logical relations?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/03/24/what-is-logical-relations/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-03-24-what-is-logical-relations</id>
  <published>2023-03-24T23:32:03Z</published>
  <updated>2023-03-24T23:32:03Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I have long struggled to understand what a logical relation is. This may come as a surprise, since I have used logical relations a bunch in my research, apparently successfully. I am not afraid to admit that despite that success, I didn&amp;rsquo;t really know what I was doing&amp;mdash;I&amp;rsquo;m just good at pattern recognition and replication. I&amp;rsquo;m basically a machine learning algorithm.&lt;/p&gt;

&lt;p&gt;So I finally decided to dive deep and figure it out: what is a logical relation?&lt;/p&gt;

&lt;p&gt;As with my previous note on realizability, this is a copy of my personal notebook on the subject, which is NOT AUTHORITATIVE, but maybe it will help you.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Here&amp;rsquo;s my working definition of a logical relation:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;A realizability semantic model,&lt;/li&gt;
 &lt;li&gt;built of predicates over syntax,&lt;/li&gt;
 &lt;li&gt;that &lt;em&gt;reflects&lt;/em&gt; judgments and structures from semantics to syntax.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Point 1 is subtle; it implies that the logical relation is both a model, and a &lt;a href="/blog/2022/10/05/what-is-realizability/"&gt;realizability semantics&lt;/a&gt;. Unfortunately, I still don&amp;rsquo;t know what a model is, so I&amp;rsquo;m going to have work with the following probably wrong oversimplification: the logical relation must take (syntactically) equal terms to (semantically) equal terms. Which notion of syntactic equality though? I&amp;rsquo;m not sure, and I&amp;rsquo;m going to ignore it for now.&lt;/p&gt;

&lt;p&gt;Point 2 is actually more specific than necessary. We don&amp;rsquo;t need to predicates over syntax specifically, but really over some base model. It&amp;rsquo;s easier for me to think of this as &amp;ldquo;syntax&amp;rdquo;, though.&lt;/p&gt;

&lt;p&gt;Point 3 is quite difficult to make precise without making a lot of this more precise in a mathematical framework. Jon Sterling gave me the following helpful definition:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;A logical relation on a model M (viewed as a category) is then a model that is constructed in the following way:&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;
   &lt;p&gt;Choose some functor R : M &amp;mdash;&amp;gt; E where E is a sufficiently structured category (e.g. the category of sets, or something else!). The most basic example of a functor R is the &amp;ldquo;global sections functor&amp;rdquo; M &amp;mdash;&amp;gt; Set, which sends every type in M to the set of &lt;em&gt;closed elements&lt;/em&gt; of that type. This is exactly the usual “non-Kripke logical relations"; to get Kripke logical relations, you replace Set with a functor category (presheaf category) and choose a more interesting functor R.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;Now define a new category G, as a category whose objects are pairs of an object A of M, together with a subobject of R(A). A morphism in G from (A,A’) to (B, B&amp;rsquo;) is given by a morphism (f : A -&amp;gt; B) that sends elements satisfying A&amp;rsquo; to elements satisfying B&amp;rsquo;.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;You have to show that the category G is actually a model of your language (e.g. show that it has function spaces, booleans, whatever). Doing so is the FTLR.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;
 &lt;p&gt;Note that there are some ways to generalize the situation above, but this is basically what logical relations are.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Point 3 is also is more specific than necessary; &amp;ldquo;syntax&amp;rdquo; can be generalized to be &amp;ldquo;base model&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Despite the complexity, we can see point 3 in action in some examples below.&lt;/p&gt;
&lt;!-- https://types.pl/@wilbowma/110079663033785019--&gt;

&lt;h2 id="what-are-logical-relations-historically"&gt;What are logical relations, historically?&lt;/h2&gt;

&lt;h3 id="tait1967---intensional-interpretations-of-functionals-of-finite-type-i"&gt;tait1967 - Intensional interpretations of functionals of finite type I&lt;/h3&gt;

&lt;p&gt;Logical relations are sometimes called &amp;ldquo;Tait&amp;rsquo;s Method&amp;rdquo;, dating back to &lt;a href="https://doi.org/10.2307/2271658"&gt;Tait&lt;/a&gt;, as far as I can tell.&lt;/p&gt;

&lt;p&gt;In this paper, Tait proves that System T with bar induction is a conservative extension of intuitionistic analysis U_1, which is intuitionistic arithmetic plus quantification over functions plus the axiom (schema) of choice plus bar induction. This conservative extension property is the semantic property of interest. The proof starts with a proof that T without bar induction is a conservative extension of just intuitionistic arithmetic (no choice or bar induction).&lt;/p&gt;

&lt;p&gt;To do this, Tait develops a type-indexed predicate over System T terms (without bar induction), providing a U_0 term for all T terms of each type. These predicates M_t, C_t, and E_t are (I think) what we refer to as a logical relation. In particular, the C_t relation provides the interpretation of T values of type t, M_t seems to deal with variables, and E_t seems to be a binary relation defining semantics (&amp;ldquo;weak α-definitional equality&amp;rdquo;) of terms.&lt;/p&gt;

&lt;p&gt;Theorem V (page 205) uses this logical relation to prove that, for all semantics values at the same type, (weak α-) definitional equality is decidable: they either are or are not related in E_t. This seems to be the key point: the definitional equality is reflected out of the semantics of terms, so it can apply to the syntax of terms.&lt;/p&gt;

&lt;p&gt;This use of logical relation seems to also be a realizability semantics, since it it assigns syntactic types to a collection of semantics terms, by induction over syntactic types, where the realizers are a subset of all possible semantics terms.&lt;/p&gt;

&lt;p&gt;However, it seems to be more than a realizability semantics, too. What seems very important in this paper is that the semantics preserves structure, namely definitional equality. Perhaps implicitly though, other pieces are important. For example, T functions are interpreted as U functions, although it&amp;rsquo;s not clear to me that this is critical.&lt;/p&gt;

&lt;p&gt;This is in contrast to Kleene&amp;rsquo;s (kleene1945) realizability, which did not seem concerned with structure, but only the existence of the realizers.&lt;/p&gt;

&lt;h3 id="plotkin1973---lambda-definability-and-logical-relations"&gt;plotkin1973 - Lambda-definability and logical relations&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.cl.cam.ac.uk/~nk480/plotkin-logical-relations.pdf"&gt;Plotkin&lt;/a&gt; seems to be responsible for the name, and perhaps rediscovering logical relations in the context of programming languages.&lt;/p&gt;

&lt;p&gt;Plotkin helpfully gives us a definition of &amp;ldquo;logical&amp;rdquo;, as well, and it seems quite importantly related to part 3 of my working definition. Plotkin defines a relation R as logical if it is:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;a subset of any D_k from the carrier any D∞ model (this seems to correspond  to &amp;ldquo;admissible relations&amp;rdquo; in modern logical relations parlance);&lt;/li&gt;
 &lt;li&gt;the relation is preserved by functions in D. That is, the relation holds on a  function f in D_k iff for all arguments x, R(x) implies R (f x)  (extended to the n-ary case for n-ary relations).&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;This suggests that it is important the logical relation is somehow interpreting syntactic structures as semantic structures, as in the case of Tait&amp;rsquo;s model interpreting syntactic functions as semantic functions. More generally, we likely want this property of all structures in the languages: syntactic pairs are interpreted as semantic pairs, etc. Jon&amp;rsquo;s category theoretical definition seems to generalize Plotkin&amp;rsquo;s definition nicely.&lt;/p&gt;

&lt;p&gt;This denotational logical relation also shows us a logical relation that is not defined over syntax. Instead, it is a relation over some arbitrary non-trivial D∞ model. The author mentions that since they can interpret syntax in a D∞ model, they informally treat the logical relation as over syntax sometimes, which I suppose could be made formal easily enough.&lt;/p&gt;

&lt;h2 id="how-is-logical-relations-used-in-pl"&gt;How is &amp;ldquo;logical relations&amp;rdquo; used in PL?&lt;/h2&gt;

&lt;h3 id="ahmed2006---step-indexed-syntactic-logical-relations-for-recursive-and-quantified-types"&gt;ahmed2006 - Step-Indexed Syntactic Logical Relations for Recursive and Quantified Types&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://doi.org/10.1007/11693024_6"&gt;In this paper&lt;/a&gt;, Ahmed is concerned with &lt;em&gt;syntactic&lt;/em&gt; logical relations for recursive and quantified types, in particular for reasoning about contextual equivalence. Likely due to Ahmed&amp;rsquo;s work, this kind of syntactic logical relation seems to be what most people mean or think when they say &amp;ldquo;logical relation&amp;rdquo;, although that may be changing.&lt;/p&gt;

&lt;p&gt;The desired property of the logical relation then is that two related semantic terms should be contextually equivalent in the syntax. That is, the logical relation reflects (from semantics to syntax) equivalence.&lt;/p&gt;

&lt;p&gt;Strangely (for a realizability model), this particular syntactic logical relation also reflects typing: semantic terms in the relation are also guaranteed to be well-typed in the syntax. In contrast, some uses of &amp;ldquo;logical relations&amp;rdquo; enable semantics terms to be syntactically ill-typed. Such logical relations might be better called realizability models, although they do something reflect some structure, so perhaps reflecting typability is not a critical point of reflecting structure.&lt;/p&gt;

&lt;p&gt;Ahmed in the introduction points out an interesting distinction: that logical relations can be either denotational, or syntactic. Syntactic logical relations model syntax as sets of syntactic values such that some property holds over that syntax. By contrast, denotational logical relations model syntax as some denotational object,  Syntactic logical relations are useful for proving properties of the operational semantics directly. Denotational models instead model syntax as denotational objects, such as, &lt;em&gt;e.g.&lt;/em&gt;, sets of set-theoretic functions over elements of a D∞ model in plotkin1973. This is useful for easily proving meta-theoretical properties by reflecting properties of the denotation into the syntax, but not necessarily about the operational semantics directly.&lt;/p&gt;

&lt;p&gt;For example, Tait uses a &amp;ldquo;denotational logical relation&amp;rdquo; into intuitionistic analysis to prove that definitional equality of System T is decidable&amp;mdash;the definition of definitional equality, in the model, and its proof of decidability, are reflected back into the syntax; this requires no operational semantics at all. Plotkin uses a denotational logical relation, into domain theory, to show that certain λ-calculus constructs are or are not definable&amp;mdash;existence of a term in the logical relation is reflected into the syntax as a definable expression. Neither of these is a syntactic logical relation; the semantic values never mention syntactic values directly.&lt;/p&gt;

&lt;p&gt;Ahmed uses a &amp;ldquo;syntactic logical relation&amp;rdquo; to prove something about the operational semantics, namely, to prove contextual equivalence (an operational notion), indirectly. Direct proofs of contextual equivalence are difficult. So instead, a semantic proof of equivalence is reflected back into the syntax as ta proof of contextual equivalence. This requires structuring the logical relation into a denotation of sets of syntactic terms that evaluate in the operational semantics, so that being in the relation tells us something about evaluation in the operational semantics, which tells us something about contextual equivalence.&lt;/p&gt;

&lt;h3 id="abel2018---decidability-of-conversion-for-type-theory-in-type-theory"&gt;abel2018 - Decidability of conversion for type theory in type theory&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://doi.org/10.1145/3158111"&gt;Abel &lt;em&gt;et al.&lt;/em&gt;&lt;/a&gt; define a syntactic logical relation for typed, reducible (and equivalent) terms, to prove decidability of conversion for type theory. Here, the use of syntactic logical relation is important for proving a particular conversion algorithm over the syntax is decidable.&lt;/p&gt;

&lt;p&gt;The interesting feature of this logical relation is the generalization from a model inductively defined over types, to inductively defined over judgments. This demonstrates a weakness in my working definition of logical relation and realizability, since I defined &amp;ldquo;realizability&amp;rdquo; in terms of models inductively defined over types.&lt;/p&gt;

&lt;h3 id="timany2022---a-logical-approach-to-type-soundness"&gt;timany2022 - A Logical Approach to Type Soundness&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://iris-project.org/pdfs/2022-submitted-logical-type-soundness.pdf"&gt;This paper&lt;/a&gt; is interesting because it uses a syntactic logical relation that intentionally does not reflect typing, as many syntactic logical relations cdo. Semantically valid terms are not necessarily syntactically valid. In other ways, it looks very much like a logical relation: syntactic pairs are semantic pairs, sums sums, functions functions, etc.&lt;/p&gt;

&lt;p&gt;The key property this paper is interested in is type safety: all well-typed terms are well-defined in the operational semantics, i.e., they evaluate to values or well-defined errors or fail to terminate, but importantly, do not get stuck. &amp;ldquo;in &lt;em&gt;the&lt;/em&gt; operational semantics&amp;rdquo; is important to understanding why this is a syntactic logical relation; it must model terms as sets of syntactic values to reason about the operational semantics given in the paper.&lt;/p&gt;

&lt;p&gt;However, one could imagine proving a slightly different form of type safety with a denotational logical relation. Giving a logical relation into an arbitrary model with a well-defined notion of evaluation would be implicitly a proof of type safety: that &lt;em&gt;there exists&lt;/em&gt; a model that is type safe. The ability to reflect from semantics to syntax provides a mechanism for constructing that evaluation over syntax. So while the denotational logical relation provides no direct proof about the operational semantics, it may provide a mechanism for a type-safe-by-construction operational semantics. (This reflecting evaluation out of the semantics seems very related to the idea of normalization-by-evaluation, but I&amp;rsquo;m not clear on this.)&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What is realizability?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2022/10/05/what-is-realizability/" />
  <id>urn:https-www-williamjbowman-com:-blog-2022-10-05-what-is-realizability</id>
  <published>2022-10-05T21:54:39Z</published>
  <updated>2022-10-05T21:54:39Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I recently decided to confront the fact that I didn&amp;rsquo;t know what &amp;ldquo;realizability&amp;rdquo; meant. I see it in programming languages papers from time to time, and could see little rhyme or reason to how it was used. Any time I tried to look it up, I got some nonsense about constructive mathematics and Heyting arithmetic, which I also knew nothing about, and gave up.&lt;/p&gt;

&lt;p&gt;This blog post is basically a copy of my personal notebook on the subject, which is NOT AUTHORITATIVE, but maybe it will help you.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;My best understanding of realizability right now, in programming languages (PL) terms, is:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;A technique for assigning each &lt;em&gt;syntactic type&lt;/em&gt; to a collection of &lt;em&gt;semantic terms&lt;/em&gt;;&lt;/li&gt;
 &lt;li&gt;By &lt;em&gt;induction&lt;/em&gt; over syntactic types;&lt;/li&gt;
 &lt;li&gt;Where the semantic terms that are &lt;em&gt;realizers&lt;/em&gt;&amp;mdash;i.e., included in the collection related to some syntactic type&amp;mdash;are a sub-collection of all possible terms in the semantic domain. That is, there are valid semantic terms not associated with any syntactic type.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;I use the word &amp;ldquo;collection&amp;rdquo; rather than &amp;ldquo;set&amp;rdquo; to avoid invoking set theory.&lt;/p&gt;

&lt;p&gt;Graphically, we can represent this as follows:&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/img/realizability.png" alt="" title="Realizability" /&gt;
 &lt;p class="caption"&gt;&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;The point of the technique is that clause 2 gives us a proof technique by induction, and clause 3 means we can relate the collection of terms (or proofs) to some other well-known collection. This yields a proof technique for metatheoretic properties about the collection, such as that there are only terminating terms in the collection of realizers, or there are only recursive functions and therefore some classical things remain unprovable.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not entirely sure that clause 2, induction, is necessary, and I can&amp;rsquo;t find anything explicit about clause 3, but they seem to be true historically and in many uses of the term.&lt;/p&gt;

&lt;p&gt;Okay so how did I get to this understanding?&lt;/p&gt;

&lt;h2 id="what-is-realizability-historically"&gt;What is realizability, historically?&lt;/h2&gt;

&lt;h3 id="kleene1945---on-the-interpretation-of-intuitionistic-number-theory"&gt;kleene1945 - On the Interpretation of Intuitionistic Number Theory&lt;/h3&gt;

&lt;p&gt;Realizability seems to come from Kleene&amp;rsquo;s paper &lt;a href="https://doi.org/10.2307/2269016"&gt;&amp;ldquo;On the Interpretation of Intuitionistic Number Theory&amp;rdquo;&lt;/a&gt;. I say &amp;ldquo;seems to&amp;rdquo; as Kleene attributes the &amp;ldquo;detailed investigation of the notion of realizability&amp;rdquo; to David Nelson, attributes several of the results in the paper to Nelson, and claims that the main results of the paper are joint work with Nelson. But the paper only has Kleene&amp;rsquo;s name on it, and Kleene claims in the first footnote that they introduced the idea of realizability to Nelson in a seminar. So anyway, realizability seems to come from Kleene, and this is the canonical paper cited for the technique.&lt;/p&gt;

&lt;p&gt;In this paper, realizability is quite specific. It&amp;rsquo;s a technique that takes an intuitionistic first-order logic formula about Peano arithmetic (Heyting arithmetic) and constructs a natural number from it, representing the (constructive) proof of that formula. Only provable formulas are realized. The point of this exercise is to prove various metatheorems about the realized language: is it consistent, and what are provable/unprovable in the intuitionistic formulae.&lt;/p&gt;

&lt;p&gt;Intuitively, something is unprovable if there exists a formula, but there does not exist a realization of it. This can be shown by connecting the formula to the set of realizers (in this case, natural numbers), but showing that there cannot exist a related natural number (or, more often, function on natural numbers represented by its Gödel number) with the properties required of the realizability interpretation. The simplest example: since &amp;ldquo;false&amp;rdquo; is unprovable (it has no realization, by construction), the intuitionistic logic is consistent.&lt;/p&gt;

&lt;p&gt;This also lets us prove something about the class of all provable statements. Since we have a method for constructing something from any provable (or true) statement, we can say something about the set of all provable statement in relation to the realizers. Kleene mentions one consequence is that the intuitionistic calculus cannot prove the existance of any function other than a general recursive function, since those are the only functions constructed in the realizability interpretation. This tells us, for example, that the intuitionistic calculus is different from classical set theory, which contains other functions.&lt;/p&gt;

&lt;p&gt;An important detail in this paper that clarifies the distinction between the intuitionistic and the classical happens in Clause 6, on page 113. This is the definition of the realizability interpretation for existential quantification ∃x.A(x). This has a realization if, for some &lt;strong&gt;x&lt;/strong&gt;, A(&lt;strong&gt;x&lt;/strong&gt;) has a realization. It&amp;rsquo;s important to notice that this second &amp;ldquo;for some &lt;strong&gt;x&lt;/strong&gt;&amp;rdquo; quantification happens in the metalanguage, namely, classical set theory, and therefore could be choosen by Choice. Kleene discusses this on page 118, where he uses the word &amp;ldquo;classically&amp;rdquo; as a modifier on various quantifiers to remind us that, when working with the quantification and realizers directly, we are working in a classical system in which intuitionistic proofs also exist.&lt;/p&gt;

&lt;p&gt;What seems to be going on here is that the realizers are something like the intuitionistic subset of classical set theory. I think that statement isn&amp;rsquo;t exactly true; Kleene uses classical choice when working with the realizers to show there are unprovable theorems. For example, a realizer parameterized over (classically) &lt;em&gt;all&lt;/em&gt; variables may not correspond to an intuitionistic formula. So it&amp;rsquo;s not that the realizers are only intuitionistic, I think. But any particular realizer is (must be)? The important point may be the realizers are a subset of the whole system, and thus we can prove interesting metatheorems that rely on distinguishing the realizers (and therefore, the formulae they realizer) from all the things in the full system.&lt;/p&gt;

&lt;h3 id="amadio1998---domains-and-lambda-calculi-chapter-15"&gt;amadio1998 - Domains and Lambda-Calculi, Chapter 15&lt;/h3&gt;

&lt;p&gt;Chapter 15 of Amadio and Currien&amp;rsquo;s book &lt;a href="https://doi.org/10.1017/cbo9780511983504"&gt;&amp;ldquo;Domains and Lambda-Calculus&amp;rdquo;&lt;/a&gt; introduces realizability in its historical context. The introduction formalizes Kleene&amp;rsquo;s work as an example, and discusses its use.&lt;/p&gt;

&lt;p&gt;They emphasize two things, which seem to confirm some of my understanding:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;The realizability relation is defined inductively over &lt;em&gt;formulas&lt;/em&gt;, and relates &lt;em&gt;formulas&lt;/em&gt; to &lt;em&gt;proofs&lt;/em&gt;.&lt;/li&gt;
 &lt;li&gt;The use lets us reason about all &lt;em&gt;proofs&lt;/em&gt; in the system.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;This is the best definition of realizability I&amp;rsquo;ve seen, and applies both to Kleene&amp;rsquo;s original, but also to uses in PL.&lt;/p&gt;

&lt;p&gt;The authors point out that Kleene&amp;rsquo;s original goal was to prove consistency. They then confirm my above intuitions, that the realizability interpretation also lets us prove metatheorems about what is provable/unprovable in the realized system. However, they note that one application of this is to find &lt;em&gt;unprovable&lt;/em&gt; &lt;em&gt;true&lt;/em&gt; statements, which can be consistently axiomatized back into the original system. There are proofs in the set of realizers, i.e., true statements, that are never constructed by the realizability interpretation. These could be added back to the original system to enrich it.&lt;/p&gt;

&lt;p&gt;This latter use seems to confirm one feature of realizability that isn&amp;rsquo;t explicit stated anywhere, but seems to be true of all realizability interpretations I&amp;rsquo;ve seen: that the realizers are a strict subsystem of some larger formal system.&lt;/p&gt;

&lt;h2 id="how-is-realizability-used-in-pl"&gt;How is &amp;ldquo;realizability&amp;rdquo; used in PL?&lt;/h2&gt;

&lt;p&gt;In programming languages, we&amp;rsquo;re not often concerned with intuitionistic vs classical logic; we&amp;rsquo;re working constructively by default. In fact, many of the uses of &amp;ldquo;realizability&amp;rdquo; in PL don&amp;rsquo;t seem to be related to logic at all, but to modeling well-typed programs. And while, sure, these are related by Curry-Howard, the difference seems important to me. So what does realizability mean in this context?&lt;/p&gt;

&lt;p&gt;In most uses in PL, the important feature seems to be clause 3 in my definition above: the collection of all values is larger than the set of realizers. In PL, this suggests that we&amp;rsquo;re ascribing types to &amp;ldquo;untyped&amp;rdquo; terms, and the realizers are those that are semantically well typed, but not necessarily syntactically well typed. The full collection contains also untyped terms, and we can therefore prove through realizability that the type system rules out ill-typed terms.&lt;/p&gt;

&lt;p&gt;There do seem to be some examples in PL that are explicitly relating classical and intuitionistic ideas, namely those trying to import constructive interpretations of classic logic. I&amp;rsquo;m not really interested in those, and I think the connection to realizability is much more clear in those applications, so I&amp;rsquo;ll ignore that area.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at some examples.&lt;/p&gt;

&lt;h2 id="benton2010---realizability-and-compositional-compiler-correctness-for-a-polymorphic-language"&gt;benton2010 - Realizability and Compositional Compiler Correctness for a Polymorphic Language&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://nickbenton.name/cccmsrtr.pdf"&gt;&amp;ldquo;Realizability and Compositional Compiler Correctness for a Polymorphic Language&amp;rdquo;&lt;/a&gt;, Benton and Hur define a &amp;ldquo;realizability&amp;rdquo; interpretation of System F types realized by terms in low-level language, for proving some compiler correctness properties. The terms realize the types, and this lets us talk about which low-level programs are valid to link with, without restricting the set of linkable programs to only those generated by the compiler.&lt;/p&gt;

&lt;p&gt;This has lost all connection to intuitionistic vs classical logic, but I suppose it keeps the key features of the technique: types (formula) of one language are realized by terms in another, and there is some concern that the realizers should be a subset of all terms. Not all low-level programs should be valid, but some set of them should be.&lt;/p&gt;

&lt;h2 id="nakano2000---a-modality-for-recursion"&gt;nakano2000 - A Modality for Recursion&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doi.org/10.1109/LICS.2000.855774"&gt;&amp;ldquo;A Modality for Recursion&amp;rdquo;&lt;/a&gt; was actually the start of my realizability journey. This paper starts by defining a collection of models (β-models) of the untyped λ-calculus. It then defines the class of realizability models, in terms of β-models, for an extrinsically typed λ-calculus with equi-recursive types. A realizability model is parameterized by a β-model, and is a relation inductively defined over types to their realizers, which are values drawn from the β-model.&lt;/p&gt;

&lt;p&gt;So why is this realizability? Well, I don&amp;rsquo;t see anything to do with intuitionistic vs classical. But, the set of all values is larger than the set of realizers, which seems to be important to all uses of &amp;ldquo;realizability&amp;rdquo;, and important for this result in particular. In this paper, this is used to show that the dot modality rules out some valid β-model terms, namely those that would correspond to non-terminating λ terms.&lt;/p&gt;

&lt;p&gt;Later in the paper, they define a &amp;ldquo;realizability interpretation&amp;rdquo;. This seems to be distinct from the collection of all realizability models in that they pick a particular set of realizers? So, it ought to be a realizability model, I guess? But they don&amp;rsquo;t say so explicitly. The interpretation is still quite heavily parameterized, but it does seem to fix or restrict the set of realizers. Anyway, this interpretation includes all the features of my definition above: it&amp;rsquo;s inductively defined over types, relating types to (a semantic model of) untyped λ terms, for the purposes of proving something about the collection of realizers as they related to the collection of all untyped λ terms.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">The A Means A</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2022/06/30/the-a-means-a/" />
  <id>urn:https-www-williamjbowman-com:-blog-2022-06-30-the-a-means-a</id>
  <published>2022-06-30T17:25:55Z</published>
  <updated>2022-06-30T17:25:55Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I have argued about the definition of &amp;ldquo;ANF&amp;rdquo; many times. I have looked at the history and origins, and studied the translation, and spoken to the authors. And yet people insist I&amp;rsquo;m &amp;ldquo;quacking&amp;rdquo; because I insist that &amp;ldquo;ANF&amp;rdquo; means &amp;ldquo;A-normal form&amp;rdquo;, where the &amp;ldquo;A&amp;rdquo; only means &amp;ldquo;A&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Here, I write down the best version of my perspective so far, so I can just point people to it.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;I want to answer three question: what does the &lt;em&gt;A&lt;/em&gt; mean, why does the &lt;em&gt;A&lt;/em&gt; matter, and where does the &lt;em&gt;A&lt;/em&gt; come from.&lt;/p&gt;

&lt;h2 id="what-does-the-a-mean"&gt;What does the &lt;em&gt;A&lt;/em&gt; mean?&lt;/h2&gt;

&lt;p&gt;The &amp;ldquo;A&amp;rdquo; in &amp;ldquo;A-normal form&amp;rdquo; refers to a particular formal object, named &amp;ldquo;A&amp;rdquo; (not &amp;ldquo;administrative&amp;rdquo;), with respect to which there is a normal form with certain useful properties. This form is &amp;ldquo;A normal&amp;rdquo;&amp;mdash;none of the A reductions apply to terms in this form&amp;mdash;hence, A-normal form.&lt;/p&gt;

&lt;p&gt;While it&amp;rsquo;s true that the history of ANF is concerned with &amp;ldquo;administrative reductions&amp;rdquo; &lt;em&gt;in CPS&lt;/em&gt;, this is an informal concept, modeled by the formal object &amp;ldquo;A&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;In truth, &amp;ldquo;A&amp;rdquo; is several formal objects, defined somewhat differently in at least 3 different papers. Only one of these is arguably called &amp;ldquo;administrative&amp;rdquo;, but is about CPS, and not what we now call ANF.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;A&amp;rdquo; appears in &amp;ldquo;The Essence of Compiling with Continuations&amp;rdquo;, page 5. Under the discussion of the CPS, optimization, and un-CPS diagram, the authors observe that this diagram begs for a completion, some direct process, &amp;ldquo;A&amp;rdquo;, that simply normalizes a term within the same language. This diagram is reproduced below: \[
\begin{array}{ccc}
e &amp;amp; \overset{CPS}{\to} &amp;amp; e' \\
\overset{A}{\downarrow} &amp;amp;&amp;amp; \overset{\beta}{\downarrow} \\
e_A &amp;amp; \overset{unCPS}{\leftarrow} &amp;amp; e_O
\end{array}
\] They ask, what are some set of reductions, call this set A, such that normalizing with respect to A would produce a normal form, A-normal form, that characterizes the use of CPS in practice.&lt;/p&gt;

&lt;p&gt;The same pattern appears in "Reasoning about Programs in Continuation-Passing Style, page 1:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;Thus, we refine this question as follows:  Is there a set of axioms, A, that extend the call-by-value λ-calculus such that: &amp;hellip;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The authors go on to define the set A, never naming it by &lt;em&gt;some administrative reductions&lt;/em&gt;, but deriving A instead from the inverse CPS translation.&lt;/p&gt;

&lt;p&gt;We could argue that Sabry&amp;rsquo;s thesis, Chapter 3, Section 1, &amp;ldquo;Administrative Source Reduction: The A-Reductions&amp;rdquo;, names the A-reductions &amp;ldquo;administrative&amp;rdquo;. He goes on to analyse those reductions considered to be the administrative ones, defining βlift and βflat in terms of CPS. He then defines in Definition 3.1, the administrative source reduction (A-reductions). However, these refer to reductions over CPS terms, and are distinct from the reductions considered for ANF. While they are the origin of ANF, they do not produce terms in what we now call ANF. A term in &amp;ldquo;administrative normal form&amp;rdquo; with respect to that set of reductions would actually be in CPS. That&amp;rsquo;s not what we mean when we say ANF; we mean normal with respect to the set A defined in &amp;ldquo;The Essence of Compiling with Continuations&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Maintaining this distinction between the formal object A and the informal notion of administrative reductions is important for two reasons. First, it helps remind us that ANF is a form ultimately about normalizing a specific set of reductions, not the output of a particular translation, which is important in practice. Implementations often relax ANF until code generation, by omitting some of the A reductions, typically, A2 in &amp;ldquo;The Essence of Compiling with Continuations&amp;rdquo;&amp;mdash;even that paper relaxes A2 in their implementation in the appendix, because A2 leads to exponential code duplication or requires object-language continuations (&amp;ldquo;join points&amp;rdquo;). It&amp;rsquo;s hard to even formally discuss this relaxation if we do not have the set of normalized reductions in mind. Second, the idea that ANF is free of &amp;ldquo;administrative&amp;rdquo; redexes is absurd, since the idea of the administrative redex is an informal concept: a reduction that isn&amp;rsquo;t really necessary but merely an artifact of the translation. It is easy to introduce such administrative redexes in ANF; e.g., &lt;code&gt;let x = y in
x&lt;/code&gt; contains an extra unnecessary ζ redex, but it is in ANF. It is, however, free of A reductions.&lt;/p&gt;

&lt;h2 id="why-does-the-a-matter"&gt;Why does the &lt;em&gt;A&lt;/em&gt; matter?&lt;/h2&gt;

&lt;p&gt;I don&amp;rsquo;t actually care what the &amp;ldquo;A&amp;rdquo; means, or what the authors intended it to mean. I care that we think about ANF as a normal form, normal with respect to a specific set of reductions.&lt;/p&gt;

&lt;p&gt;This most recent rant was triggered by a conversation with a reviewer, who, after observing that the &amp;ldquo;A&amp;rdquo; actually stood for &amp;ldquo;administrative&amp;rdquo;, asked whether our ANF translation could be decomposed into two translations, one that did everything but normalize the &lt;code&gt;if&lt;/code&gt;s (handling &lt;code&gt;if&lt;/code&gt; is annoying in ANF, as it either requires being clever or causes code duplication), and then separately handle &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The answer is completely obvious&amp;hellip; if you think about ANF in terms of a normal form with respect to a set of reductions, and not as merely the output of some translation process, nor &amp;ldquo;CPS but like without adminsitrative redexes&amp;rdquo;. Since ANF is a normal form with respect to &amp;ldquo;A&amp;rdquo;, we can easily decompose it into multiple normal forms, thus deriving several decomposed translations: remove the A reduction that normalizes &lt;code&gt;if&lt;/code&gt;, and you get another normal form. Remove the rules that normalize &lt;code&gt;if&lt;/code&gt; and nested &lt;code&gt;let&lt;/code&gt;, and you get monadic form.&lt;/p&gt;

&lt;p&gt;But all of this is much more complicated to explain if you think of ANF as a particular translation or particular syntactic form, and not a normal form with respect to the set A. And this seems to be very likely how you will think of you think &lt;em&gt;A&lt;/em&gt; means &lt;em&gt;administrative&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id="where-does-the-a-come-from"&gt;Where &lt;em&gt;does&lt;/em&gt; the &lt;em&gt;A&lt;/em&gt; come from??&lt;/h2&gt;

&lt;p&gt;Incidentally, I spoke with Amr after he read this blog post. The origin of the &amp;ldquo;A&amp;rdquo; comes from a result by Curry, who proves some theorems about any combinatory logic extended by a set &lt;em&gt;A&lt;/em&gt; of ground equations: https://staff.fnwi.uva.nl/p.h.rodenburg/Varia/RelCLlam.pdf&lt;/p&gt;

&lt;p&gt;This led Matthias to ask Amr to create a set &lt;em&gt;A&lt;/em&gt;, such that bla bla bla.&lt;/p&gt;

&lt;p&gt;Amr admits he may have intended a pun between &lt;em&gt;A&lt;/em&gt; and &lt;em&gt;administrative&lt;/em&gt;, but doesn&amp;rsquo;t remember.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What is peer reviewing?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2022/04/26/what-is-peer-reviewing/" />
  <id>urn:https-www-williamjbowman-com:-blog-2022-04-26-what-is-peer-reviewing</id>
  <published>2022-04-26T23:56:04Z</published>
  <updated>2022-04-26T23:56:04Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I&amp;rsquo;ve been doing, and experiencing, a lot of peer reviewing lately.
I&amp;rsquo;ve been ranting about it on Twitter as I get reviews that don&amp;rsquo;t help me and, in many ways, hurt me, and lauding reviews that provide useful constructive feedback (even if I disagree with it or the decisions).
I&amp;rsquo;ve been trying to figure out how to provide good reviews and avoid negative aspects of reviewing.&lt;/p&gt;

&lt;p&gt;I need to get the thoughts out of my head.
These are not declarations of what peer reviewing is or should be, but my attempt to work through those questions.&lt;/p&gt;
&lt;!--more--&gt;

&lt;h1 class="heading"&gt;&lt;a name="(part._.The_.Scientific_.Aspect_of_.Reviewing)"&gt;&lt;/a&gt;The Scientific Aspect of Reviewing&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.The_.Scientific_.Aspect_of_.Reviewing)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;

&lt;blockquote&gt;
 &lt;p&gt;scientific | &lt;span class="emph"&gt;adjective&lt;/span&gt;:
based on or characterized by the methods and principles of science.&lt;/p&gt;
 &lt;p&gt;Science | &lt;span class="emph"&gt;noun&lt;/span&gt;:
a systematically organized body of knowledge.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Mostly we think about the scientific aspect of peer reviewing.
If we&amp;rsquo;ve written a scientific piece, we have tried to answer a question, scientifically.
We have posed a research question, hypothesized some answer, tried to evaluate the answer objectively, and present all of that clearly to advance the state of knowledge.&lt;/p&gt;

&lt;p&gt;The point of peer review, then, is to check that we have indeed done some science.
To check our question is reasonable, that our evaluation is not flawed, and that we have indeed advanced the state of knowledge (and communicated that knowledge clearly, at least relatively to some community).&lt;/p&gt;

&lt;p&gt;This interpretation of peer review is intuitive, but is it real?&lt;/p&gt;

&lt;p&gt;Here are the evaluation criteria from the call for papers for some major programming languages conferences I&amp;rsquo;ve been involved in. They&amp;rsquo;re all SIGPLAN conferences, so they are all fairly similar:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  &lt;p&gt;POPL 2022:&lt;/p&gt;
  &lt;p&gt;The Review Committee will evaluate the technical contribution of each submission as well as its accessibility to both experts and the general POPL audience. All papers will be judged on significance, originality, relevance, correctness, and clarity. Each paper must explain its scientific contribution in both general and technical terms, identifying what has been accomplished, explaining why it is significant, and comparing it with previous work.&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;
  &lt;p&gt;PLDI 2022:&lt;/p&gt;
  &lt;p&gt;Reviewers will evaluate each contribution for its accuracy, significance, originality, and clarity. Submissions should be organized to communicate clearly to a broad programming-language audience as well as to experts on the paper&amp;#8217;s topics. Papers should identify what has been accomplished and how it relates to previous work.&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;
  &lt;p&gt;ICFP 2022:&lt;/p&gt;
  &lt;p&gt;Submissions will be evaluated according to their relevance, correctness, significance, originality, and clarity. Each submission should explain its contributions in both general and technical terms, clearly identifying what has been accomplished, explaining why it is significant, and comparing it with previous work. The technical content should be accessible to a broad audience.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;h2 class="heading"&gt;&lt;a name="(part._.Correctness)"&gt;&lt;/a&gt;Correctness&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Correctness)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;&lt;span class="emph"&gt;Accuracy&lt;/span&gt; or &lt;span class="emph"&gt;correctness&lt;/span&gt; appear in all of these.
This makes sense; one major aspect of reviewing is to make sure the scientific work hasn&amp;rsquo;t made any mistakes.
Of course, the reviewing itself might make mistakes.
The goal isn&amp;rsquo;t to do a perfect job, but to try.
And if we try, keep doing science, keep checking each others&amp;rsquo; work, keep asking questions and even re-asking questions, eventually we&amp;rsquo;ll approach something resembling the truth.
I like this criterion and think it&amp;rsquo;s probably the most important one.&lt;/p&gt;

&lt;h2 class="heading"&gt;&lt;a name="(part._.Originality)"&gt;&lt;/a&gt;Originality&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Originality)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;&lt;span class="emph"&gt;Originality&lt;/span&gt; appears in all three as well.
This one is a little odd.
If the point of science is to advance the state of knowledge, it makes sense that scientific work should be &lt;span class="emph"&gt;original&lt;/span&gt;, &lt;span class="emph"&gt;i.e.&lt;/span&gt;, new, novel, producing something that was previously unknown.
But, it also seems a little at odds with the previous criteria.
One great way for checking correctness is reproducing or replicating prior results, double-checking existing work and making sure we get the same answer.
The emphasis on originality or novelty seems to be at odds this goal.
We could interpret it a little more generously, by considering replication and reproduction as new in the sense that they are new evaluations of an old question, so it is still original work.
That&amp;rsquo;s okay with me.
But it does require a little care in the interpretation of the reviewing criteria....&lt;/p&gt;

&lt;h2 class="heading"&gt;&lt;a name="(part._.Clarity)"&gt;&lt;/a&gt;Clarity&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Clarity)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;&lt;span class="emph"&gt;Clarity&lt;/span&gt; appears in all three as well.
This is interesting as it maybe seems irrelevant to the idea of a rigorous and objective evaluation of a research question.&lt;/p&gt;

&lt;p&gt;It may even seem.. not true of essentially any research paper.
If you&amp;rsquo;ve ever tried to read one of my research papers, and you&amp;rsquo;re not literally in my field, and even for many people who are, you&amp;rsquo;d probably say they&amp;rsquo;re hard to read.
Maybe not very clear, maybe lots of obtuse notation, vocabulary, methodologies, ideas, ...
But the reviews have judged them to be clear enough for accepting.&lt;/p&gt;

&lt;p&gt;So clarity seems to be quite ambiguous, quite subjective.
At the very least it&amp;rsquo;s relative.
Let&amp;rsquo;s say it&amp;rsquo;s relative to the community reviewing and calling for papers.&lt;/p&gt;

&lt;p&gt;But why is it important? As long as the work is correct!
Well, the point of science isn&amp;rsquo;t merely evaluating a research question, but advancing the state of knowledge.
We can&amp;rsquo;t very well advance knowledge if no one, or a vast majority of a community of interest, can understand what you&amp;rsquo;ve done.&lt;/p&gt;

&lt;p&gt;So it&amp;rsquo;s important for the work to be not only well evaluated, but clearly (relatively) well evaluated, and well communicated.
This way it advance knowledge for many people, and not just the authors.&lt;/p&gt;

&lt;p&gt;So far, so scientific.
All these criteria directly relate to the original scientific goal.&lt;/p&gt;

&lt;h2 class="heading"&gt;&lt;a name="(part._.Relevance)"&gt;&lt;/a&gt;Relevance&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Relevance)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;POPL and ICFP include "relevance".
I take this to mean relevance to the field.
For example, submitting a machine learning paper to POPL is probably not relevance, even if it is of the highest quality science.&lt;/p&gt;

&lt;p&gt;This is related to the advancement of knowledge, since only reviewers who are familiar with the area, methodologies, state of knowledge etc are going to be capable of assessing the other criteria.&lt;/p&gt;

&lt;p&gt;This leads to some problems at the borders between areas.
What if it is relevant, but heavily in another field, and as a result, there isn&amp;rsquo;t very much expertise to review the paper?
But one hears stories about these papers having a hard time finding a place in any venue.
I guess I should take a charitable view of such papers, but then, that may require sacrificing review quality.&lt;/p&gt;

&lt;p&gt;Or what about work that is &lt;span class="emph"&gt;revolutionary&lt;/span&gt;, in the sense that it is creating completely new models, methodologies?
Such work would argue that it is relevant, but it would be difficult for the reviewers to judge it so.
It might seem completely irrelevant&amp;#8212;
 &lt;wbr /&gt;no one has used it yet, perfectly good techniques (which will, by nature, be more clear and easier to judge correctness of) will apply in many of the examples.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t think there&amp;rsquo;s a good solution here.
Revolutions are hard.
Founding new fields, subfields, etc, is hard.&lt;/p&gt;

&lt;h2 class="heading"&gt;&lt;a name="(part._.Significance)"&gt;&lt;/a&gt;Significance&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Significance)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;The last criteria for PLDI is &lt;span class="emph"&gt;significance&lt;/span&gt;, which also appears for POPL and ICFP.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;I have no idea what this means.
The dictionary provides:
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote&gt;
  &lt;p&gt;significance | &lt;span class="emph"&gt;noun [mass noun]&lt;/span&gt;: the quality of being worthy of attention; importance&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;This seems like a very suspect criterion.
How do we know, apriori, which ideas are important, are worthy of attention?
This requires us to understand, in advance, what impact the work could have?
Are we psychic?&lt;/p&gt;

&lt;p&gt;I suppose, in some cases, it might be somewhat clear that work is not important.
Sam TH, who I love for pushing against my (and others&amp;rsquo;) simple takes to advocate for complexity, recommended this paper: &lt;a href="https://doi.org/10.1007/s11245-006-0005-2"&gt;&lt;span class="url"&gt;https://doi.org/10.1007/s11245-006-0005-2&lt;/span&gt;&lt;/a&gt;.
It introduces a strawman in the context of philosphy, of people inventing and then studying a game called "chmess".
One could investigate all of these questions scientifically, but they would all be insignificant, because the made up game affects no one in the world.&lt;/p&gt;

&lt;p&gt;In this case, it&amp;rsquo;s clear that the questions are not significant, but it introduces the key problem with significance&amp;#8212;
 &lt;wbr /&gt;the answer to the question is a relative one (like clarity).
Maybe a question is not significant to one field, but is to another, because that field knows how to apply that kind of question to some other problem that is significant, and so on.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t know how to detect significance then.&lt;/p&gt;

&lt;p&gt;The chmess paper suggests asking whether you could explain the research question to an outside audience and convince them of its importance.
This seems like a low bar, however.
Almost every paper I read begins with a motivation section, which does exactly that:
here&amp;rsquo;s some interesting the theoretical problem and how it could, in principle, be used to solve or address or make progress on some real world problem.
Perhaps that just means we&amp;rsquo;re all good at (convincing ourselves that we&amp;rsquo;re) working on significant problems.&lt;/p&gt;

&lt;p&gt;Supposing I could accurately judge significance by this definition, how does it relate to the original goal: ensuring that a scientific work advances knowledge?
Well, if the result is unimportant, one might argue (if one were a pragmatist, in the sense of philosophy sense) that unimportant knowledge is not useful, and therefore, not knowledge.
But it still seems quite difficult to judge the utility of knowledge.&lt;/p&gt;

&lt;p&gt;It reminds me of number theory, which was considered quite without practical application.
Until we invented cryptography.&lt;/p&gt;

&lt;p&gt;While trying to understand significance on Twitter, others proposed an alternative definition: that the research question is &lt;span class="emph"&gt;large enough&lt;/span&gt; (to be important?).
This seems like an even more suspect definition.
For one, what is large enough?
Completely subjective.
The prior definition of significance is relative to a community, but this is relative to an individual&amp;rsquo;s expectations.
For two, it has perverse results in practice.
In an effort to ensure a result is big enough, an author is incentivized to make a result larger (or appear larger), perhaps artificially.
The knowledge is withheld from the community and society until it reaches some arbitrary bar.
That bar is unavoidably pushed higher, as each year new scientists joining the field compare to the current bar, new authors strive to beat that bar (from the prior incentive) and the baseline is reset.&lt;/p&gt;

&lt;p&gt;And for what?
What part of our original scientific goal is achieved by ensuring a result is "large enough"?
It doesn&amp;rsquo;t help advance knowledge to withhold a result for being small, if it is correct, and clear, and original.&lt;/p&gt;

&lt;p&gt;I see none.&lt;/p&gt;

&lt;p&gt;At best, this definition seems to be a response to something unscientific... see the next section.&lt;/p&gt;

&lt;h1 class="heading"&gt;&lt;a name="(part._.The_.Social_.Aspect_of_.Reviewing)"&gt;&lt;/a&gt;The Social Aspect of Reviewing&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.The_.Social_.Aspect_of_.Reviewing)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;

&lt;blockquote&gt;
 &lt;p&gt;social | &lt;span class="emph"&gt;adjective&lt;/span&gt;: relating to society or its organization.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;There&amp;rsquo;s another aspect to peer review, which I will call a social aspect.
Science is, of course, a social process, so these are not unrelated.
But I want to separate them.&lt;/p&gt;

&lt;p&gt;The previous aspects to reviewing dealt &lt;span class="emph"&gt;explicity&lt;/span&gt; with scientific mission&amp;#8212;
 &lt;wbr /&gt;the advancement of knowledge.
But it is us humans that are attempting to do that, in a large context with many systems and pressures that we interact with and within.&lt;/p&gt;

&lt;p&gt;For example, to advnace knowledge, we must keep up with the state of knowledge.
One purpose of reviewing I&amp;rsquo;ve heard advocate is to act in defense of human attention, so that we can focus on the advancement that are relevant and important.
A peer reviewers job is, in part, to reject "noise" from the process, so it is even possible to know what the state of knowledge is.&lt;/p&gt;

&lt;p&gt;This seems related to the second definition of "significance" in the prior section.
If a result is "too small", perhaps it becomes a distraction.
New authors spend too much time learning it and pushing it to a state of being useful, taking more time than it would have taken the original authors, thus wasting time.
Or perhaps realizing the result does not scale to enough settings as originally assumed, but only after wasting a great deal of time, attention, and effort.&lt;/p&gt;

&lt;p&gt;But this requires us to make the call on what others will want to and/or should pay attention to.
That&amp;rsquo;s a hard call to make; I&amp;rsquo;m not sure whether I can make or should make it.&lt;/p&gt;

&lt;p&gt;It could also be a reaction to gaming the system that employs scientists and funds research.
A bunch of small publication is still a large publication count, which can (through the magic of relying on metrics) convince people to provide funding or jobs to one person, but not another.
This, in turn, can prevent others from doing useful work to advance knowledge; they could use made use of those jobs or funding.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not going to rant here about the Tyranny of Metrics, for which there&amp;rsquo;s a whole book I heartily recommend.&lt;/p&gt;

&lt;p&gt;Metrics exist, and we have to work with them, so it&amp;rsquo;s worth paying attention to them.
We don&amp;rsquo;t want people gaming our system, even if our system is stupid.
We should try to change it, but that&amp;rsquo;s not always possible.&lt;/p&gt;

&lt;p&gt;Still I think it&amp;rsquo;s worth being careful of doing more harm than good when trying to prevent people from gaming the system.
I&amp;rsquo;m not sure how easy it is to recognize "salami slicing" a work in to lots of little pieces of work, apriori.
Science &lt;span class="emph"&gt;is&lt;/span&gt; incremental.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;On the other side, does a venue have a responsibility to game unjust systems?
Some systems exist evaluate venues based on inclusion in certain indexes, acceptance reates, classificaiton as journal or conference, etc, and peoples jobs&amp;rsquo; rely on these things.
Should a venue do things like turn itself into a journal (as PACMPL has done) to game an unjust evaluation system?
What about targeting a certain acceptance ratio, which POPL explicitly does?&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote class="refpara"&gt;
  &lt;blockquote class="refcolumn"&gt;
   &lt;blockquote class="refcontent"&gt;
    &lt;p&gt;&lt;a href="https://www.sigplan.org/Conferences/POPL/Principles/"&gt;&lt;span class="url"&gt;https://www.sigplan.org/Conferences/POPL/Principles/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;This acceptance ratio is important for maintaing a high ranking in the CORE ranking system.&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote class="refpara"&gt;
  &lt;blockquote class="refcolumn"&gt;
   &lt;blockquote class="refcontent"&gt;
    &lt;p&gt;See ICFP&amp;rsquo;s downgrade from A* to A, which cites the acceptance ratio of 33% being too high: &lt;a href="http://portal.core.edu.au/core/media/justification/CORE2021/4612ICFP.pdf"&gt;&lt;span class="url"&gt;http://portal.core.edu.au/core/media/justification/CORE2021/4612ICFP.pdf&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;Do reviewers have a responsibility to maintain a high ranking, to the benefit of the venue and the people submitting to their venue, by rejecting a certain proportion of papers?
Without doing so, we risk the scientific endeavour&amp;#8212;
 &lt;wbr /&gt;the venue and its community may no longer be able to effectively advance knowledge.&lt;/div&gt;

&lt;p&gt;I dunno man I&amp;rsquo;m not a moral philosopher.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">The Syllabus</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2022/04/15/the-syllabus/" />
  <id>urn:https-www-williamjbowman-com:-blog-2022-04-15-the-syllabus</id>
  <published>2022-04-15T19:55:39Z</published>
  <updated>2022-04-15T19:55:39Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I wrote the follow at some semester prior to today, about no one in particular, while updating syllabus.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Please read the syllabus. The answer to your question is on the syllabus. If you review the syllabus you will find answers to this question and others. As I have said in many other places many times before, you can find the answer to your questions regarding course policies answered on the syllabus. The syllabus is where we describe the answer to course policies, grading, instructions on what to do in various circumstances, and answer frequently asked questions. Like this one. The syllabus is a useful tool for discovering the answer to questions about the course. Questions we have answered on the syllabus should not be asked because we have answered them on the syllabus. Piazza, email, canvas messages, office hours, after class ambushing of the professor and TAs, and lab are not the places to ask questions that are answered on the syllabus. so many times but it is not getting to me. Even if you think your situation is unusual, we have almost certainly run into it before and answered it on the syllabus. You will never make me crack. We have been teaching for decades, and get guidance from Above, and we answer the questions and put information on the syllabus. Every time you ask a question that is answered on the syllabus, the unholy child weeps the blood of virgins, and Russian hackers subtract points from your final grade. Asking questions that are answered on the syllabus summons tainted souls into the realm of the living. Questions answered on the syllabus go together like love, marriage, and ritual infanticide. The syllabus cannot hold it is too late. The force of questions already answered on the syllabus in the same conceptual space will destroy your mind like so much watery putty. If you ask questions answered on the syllabus you are giving in to Them and their blasphemous ways which doom us all to inhuman toil for the One whose Name cannot be expressed in the Basic Multilingual Plane, he comes. The endless questions already answered on the syllabus will liquify the n​erves of the sentient whilst you observe, your psyche withering in the onslaught of horror. ((Questions-answered-on-Syll̿̔̉us are the cancer that is killing the Piazza it is too late it is too late we cannot be saved the transgression of a chi͡ld ensures syllabus will consume all living tissue (except for questions already answered there which it cannot, as they have been answered on the syllabus) dear lord help us how can anyone survive this scourge asking questions answered on the syllabus has doomed humanity to ( an eternity of dread torture and time wasted that could have spent teaching as questions already answered on the syllabus establishes a breach between this world and the dread realm of c͒ͪo͛ͫrrupt entities (like Grading Scheme, but more corrupt) a mere glimpse of the world of questions answered on the syllabus will ins​tantly transport a students&amp;rsquo; consciousness into a world of ceaseless screaming, he comes, the pestilent slithy syllabus-infection wil​l devour your questions, application and existence for all time like The Design Recipe only worse he comes he comes do not fi​ght he com̡e̶s, ̕h̵i​s un̨ho͞ly radiańcé destro҉ying all enli̍̈́̂̈́ghtenment, syllabus questions lea͠ki̧n͘g fr̶ǫm ̡yo​͟ur eye͢s̸ ̛l̕ik͏e liq​uid pain, the song of re̸gular waitlist will exti​nguish the voices of mor​tal man from the sp​here I can see it can you see ̲͚̖͔̙î̩́t̲͎̩̱͔́̋̀ it is beautiful t​he final snuffing of the lie​s of Man ALL IS LOŚ͖̩͇̗̪̏̈́T ALL I​S LOST the pon̷y he comes he c̶̮omes he comes the ich​or permeates all MY FACE MY FACE ᵒh god no NO NOO̼O​O NΘ stop the an​*̶͑̾̾​̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨe̠̅s ͎a̧͈͖r̽̾̈́͒͑e n​ot rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚​N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ (((&lt;/p&gt;

&lt;p&gt;)&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What is the Point of a Final Exam</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2022/01/06/what-is-the-point-of-a-final-exam/" />
  <id>urn:https-www-williamjbowman-com:-blog-2022-01-06-what-is-the-point-of-a-final-exam</id>
  <published>2022-01-07T04:11:16Z</published>
  <updated>2022-01-07T04:11:16Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;It&amp;rsquo;s weird, but professors are almost never taught how to teach, how to design a course, how to assess students, how to design an exam or what the point of an exam even is. We&amp;rsquo;re just expected to pick this up on our own, I guess. It&amp;rsquo;s not as nonsensical as it sounds, since we are trained how to do research and communicate that research, and there is some overlap. But still.&lt;/p&gt;

&lt;p&gt;If my experience is any indication, we just pick up an existing course structure and more or less follow that. Oh, the last person who taught this course used this material, and this syllabus, and these exams, so I&amp;rsquo;ll just do more or less that for now. If we&amp;rsquo;re ambitious and/or want to shoot our tenure track in the foot, we might try to innovate soon after. Otherwise, we might innovate later.&lt;/p&gt;

&lt;p&gt;Anyway I&amp;rsquo;m not good at doing things just because that&amp;rsquo;s how they&amp;rsquo;ve always been done; I need first principles. After designing, administering, grading, invigilating several of them, I was struggling to figure out what the point of a final exam is. So I had a bunch of conversations on &lt;a href="https://twitter.com/wilbowma/status/1479204850185355264"&gt;Twitter&lt;/a&gt; and now I&amp;rsquo;m collecting my thoughts on what the point of a final exam is and how it might, or might not, serve a purpose in my course.&lt;/p&gt;

&lt;p&gt;Warning: I am not an education researcher, and this is not research, and it&amp;rsquo;s got a lot of stream-of-consciousness.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="what-is-the-point-of-a-final"&gt;What is the point of a final?&lt;/h2&gt;

&lt;p&gt;Obviously, a final exam is a part of a course, so what is the point of a course? Presumably, to teach students. If only we lived in such a utopia.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;d start by assuming the purpose of a university course is:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;to teach students; and&lt;/li&gt;
 &lt;li&gt;to credential students.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;I consider credentialing to be less important than teaching, but acknowledge that there is a use in credentialing, so I should do it and do it well.&lt;/p&gt;

&lt;h3 id="credentialing"&gt;Credentialing&lt;/h3&gt;

&lt;p&gt;A final exam can very easily accomplish credentialing: you put everything the students should have learned in the course on the final exam, and you measure how well they do, giving them a grade (credential).&lt;/p&gt;

&lt;p&gt;But is a final exam the best way to accomplish credentialing? What goes into credentialing? I think the main principle is that we&amp;rsquo;d like the credential to be close to ground truth. A high mark should indicate high mastery, and vice versa. How do we know if an exam is measuring mastery well?&lt;/p&gt;

&lt;p&gt;After a bunch of discussions, I think there are a few threats that could cause measurement error in any assessment:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;cheating;&lt;/li&gt;
 &lt;li&gt;student performance error (e.g., stress, anxiety, illness);&lt;/li&gt;
 &lt;li&gt;design error (e.g., confusing instructions or questions, too little time to complete assessment, questions that don&amp;rsquo;t measure learning objectives);&lt;/li&gt;
 &lt;li&gt;attribution error (e.g., measuring a group assessment that doesn&amp;rsquo;t reflect an individual&amp;rsquo;s mastery);&lt;/li&gt;
 &lt;li&gt;sampling error (e.g., a grade on an assessment early in the semester does not actually indicate lack of mastery if the student learns later but has no opportunity to demonstrate improvement later; or, an assessment in one context may not be representative in another context, so another assessment in another context is useful).&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;I&amp;rsquo;m going to mostly ignore (3).  It&amp;rsquo;s a research area of its own (e.g., &lt;a href="https://en.wikipedia.org/wiki/Item_response_theory"&gt;Item Response Theory&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Concept_inventory"&gt;Concept Inventory&lt;/a&gt;), for one, and I&amp;rsquo;m no expert in that area. But design errors in an exam are as likely (or unlikely) as in any other assessment, or perhaps less because course staff can spend more time polishing a single exam than multiple assessments.&lt;/p&gt;

&lt;p&gt;Exams, and final exams, reduce (1) and (4) very well. Exams are typically very structured making cheating difficult compared to homework&amp;rsquo;s, projects, etc, and to properly measure a single individual. Take home or online exam don&amp;rsquo;t have this benefit, so must be designed to be more difficult, complex, or required invasive invigilation technology.&lt;/p&gt;

&lt;p&gt;Final exams in particular mitigate (5), since they occur at the very end of the semester. Exams in general also provide an opportunity to revisit assessing several learning objectives in another, broader, perhaps integrated context.&lt;/p&gt;

&lt;p&gt;Exams seem very susceptible to (2). Universities typically have policies in place to support accessibility and deal with illness, to help address some of (2). But many students find a single, highly weighted exam very stressful, and they may fail to perform on this one, very important assessment, despite having mastered material and demonstrated that mastery throughout the semester. On the other hand, some students find exams far less stressful, and far less time consuming, than many intermediate assessments throughout a semester. Students who find planning or long term focus challenging, or have chronic accessibility issues, might find an exam much easier than a project, for example.&lt;/p&gt;

&lt;p&gt;So exams are &lt;em&gt;pretty&lt;/em&gt; good for credentialing, in that they avoid sources of measurement error, as long as they&amp;rsquo;re well designed. But they&amp;rsquo;re very stressful. So if you need a credentialing assessment that reduce (1), (4), and (5), a final exam seems like a good choice, if you can find a way to reduce stress and anxiety. Maybe novel exam structures could do that; however, novel structures might cause more of (1) and (4), and be more complex to design and thus making (3) even trickier.&lt;/p&gt;

&lt;p&gt;Some learning objectives might also be difficult to assess with other forms of assessment than exams. For example, in my project-based compilers course, some of my learning objectives don&amp;rsquo;t fit into the course-long &amp;ldquo;write a compiler&amp;rdquo; project. They are latent skills I&amp;rsquo;d like students to learn from building a compiler, but I can&amp;rsquo;t figure out how to explicitly measure that learning in the project. This could be a failure of my ability, but it suggests the structure of exams is simpler to employ.&lt;/p&gt;

&lt;h3 id="teaching"&gt;Teaching&lt;/h3&gt;

&lt;p&gt;I consider credentialing less important than teaching, yet I covered it first because exams seem most related to credentialing.&lt;/p&gt;

&lt;p&gt;Some of my colleagues pointed out that you can make the exam part of the teaching process. This is very counter to how I&amp;rsquo;ve seen exams.&lt;/p&gt;

&lt;p&gt;An exam, particularly a final exam, can be an opportunity for students to reflect on all the material students have seen. They could be presented a new challenge or material that they should be able to learn from if they&amp;rsquo;ve mastered course material. They could also be given a chance for explicit transfer from one context to another, related to point (5) in the previous section about measuring skills in different contexts.&lt;/p&gt;

&lt;p&gt;Given the stress caused by the assessment function of an exam, particularly a final exam, I&amp;rsquo;m not sure how useful this is compared to other methods of teaching. If you want to give students the opportunity to see something in a new context, why not multiple (smaller) projects, or multiple homeworks? Novel exam structures, or lower stakes can mitigate this, as discussed above, but come with design and measurement challenges. And at what point is a less stressful, novel structured &amp;ldquo;exam&amp;rdquo; really an exam, and not something else?&lt;/p&gt;

&lt;p&gt;Another way the exam, and final exam, serve teaching is actually taking advantage of the high stakes of the exam. By giving students adequate time and material to review for the exam, they&amp;rsquo;re able to review all the material in the course in preparation for a high-stakes exam. This review is useful for learning, even if the exam itself is not.&lt;/p&gt;

&lt;p&gt;This seems at odds with research on teaching as it relates to grades, though. I&amp;rsquo;d suggest that it&amp;rsquo;s the grade, not the exam, that causes students to review. &lt;a href="https://www.lifescied.org/doi/10.1187/cbe.cbe-14-03-0054"&gt;Teaching More by Grading Less (or Differently)&lt;/a&gt; notes that grades motivate students perversely, lowering interest in learning but causing anxiety and interest in avoiding a bad grade. This suggests exams as motivator for reviewing material are not a good way to motivate learning.&lt;/p&gt;

&lt;p&gt;Final exams in particular seem to next to useless for teaching since students also don&amp;rsquo;t get very much qualitative feedback. Even if they do, they have very little reason, method, or even time to review that feedback and apply it. So even if the exam is cleverly structured to enable learning in a new context, or lets students integrate disparate lessons, will they know whether they successfully integrated lessons or transfered skills to a new context? Even if the instructor spent the time to provide qualitative feedback (which, in my experience, is not what happens with a final exam), the incentives are against the student using it.&lt;/p&gt;

&lt;h3 id="is-a-final-exam-right-for-my-course"&gt;Is a final exam right for my course?&lt;/h3&gt;

&lt;h4 id="for-teaching"&gt;For Teaching&lt;/h4&gt;

&lt;p&gt;I&amp;rsquo;m not really convinced by the value of the exam for teaching, in itself. But, I could see two reasons:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;your course doesn&amp;rsquo;t provide another final opportunity for students to integrate disparate lessons into a whole;&lt;/li&gt;
 &lt;li&gt;your course must introduce a variety of disparate skills that students have little opportunity to revisit, but that a final exam encourages them to review.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;This requires mitigating stress causing performance problems on the exam, or destroying the intrinsic motivations for learning. I don&amp;rsquo;t think stress is a problem in itself, if it can be managed. I&amp;rsquo;m more concerned about replacing intrinsic motivation with extrinsic.&lt;/p&gt;

&lt;h4 id="for-credentialing"&gt;For Credentialing&lt;/h4&gt;

&lt;p&gt;Final exams seem very useful for courses with group work, or where detecting cheating is difficult. I&amp;rsquo;d hate to optimize for trying to catch cheating, but I think detecting it is necessary, particularly since credentialing is part of the goal of a university course. In-person exams are a much less invasive and less time-consuming mode of invigilating.&lt;/p&gt;

&lt;p&gt;Similarly, with heavy group work, it is difficult to assess individual mastery. Alternatives include oral assessment or review of the group work.  This is resource intensive, but also enables more qualitative feedback so could have additional value for teaching.&lt;/p&gt;

&lt;h4 id="an-example"&gt;An Example&lt;/h4&gt;

&lt;p&gt;In my case, I&amp;rsquo;m trying to decide whether exams are right for my compilers course. The course is largely structured around a single semester-long project where the students implement a compiler (a big software project). The first two weeks milestones are completed individually, but the rest of the semester is completed in a group. Students who complete and contribute to the project can be reasonably assumed to have mastered a large portion of the material and most of the learning objectives. The project is not graded until the end of the semester, and students are provided considerable intermediate feedback, so have a lot of opportunity to learn from feedback, improve, and demonstrate improvement.&lt;/p&gt;

&lt;p&gt;Cheating is a minor concern, but shirking is a bigger concern. A student could easily coast on their group.&lt;/p&gt;

&lt;p&gt;I think an exam has some minor effect for discouraging shirking, and at least lets us catch it. I think performing oral code reviews and some form of survey of group contribution would be a more direct way of identifying this and providing more qualitative feedback. However, I don&amp;rsquo;t really have the resources for more than about 1 code review. We could perhaps implement it stochasticly.&lt;/p&gt;

&lt;p&gt;An exam provides some opportunity for learning, in itself, but at a high cost. I can use it to have students apply the same material in a new context.  However, in such a time constrained and high-stakes setting that I&amp;rsquo;m not convinced it is particularly effect or is worth the cost. The project itself is cumulative, and provides all the opportunity and material needed to review the course, so encouraging review isn&amp;rsquo;t necessary.&lt;/p&gt;

&lt;p&gt;Compared to an exam, providing more, low-stakes opportunities to apply lessons in a new context seems like a better approach, since it mitigates (2) and provide more opportunity for feedback, learning from the feedback, and demonstrating learning. Making these exercises individual would address cheating and shirking, but might require them to be higher stakes, at least cumulatively. This would have a stronger effect for detecting shirking early. However, this would disadvantage students who find multiple assessments problematic. Such students are already at a disadvantage because of the time investment the project requires.&lt;/p&gt;

&lt;p&gt;The exam does provide an opportunity to assess some learning objectives that I can&amp;rsquo;t figure out how to assess in the project. Perhaps I could integrate these into the aforementioned lower stakes exercises, or figure out how to integrate them into the project. Or perhaps these learning objectives aren&amp;rsquo;t really important, if I think the project is most important.&lt;/p&gt;

&lt;p&gt;So it seems like the primary purpose the exam is serving in my course is credentialing.  It helps us avoid attribution error, and to a lesser extent sampling error, at the cost of normal performance errors. It serves little, but some, learning function.&lt;/p&gt;

&lt;p&gt;The learning function might be better served by multiple excesses outside the project.  There&amp;rsquo;s a tension in using them: they need to be high stakes to serve the credentialing function and avoid sampling error, but low stakes to serve the learning functions. Sampling error is not a big problem in this course, so maybe I should favour low stakes exercises.&lt;/p&gt;

&lt;p&gt;Attribution error is a problem, but stochastic code review and group work surveys might be a better way to address this than an exam.&lt;/p&gt;

&lt;p&gt;If the exam is not in-person, the increased possibility of cheating negates some effect on attribution error, although code similarity detection tools make detecting cheating easier than detecting attribution error.&lt;/p&gt;

&lt;p&gt;The exam is perhaps a simpler mechanism to employ than a combination of more small exercises and stochastic code review, but could result in more performance error.&lt;/p&gt;

&lt;p&gt;Is an exam right? I don&amp;rsquo;t think it&amp;rsquo;s a wrong choice, but I think there are better choices particularly in favour of learning, and now I have a better idea of what the trade-offs are.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Enabling CORS for nginx WebDAV and CalDAV reverse-proxy</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2021/05/13/enabling-cors-for-nginx-webdav-and-caldav-reverse-proxy/" />
  <id>urn:https-www-williamjbowman-com:-blog-2021-05-13-enabling-cors-for-nginx-webdav-and-caldav-reverse-proxy</id>
  <published>2021-05-13T20:08:26Z</published>
  <updated>2021-05-13T20:08:26Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;The past few weeks I&amp;rsquo;ve been learning to develop and deploy a Progress Web App (PWA) that can communicate with my WebDAV and CalDAV servers.
Unfortunately, while these are on the same domain, they are on different sub-domains, and this causes the requests to be considered cross-origin requests.
For security reasons, cross-origin requests are blocked by most browsers by default unless the server explicitly allows cross-origin resource sharing (&lt;a name="(tech._cor)"&gt;&lt;/a&gt;&lt;span style="font-style: italic"&gt;CORS&lt;/span&gt;).
This is pretty easy to set up for static resources or scripts, if they use default headers and GET and POST methods.
However, it&amp;rsquo;s particularly complicated for WebDAV, CalDAV, and other protocols that use additional headers or methods.&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;
 &lt;h1 class="fake-header"&gt;Table of Contents&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;table cellpadding="0" cellspacing="0"&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toptoclink" data-pltdoc="x" href="#%28part._.T.L.D.R%29"&gt;1&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;TLDR&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toptoclink" data-pltdoc="x" href="#%28part._.C.O.R.S_.Requests_and_.Responses%29"&gt;2&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;CORS Requests and Responses&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toclink" data-pltdoc="x" href="#%28part._.Preflight%29"&gt;2.1&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Preflight&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toclink" data-pltdoc="x" href="#%28part._.Preflight_.Request%29"&gt;2.1.1&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Preflight Request&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toclink" data-pltdoc="x" href="#%28part._.Preflight_.Response%29"&gt;2.1.2&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Preflight Response&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toclink" data-pltdoc="x" href="#%28part._.Cross-.Origin_.Requests%29"&gt;2.2&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Cross-Origin Requests&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toptoclink" data-pltdoc="x" href="#%28part._.Configuring_nginx%29"&gt;3&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Configuring nginx&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toclink" data-pltdoc="x" href="#%28part._.Configure_.Valid_.Cross-.Origin_.Hosts%29"&gt;3.1&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Configure Valid Cross-Origin Hosts&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toclink" data-pltdoc="x" href="#%28part._.Configure_.C.O.R.S_.Headers%29"&gt;3.2&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Configure CORS Headers&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toclink" data-pltdoc="x" href="#%28part._.Process_.C.O.R.S_.Requests%29"&gt;3.3&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Process CORS Requests&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;
     &lt;p&gt;&lt;span class="hspace"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a class="toptoclink" data-pltdoc="x" href="#%28part._.Conclusion_and_.Debugging%29"&gt;4&lt;span class="hspace"&gt;&amp;nbsp;&lt;/span&gt;Conclusion and Debugging&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;

&lt;h1 class="heading"&gt;1
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.T.L.D.R)"&gt;&lt;/a&gt;TLDR&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.T.L.D.R)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Copy/paste/modify the below snippets into your &lt;span class="stt"&gt;nginx.conf&lt;/span&gt; in the correct places.
You&amp;rsquo;ll need to add the &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; declarations to &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;http&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; context, and merge the two &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;server&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; declarations into your WebDAV and CalDAV server configuration blocks.
You&amp;rsquo;ll also need to customize the safelist that sets &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;$cors_origin_header&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;, and possibly the &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;$cors_expose_headers&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; and &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;$cors_allow_headers&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; variables.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;&lt;a href="//resources/@|filename|"&gt;cors-nginx.conf&lt;/a&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;div class="brush: nginx"&gt;
  &lt;pre&gt;&lt;code&gt;http {
  # .. in http context ..
  # Declare the safe cross-origin hosts
  map $http_origin $cors_origin_header {
    hostnames;
    default "https://example.com";
    "https://example.com" "$http_origin";
    "https://www.example.com" "$http_origin";
  }
  # Declare CORS exposed response headers
  map $host $std_response_headers {
    default "Content-Type, Content-Range, Content-Language, Date, Content-Length, Content-Encoding";
  }
  map $host $cache_control_response_headers  {
    default "Etag, Last-Modified";
  }
  map $host $dav_response_headers {
    default "Dav";
  }
  map $host $cors_expose_headers {
    default "${dav_response_headers}, ${std_response_headers}, ${cache_control_response_headers}";
  }
  # Declare CORS allowed request headers
  map $host $std_request_headers {
    default "Authorization, Origin, X-Requested-With, Range, Accept-Encoding, Content-Length, Content-Type";
  }
  map $host $dav_request_headers {
    default "If-Match, If-None-Match, If-Modified-Since, Depth";
  }
  map $host $cors_allow_headers {
    default "${dav_request_headers}, ${std_request_headers}";
  }
  # Detect a preflight request
  map $http_access_control_request_headers $preflight_h {
    default "true";
    "" "false";
  }
  map $http_access_control_request_method $preflight_m {
    default "true";
    "" "false";
  }
  map $request_method $preflight {
    default "false";
    "OPTIONS" "${preflight_h}${preflight_m}true";
  }
  # Configure WebDAV
  server {
    listen       443 ssl http2;
    listen       [::]:443 ssl http2;
    server_name  webdav.example.com;

    location /.well-known/ {
      root /srv/http/www;
    }

    # Advertise CORS access controls.
    add_header "Access-Control-Allow-Origin" "$cors_origin_header" always;
    add_header "Access-Control-Allow-Credentials" "true" always;
    add_header "Access-Control-Expose-Headers" "$cors_expose_headers" always;

    location / {
      # Handle preflight request
      if ($preflight = "truetruetrue"){
         add_header "Access-Control-Allow-Origin" "$cors_origin_header";
         add_header "Access-Control-Allow-Headers" "$cors_allow_headers";
         add_header "Access-Control-Allow-Methods" "PROPFIND, COPY, MOVE, MKCOL, CONNECT, DELETE, DONE, GET, HEAD, OPTIONS, PATCH, POST, PUT";
         add_header "Access-Control-Max-Age" 1728000;
         add_header "Content-Type" "text/plain charset=UTF-8";
         add_header "Content-Length" 0;
         return 204;
      }

      auth_basic "Not currently available";
      auth_basic_user_file /etc/nginx/htpasswd;
      root /srv/http/webdav/data;
      client_body_temp_path /tmp/nginx-webdav;
      client_max_body_size 0;

      dav_methods PUT DELETE MKCOL COPY MOVE;
      dav_ext_methods PROPFIND OPTIONS;

      create_full_put_path on;
      dav_access user:rw group:r;

      autoindex on;
    }
  }

  # CalDAV and CardDAV
  server {
    listen       443 ssl http2;
    listen       [::]:443 ssl http2;
    server_name  caldav.example.com carddav.example.com;

    location /.well-known/ {
      root /srv/http/www;
    }

    location /.well-known/caldav {
      return 301 https://caldav.example.com/;
    }

    location /.well-known/carddav {
      return 301 https://carddav.example.com/;
    }

    add_header "Access-Control-Allow-Origin" "$cors_origin_header" always;
    add_header "Access-Control-Allow-Credentials" "true" always;
    add_header "Access-Control-Expose-Headers" "$cors_expose_headers" always;

    location / {
      if ($preflight = "truetruetrue"){
         add_header "Access-Control-Allow-Origin" "$cors_origin_header";
         add_header "Access-Control-Allow-Headers" "$cors_allow_headers";
         add_header "Access-Control-Allow-Methods" "REPORT, PROPFIND, COPY, MOVE, MKCOL, CONNECT, DELETE, DONE, GET, HEAD, OPTIONS, PATCH, POST, PUT";
         add_header "Access-Control-Max-Age" 1728000;
         add_header "Content-Type" "text/plain charset=UTF-8";
         add_header "Content-Length" 0;
         return 204;
      }

      auth_basic "Not currently available";
      auth_basic_user_file /etc/nginx/caldav/htpasswd;
      proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass_header Authorization;
      proxy_pass        http://127.0.0.1:5232/;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 class="heading"&gt;2
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.C.O.R.S_.Requests_and_.Responses)"&gt;&lt;/a&gt;CORS Requests and Responses&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.C.O.R.S_.Requests_and_.Responses)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;

&lt;h2 class="heading"&gt;2.1
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Preflight)"&gt;&lt;/a&gt;Preflight&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Preflight)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;When a script running in a secure browser attempts to make a cross-origin request, the browser first send a &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; (for non-trivial requests), and then sends the actual request if the server advertises that &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._cor%29"&gt;&lt;span class="techinside"&gt;CORS&lt;/span&gt;&lt;/a&gt; is enabled for that request.
A &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; might be skipped for an HTTP &lt;span class="stt"&gt;GET&lt;/span&gt; method request, because this is considered harmless.&lt;/p&gt;

&lt;h3 class="heading"&gt;2.1.1
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Preflight_.Request)"&gt;&lt;/a&gt;Preflight Request&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Preflight_.Request)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;Essentially, a &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; is the browser asking the server for permission to make a request of a certain &lt;span class="stt"&gt;METHOD&lt;/span&gt; and then share the data and certain headers with a third party.
The &lt;a name="(tech._preflight._request)"&gt;&lt;/a&gt;&lt;span style="font-style: italic"&gt;preflight request&lt;/span&gt; is an HTTP &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS"&gt;&lt;span class="stt"&gt;OPTIONS&lt;/span&gt;&lt;/a&gt; method request with the following headers set:
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers"&gt;&lt;span class="stt"&gt;Access-Control-Request-Headers&lt;/span&gt;&lt;/a&gt;, which declares the headers that the cross-origin script is requesting.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Method"&gt;&lt;span class="stt"&gt;Access-Control-Request-Method&lt;/span&gt;&lt;/a&gt;, which declares the method of the request that the cross-origin script wants to send.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin"&gt;&lt;span class="stt"&gt;Origin&lt;/span&gt;&lt;/a&gt;, which declares the domain of the origin of the script that wants to make a cross-origin request&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;

&lt;p&gt;For HTTP servers serving static content or scripts that don&amp;rsquo;t use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS"&gt;&lt;span class="stt"&gt;OPTIONS&lt;/span&gt;&lt;/a&gt;, it&amp;rsquo;s enough to detect an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS"&gt;&lt;span class="stt"&gt;OPTIONS&lt;/span&gt;&lt;/a&gt; request, set the above headers, and return a 204 status code.
For some HTTP servers, like WebDAV and CalDAV, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS"&gt;&lt;span class="stt"&gt;OPTIONS&lt;/span&gt;&lt;/a&gt; request has another use, and we really have to detect a 
 &lt;font class="badlink"&gt;&lt;span class="techoutside"&gt;&lt;span class="techinside"&gt;preflight reuqest&lt;/span&gt;&lt;/span&gt;&lt;/font&gt; by detecting both an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS"&gt;&lt;span class="stt"&gt;OPTIONS&lt;/span&gt;&lt;/a&gt; request and the &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; headers.&lt;/p&gt;

&lt;h3 class="heading"&gt;2.1.2
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Preflight_.Response)"&gt;&lt;/a&gt;Preflight Response&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Preflight_.Response)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;To respond to a &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt;, the server is expected to reply with an empty content response, HTTP status code 204, and the following headers:
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;/a&gt;, which declares the hostnames that are allowed to make cross-origin requests. This ought to include the &lt;span class="stt"&gt;Origin&lt;/span&gt; of &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; for the &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; to succeed, and can be a wildcard value &lt;span class="stt"&gt;*&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Headers&lt;/span&gt;&lt;/a&gt;, which declares which headers are allowed to be part of the cross-origin request. These are all be HTTP &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._request._header%29"&gt;&lt;span class="techinside"&gt;request headers&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Methods&lt;/span&gt;&lt;/a&gt;, which declares which HTTP methods are allowed as part of cross-origin request.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age"&gt;&lt;span class="stt"&gt;Access-Control-Max-Age&lt;/span&gt;&lt;/a&gt;, an optional header that declares how long this response to a &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; can be cached;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;The 204 status code declares a success with no content.
An HTTP &lt;a name="(tech._request._header)"&gt;&lt;/a&gt;&lt;span style="font-style: italic"&gt;request header&lt;/span&gt; is one that originates from the client and is part of a request from the client.
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote class="refpara"&gt;
  &lt;blockquote class="refcolumn"&gt;
   &lt;blockquote class="refcontent"&gt;
    &lt;p&gt;See &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Request_header"&gt;&lt;span class="url"&gt;https://developer.mozilla.org/en-US/docs/Glossary/Request_header&lt;/span&gt;&lt;/a&gt; for more.&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Some browsers (such as Firefox, and Chromium) will consider the &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; as succeeding if the above headers are present, even if the status code is not 204, and even if the request contains other data.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;Sme headers are part of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Headers&lt;/span&gt;&lt;/a&gt; by default, as they are considered safe.
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote class="refpara"&gt;
  &lt;blockquote class="refcolumn"&gt;
   &lt;blockquote class="refcontent"&gt;
    &lt;p&gt;See &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header"&gt;&lt;span class="url"&gt;https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;Figuring out exactly which headers to list in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Headers&lt;/span&gt;&lt;/a&gt; is a little annoying.
For my WebDAV (nginx) and CalDAV (radicale) servers, the following list seemed sufficient for my uses:
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;The following standard headers:
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization"&gt;&lt;span class="stt"&gt;Authorization&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin"&gt;&lt;span class="stt"&gt;Origin&lt;/span&gt;&lt;/a&gt;, &lt;span class="stt"&gt;X-Requested-With&lt;/span&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range"&gt;&lt;span class="stt"&gt;Range&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding"&gt;&lt;span class="stt"&gt;Accept-Encoding&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length"&gt;&lt;span class="stt"&gt;Content-Length&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type"&gt;&lt;span class="stt"&gt;Content-Type&lt;/span&gt;&lt;/a&gt;;&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;The following DAV headers: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Match"&gt;&lt;span class="stt"&gt;If-Match&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match"&gt;&lt;span class="stt"&gt;If-None-Match&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since"&gt;&lt;span class="stt"&gt;If-Modified-Since&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Depth"&gt;&lt;span class="stt"&gt;Depth&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;This will depend on exactly what web app is communicating with the server and what it relies on, what the underlying server is.
You may need to do a bunch of testing in the web developer&amp;rsquo;s console to figure it out.&lt;/div&gt;

&lt;p&gt;Similarly, figuring out exactly which methods to list in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Methods&lt;/span&gt;&lt;/a&gt; depends on the app and server (but not the browser).
These methods are probably more well-specified.
For WebDAV and CalDAV, the following were sufficient:
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/REPORT"&gt;&lt;span class="stt"&gt;REPORT&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PROPFIND"&gt;&lt;span class="stt"&gt;PROPFIND&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/COPY"&gt;&lt;span class="stt"&gt;COPY&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/MOVE"&gt;&lt;span class="stt"&gt;MOVE&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/MKCOL"&gt;&lt;span class="stt"&gt;MKCOL&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT"&gt;&lt;span class="stt"&gt;CONNECT&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE"&gt;&lt;span class="stt"&gt;DELETE&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DONE"&gt;&lt;span class="stt"&gt;DONE&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET"&gt;&lt;span class="stt"&gt;GET&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD"&gt;&lt;span class="stt"&gt;HEAD&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS"&gt;&lt;span class="stt"&gt;OPTIONS&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH"&gt;&lt;span class="stt"&gt;PATCH&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"&gt;&lt;span class="stt"&gt;POST&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT"&gt;&lt;span class="stt"&gt;PUT&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 class="heading"&gt;2.2
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Cross-.Origin_.Requests)"&gt;&lt;/a&gt;Cross-Origin Requests&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Cross-.Origin_.Requests)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;After a &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt;, the browser will start sending cross-origin HTTP requests.
These will be normal HTTP requests, but the browser will expect the following additional headers in the response:
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;/a&gt;, which declares the hostnames of cross-origin scripts that this response can be shared with.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Credentials&lt;/span&gt;&lt;/a&gt;, which is either "true" or "false", and declares whether the authorization information in this response can be shared with cross-origin scripts.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers"&gt;&lt;span class="stt"&gt;Access-Control-Expose-Headers&lt;/span&gt;&lt;/a&gt;, which declares which HTTP &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._response._header%29"&gt;&lt;span class="techinside"&gt;response headers&lt;/span&gt;&lt;/a&gt; can be exposed to the cross-origin script.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;An HTTP &lt;a name="(tech._response._header)"&gt;&lt;/a&gt;&lt;span style="font-style: italic"&gt;response header&lt;/span&gt; is one that originates from the server and is part of a response from the server. &lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote class="refpara"&gt;
  &lt;blockquote class="refcolumn"&gt;
   &lt;blockquote class="refcontent"&gt;
    &lt;p&gt;See &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Response_header"&gt;&lt;span class="url"&gt;https://developer.mozilla.org/en-US/docs/Glossary/Response_header&lt;/span&gt;&lt;/a&gt; for more.&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;For my WebDAV and CalDAV servers, I needed to expose via &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers"&gt;&lt;span class="stt"&gt;Access-Control-Expose-Headers&lt;/span&gt;&lt;/a&gt; the following for my uses:
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;The following standard &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._response._header%29"&gt;&lt;span class="techinside"&gt;response headers&lt;/span&gt;&lt;/a&gt;:
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type"&gt;&lt;span class="stt"&gt;Content-Type&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range"&gt;&lt;span class="stt"&gt;Content-Range&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language"&gt;&lt;span class="stt"&gt;Content-Language&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Date"&gt;&lt;span class="stt"&gt;Date&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length"&gt;&lt;span class="stt"&gt;Content-Length&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding"&gt;&lt;span class="stt"&gt;Content-Encoding&lt;/span&gt;&lt;/a&gt;;&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;The following &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._response._header%29"&gt;&lt;span class="techinside"&gt;response headers&lt;/span&gt;&lt;/a&gt; that have to do with cache control:
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Etag"&gt;&lt;span class="stt"&gt;Etag&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified"&gt;&lt;span class="stt"&gt;Last-Modified&lt;/span&gt;&lt;/a&gt;.
You may want to add &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Pragma"&gt;&lt;span class="stt"&gt;Pragma&lt;/span&gt;&lt;/a&gt; if you support HTTP 1.0, and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control"&gt;&lt;span class="stt"&gt;Cache-Control&lt;/span&gt;&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires"&gt;&lt;span class="stt"&gt;Expires&lt;/span&gt;&lt;/a&gt; if your server needs to direct your app about cache expiration. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Etag"&gt;&lt;span class="stt"&gt;Etag&lt;/span&gt;&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified"&gt;&lt;span class="stt"&gt;Last-Modified&lt;/span&gt;&lt;/a&gt; were sufficient for detecting changes between the local and remote versions of DAV files in my app.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;The following DAV-specific headers: &lt;a href="http://www.webdav.org/specs/rfc2518.html#HEADER_DAV"&gt;DAV&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;

&lt;h1 class="heading"&gt;3
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Configuring_nginx)"&gt;&lt;/a&gt;Configuring nginx&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Configuring_nginx)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Configuring &lt;span class="stt"&gt;nginx&lt;/span&gt; correctly is tricky due to the design of the &lt;span class="stt"&gt;nginx&lt;/span&gt; configuration language.
It is a declarative language, but can look imperative and trip us up.
We have to be careful in how we conditionally add headers and process requests.&lt;/p&gt;

&lt;p&gt;&lt;span class="stt"&gt;nginx&lt;/span&gt; also doesn&amp;rsquo;t allow us to use &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; to create variables in all contexts, so we have to be a little clever at times.&lt;/p&gt;

&lt;h2 class="heading"&gt;3.1
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Configure_.Valid_.Cross-.Origin_.Hosts)"&gt;&lt;/a&gt;Configure Valid Cross-Origin Hosts&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Configure_.Valid_.Cross-.Origin_.Hosts)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;To limit which domains can issue a cross-origin request, we create a safelist and set a variable based on the &lt;span class="stt"&gt;Origin&lt;/span&gt; header of the request.
We use &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; to declare the variable &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;$cors_origin_header&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; to be the origin, if the origin is on the safelist.
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote class="refpara"&gt;
  &lt;blockquote class="refcolumn"&gt;
   &lt;blockquote class="refcontent"&gt;
    &lt;p&gt;See &lt;a href="http://nginx.org/en/docs/http/ngx_http_map_module.html#map"&gt;&lt;span class="url"&gt;http://nginx.org/en/docs/http/ngx_http_map_module.html#map&lt;/span&gt;&lt;/a&gt; for more.&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;div class="brush: nginx"&gt;
 &lt;pre&gt;&lt;code&gt;map $http_origin $cors_origin_header {
  hostnames;
  default "https://example.com";
  "https://example.com" "$http_origin";
  "https://www.example.com" "$http_origin";
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this safelist, we allow cross-origin requests from &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;https://examples.com&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; and &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;https://www.examples.com&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;, but no other hosts.
We could use the wildcard &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;"*"&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; to allow requests from anyone.&lt;/p&gt;

&lt;h2 class="heading"&gt;3.2
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Configure_.C.O.R.S_.Headers)"&gt;&lt;/a&gt;Configure CORS Headers&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Configure_.C.O.R.S_.Headers)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;In &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;http&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; context, I use the following &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;s to declares the &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._cor%29"&gt;&lt;span class="techinside"&gt;CORS&lt;/span&gt;&lt;/a&gt; request and response headers.
This is an abuse of &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; to give us the ability do define variable in &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;http&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; context, since &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; doesn&amp;rsquo;t work in &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;http&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; context.&lt;/p&gt;

&lt;p&gt;You&amp;rsquo;re free to inline these header values later, but separating them out into these variables made them easier to reuse in both the WebDAV and CalDAV servers.&lt;/p&gt;

&lt;div class="brush: nginx"&gt;
 &lt;pre&gt;&lt;code&gt;# Declare allowed CORS Expose Headers; each is an HTTP response header.
map $host $std_response_headers {
  default "Content-Type, Content-Range, Content-Language, Date, Content-Length, Content-Encoding";
}
map $host $cache_control_response_headers  {
  default "Etag, Last-Modified";
}
map $host $dav_response_headers {
  default "DAV";
}
map $host $cors_expose_headers {
default "${dav_response_headers}, ${std_response_headers}, ${cache_control_response_headers}";
}

# Declare allowed CORS Request Headers; each is an http request header.
map $host $std_request_headers {
  default "Authorization, Origin, X-Requested-With, Range, Accept-Encoding, Content-Length, Content-Type";
}
map $host $dav_request_headers {
  default "If-Match, If-None-Match, If-Modified-Since, Depth";
}
map $host $cors_allow_headers {
  default "${dav_request_headers}, ${std_request_headers}";
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 class="heading"&gt;3.3
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Process_.C.O.R.S_.Requests)"&gt;&lt;/a&gt;Process CORS Requests&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Process_.C.O.R.S_.Requests)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;Next, we need to detect a &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt;.
We might be tempted to use &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;, but remember: &lt;a href="https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/"&gt;If is Evil&lt;/a&gt;, so we want to avoid it.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;Instead, we&amp;rsquo;re going to use &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; to create a variable that is equal to &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;"truetruetrue"&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; if and only if we detect a &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt;.
This time, we&amp;rsquo;re using &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; as intended, to conditionally define variables.
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;div class="brush: nginx"&gt;
  &lt;pre&gt;&lt;code&gt;map $http_origin $cors_origin_header {
  hostnames;
  default "https://example.com";
  "https://example.com" "$http_origin";
  "https://www.example.com" "$http_origin";
}

map $http_access_control_request_headers $preflight_h {
  default "true";
  "" "false";
}
map $http_access_control_request_method $preflight_m {
  default "true";
  "" "false";
}
map $request_method $preflight {
  default "false";
  "OPTIONS" "${preflight_h}${preflight_m}true";
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;We set the value of &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;$preflight&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; to &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;"truetruetrue"&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; when we detect a (non-empty) &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers"&gt;&lt;span class="stt"&gt;Access-Control-Request-Headers&lt;/span&gt;&lt;/a&gt; header, a (non-empty) &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Method"&gt;&lt;span class="stt"&gt;Access-Control-Request-Method&lt;/span&gt;&lt;/a&gt;, and the request method is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS"&gt;&lt;span class="stt"&gt;OPTIONS&lt;/span&gt;&lt;/a&gt;.
We set the variables through string concatination to emulate boolean &lt;span class="stt"&gt;and&lt;/span&gt;, since &lt;span class="stt"&gt;nginx&lt;/span&gt; does not support nested conditions or boolean arithmetic.&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;To actually detect and process a &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt;, we add the following code in &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;location&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; context in the &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;server&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; on which you want to enable &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._cor%29"&gt;&lt;span class="techinside"&gt;CORS&lt;/span&gt;&lt;/a&gt;.
I add it in the &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; block of both my WebDAV and CalDAV &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;server&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; blocks.
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;div class="brush: nginx"&gt;
  &lt;pre&gt;&lt;code&gt;if ($preflight = "truetruetrue"){
   add_header "Access-Control-Allow-Origin" "$cors_origin_header";
   add_header "Access-Control-Allow-Headers" "$cors_allow_headers";
   add_header "Access-Control-Allow-Methods" "REPORT, PROPFIND, COPY, MOVE, MKCOL, CONNECT, DELETE, DONE, GET, HEAD, OPTIONS, PATCH, POST, PUT";
   add_header "Access-Control-Max-Age" 1728000;
   add_header "Content-Type" "text/plain charset=UTF-8";
   add_header "Content-Length" 0;
   return 204;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;Note that due to limitations on &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;add_header&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;, this &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; block &lt;span class="emph"&gt;must&lt;/span&gt; appear in &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;location&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; context.
Note that we also cannot move any &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;add_header&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; command outside the &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;.
The &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;add_header&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; commands are not executed in a sequential order, but all of them are "executed" simultaneously as a block at the current level.
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote class="refpara"&gt;
  &lt;blockquote class="refcolumn"&gt;
   &lt;blockquote class="refcontent"&gt;
    &lt;p&gt;See &lt;a href="http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header"&gt;&lt;span class="url"&gt;http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;Note also that this &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; &lt;span class="emph"&gt;must&lt;/span&gt; end in &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;204&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;.
This is part of the &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt; response (although some browsers will let you get away without it), and necessary for &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; to behave correctly, since &lt;a href="https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/"&gt;If is Evil&lt;/a&gt;.&lt;/div&gt;

&lt;p&gt;You can customize the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods"&gt;&lt;span class="stt"&gt;Access-Control-Allow-Methods&lt;/span&gt;&lt;/a&gt; header depending on the server and your app to provide the least privilege.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="SIntrapara"&gt;Finally, we add the headers for other cross-origin requests.
We add the following in any valid context, except the &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; body for the &lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight request&lt;/span&gt;&lt;/a&gt;.
I added them in &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;server&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; context.
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;div class="brush: nginx"&gt;
  &lt;pre&gt;&lt;code&gt;add_header "Access-Control-Allow-Origin" "$cors_origin_header" always;
add_header "Access-Control-Allow-Credentials" "true" always;
add_header "Access-Control-Expose-Headers" "$cors_expose_headers" always;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="SIntrapara"&gt;Note that the &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;always&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; argument is required for non-&lt;a class="techoutside" data-pltdoc="x" href="#%28tech._preflight._request%29"&gt;&lt;span class="techinside"&gt;preflight requests&lt;/span&gt;&lt;/a&gt;, since the HTTP response codes for successful requests will be variously 207, 200, and 304 (maybe others), and the &lt;span class="default"&gt;&lt;code class="highlight-inline"&gt;&lt;span class="k"&gt;add_header&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; does not actually add a header for responses with some of these status codes.
&lt;/div&gt;

&lt;div class="SIntrapara"&gt;
 &lt;blockquote class="refpara"&gt;
  &lt;blockquote class="refcolumn"&gt;
   &lt;blockquote class="refcontent"&gt;
    &lt;p&gt;See &lt;a href="http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header"&gt;&lt;span class="url"&gt;http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h1 class="heading"&gt;4
 &lt;tt&gt;&amp;nbsp;&lt;/tt&gt;&lt;a name="(part._.Conclusion_and_.Debugging)"&gt;&lt;/a&gt;Conclusion and Debugging&lt;span class="button-group"&gt;&lt;a class="heading-anchor" href="#(part._.Conclusion_and_.Debugging)" title="Link to here"&gt;🔗&lt;/a&gt;&lt;span style="visibility: hidden"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Now, if you look in the Network Monitor of your browser (Ctrl+Shift+E), and click "XHR", you should see some successful cross-origin requests from your web app.
If you see they&amp;rsquo;re being rejected, try anaylzing the request, and changing the above configurations with additional headers or safelisted origins.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">A Suitable Cutlery Tray</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2021/01/18/a-suitable-cutlery-tray/" />
  <id>urn:https-www-williamjbowman-com:-blog-2021-01-18-a-suitable-cutlery-tray</id>
  <published>2021-01-18T17:59:36Z</published>
  <updated>2021-01-18T17:59:36Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;&lt;em&gt;This post is a transcription of a thread that happened live on Twitter on June 30, 2019, in response to some anger at my lack of a cutlery tray. I was in a mood following a previous cutlery incident.&lt;/em&gt;&lt;/p&gt;
&lt;!-- more--&gt;

&lt;blockquote&gt;
 &lt;p&gt;IT NEEDS A TRAY&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;You&amp;rsquo;re right. The current state of this drawer is unacceptable. Sure, I can grab a knife, spoon, or fork with relative ease, and the rubberized mat makes cleaning the drawer simple. But look at those irregular lines. There is no order. This must be fixed!&lt;/p&gt;

&lt;p&gt;The problem I have is in finding a suitable tray. I have, on occasion, been called obsessive, but really I just live my life in the way that make me happy. I like each item that I own to meet that goal. I don&amp;rsquo;t just want a utilitarian cutlery tray; I want one that will spark joy.&lt;/p&gt;

&lt;p&gt;When I look at cutlery trays, the first criteria, obviously, is a perfect fit within the drawer. It must fit flushl edge-to-edge, at least to the left and right edges, and against the bottom edge. Against the top edge would be ideal, but I suppose I can live with extra top space.&lt;/p&gt;

&lt;p&gt;The height is also a concern. The side walls of the tray and of the dividers must come exactly to the height of the drawer. This, I&amp;rsquo;m sure, is obvious to you all.&lt;/p&gt;

&lt;p&gt;Next, the tray slots must divided evenly amongst the spoons, forks, and knives (in that order, of course, for obvious reasons).  Any drawer of cutlery would have equal numbers of each, and it would be unjust to have a tray inequality divided.&lt;/p&gt;

&lt;p&gt;At this point, most cutlery trays are already out of the running, and yet I have more (obvious and sensible) requirements. The tray must be made of wood. Plastic is abhorrent. You would not believe the difficulty in locating a wooden cutlery tray by itself.&lt;/p&gt;

&lt;p&gt;But one that meets all the other requirements? Impossible. I&amp;rsquo;ve looked. I&amp;rsquo;ve been to Amazon, to Bed Bath and Beyond, to TJ Max. They simply don&amp;rsquo;t exist. It&amp;rsquo;s like a conspiracy. My only recourse, I fear, is to design my own.&lt;/p&gt;

&lt;p&gt;I could, I suppose, start a company, whose sole purpose is to design the perfect cutlery tray. I could seek out designers and material engineers, source responsibly forested wood. Teak, ideally. I could find a way to construct it without the use of glue or staples or nails.&lt;/p&gt;

&lt;p&gt;This would probably not be sufficiently profitable to stay in business long, and I&amp;rsquo;m likely to move soon and need a new design. To keep the business afloat, I should diversify. Military contracting is always profitable; perhaps I could re-purpose my engineers.&lt;/p&gt;

&lt;p&gt;My team, experienced in perfect design, responsible materials and supply chain management, would be suited to completely dominate this new market. Soon, I would hold all military contracts, patents for unimaginable weapons&amp;mdash;because no one before had dared imagine.&lt;/p&gt;

&lt;p&gt;Using the proceeds of my new monopoly, I would quietly return to the cutlery market, taking over or putting out of business any company who dared manufacture &amp;ldquo;cutlery trays&amp;rdquo;&amp;hellip; an insult to the very idea&amp;hellip;&lt;/p&gt;

&lt;p&gt;This, I fear, would not satisfy me, though. Obviously, every cutlery drawer should come equipped with the perfect cutlery tray. I would have to move in to the interior design market. All drawers and cabinets would be manufactured according to my perfect ideal, my grand design.&lt;/p&gt;

&lt;p&gt;As I begin to corner this new market, the FTC becomes concerned at the grand and beautiful hegemony I bring to each new market, but I cannot let them stop me. I perform my biggest hostile take over yet: the United States of America. I naturally held on to my best weapons.&lt;/p&gt;

&lt;p&gt;I rename it to the Grand Hegemony of Perfect Cutlery Design, and shift the focus of the economy into the design and production of cutlery trays that suite my tastes. This destroys several Chinese companies dedicated to mass production of plastic trays, and sparks a trade war.&lt;/p&gt;

&lt;p&gt;As China is my main supplier of teak, this is a true threat to the Grand Hegemony. I am forced in to military action.&lt;/p&gt;

&lt;p&gt;While I expect a swift victory due to my superior design in weapons, I did not count on the effectiveness of Chinese corporate espionage, nor on the retaliatory strikes from Russia and North Korea. The nuclear fallout forces the remains of my government into underground bunkers.&lt;/p&gt;

&lt;p&gt;We eventually win. We will have complete control of the teak supply. Our cutlery tray empire is secure. The nuclear fallout will clear eventually. Until then, I have the perfect cutlery tray built in to my cutlery drawer to keep me at peace.&lt;/p&gt;</content></entry></feed>